2017-04-12 8 views
0

HTTPリクエストを行うコマンドラインSwiftアプリケーションを作成しようとしています。補足として、アプリケーションのrun funcにセッションを提供して、コードを単体テストする依存関係注入を使用できるようにしたいとします(それで私が定義したプロトコル)。スワイプコードでクラッシュする:「インスタンスに送信されたセレクタが認識されません」

「インスタンスに送信されたセレクタが認識されません」とクラッシュします。これは何を意味するのでしょうか?

// 
// main.swift 
// MockIt 
// 
// 

import Foundation 

public protocol URLSessionProtocol { 
    func synchronousDataTask(_ url: URL) -> (Data?, URLResponse?, Error?) 
} 

class MyUrlSession : URLSession, URLSessionProtocol { 

    func synchronousDataTask(_ url: URL) -> (Data?, URLResponse?, Error?) { 
     var data: Data? 
     var response: URLResponse? 
     var error: Error? 

     let semaphore = DispatchSemaphore(value: 0) 

     let dataTask = self.dataTask(with: url) { 
      data = $0 
      response = $1 
      error = $2 

      semaphore.signal() 
     } 
     dataTask.resume() 

     _ = semaphore.wait(timeout: .distantFuture) 

     return (data, response, error) 
    } 

} 

class MyModule { 
    func run(_ session: URLSessionProtocol, _ urlString: String) { 
     let url = URL(string: urlString) 
     let (_, response, _) = 
      session.synchronousDataTask(url!) 
     print(response!) 
    } 
} 


MyModule().run(MyUrlSession(), "https://myapiendpoint.com") 

フルクラッシュはここにある:それは重要な場合

2017-04-12 11:29:07.930076 MockIt[33267:1871173] -[MockIt.MyUrlSession dataTaskForRequest:completion:]: unrecognized selector sent to instance 0x100a043d0 
2017-04-12 11:29:07.933897 MockIt[33267:1871173] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MockIt.MyUrlSession dataTaskForRequest:completion:]: unrecognized selector sent to instance 0x100a043d0' 
*** First throw call stack: 
(
    0 CoreFoundation      0x00007fff785dfe7b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x00007fff8d1c0cad objc_exception_throw + 48 
    2 CoreFoundation      0x00007fff78661cb4 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132 
    3 CoreFoundation      0x00007fff78551fb5 ___forwarding___ + 1061 
    4 CoreFoundation      0x00007fff78551b08 _CF_forwarding_prep_0 + 120 
    5 MockIt        0x000000010000177d _TFC6MockIt12MyUrlSession19synchronousDataTaskfV10Foundation3URLTGSqVS1_4Data_GSqCSo11URLResponse_GSqPs5Error___ + 477 
    6 MockIt        0x0000000100001bf8 _TTWC6MockIt12MyUrlSessionS_18URLSessionProtocolS_FS1_19synchronousDataTaskfV10Foundation3URLTGSqVS2_4Data_GSqCSo11URLResponse_GSqPs5Error___ + 72 
    7 MockIt        0x0000000100001d1d _TFC6MockIt8MyModule3runfTPS_18URLSessionProtocol_SS_T_ + 253 
    8 MockIt        0x0000000100001584 main + 116 
    9 libdyld.dylib      0x00007fff8daa4255 start + 1 
    10 ???         0x0000000000000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 
(lldb) 

わからないが、これは私のアプリディレクトリの一般的な構造である:

$ tree -L 2 
. 
├── DerivedData 
│   ├── Build 
│   ├── MockIt 
│   └── ModuleCache 
├── MockIt 
├── MockIt-Bridging-Header.h 
├── MockIt.xcodeproj 
│   ├── project.pbxproj 
│   ├── project.xcworkspace 
│   └── xcuserdata 
├── MockItTest 
│   ├── Info.plist 
│   └── MockItTest.swift 
└── main.swift 

答えて

1

URLSessionをするように設計されていませんサブクラス化する。

あなたが見ている問題は、サブクラスURLSessionを完全に初期化していないという事実に起因すると思います。 URLSessioninit(configuration:)経由で少なくとも設定オブジェクトで初期化されることを意味するときは、init()を呼び出しています。

これらの初期化子は、継承できないと特別にマークされているため、サブクラスから呼び出すことはできません。

読み取り専用であるため、構成プロパティに自分で割り当てることはできません。

これを回避するには、プロパティをオーバーライドすることができますが、ほとんど確実にサブクラス化しない方が良いでしょう。URLSession代わりにこれをエクステンションとしてやってみましたか?

さらに詳しい情報はthis questionです。

関連する問題