NSURLConnection Delegate Methods Not Called In Generic Class

匿名 (未验证) 提交于 2019-12-03 09:18:39

问题:

I have a test class that tries to reach to google with a NSURLConnection. If I try to make it generic, the NSURLConnectionDataDelegate methods are never called.

class Remote<T: NSObject>: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDelegate { //class Remote: NSObject, NSURLConnectionDelegate, NSURLConnectionDataDelegate {      var data = NSMutableData()      func connect(query:NSString) {         var url =  NSURL(string:"http://www.google.com")!         var request = NSURLRequest(URL: url)         var conn = NSURLConnection(request: request, delegate: self, startImmediately: true)     }       func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {         LF.log("didReceiveResponse")     }      func connection(connection: NSURLConnection!, didReceiveData conData: NSData!) {         LF.log("didReceiveData")         self.data.appendData(conData)     }      func connectionDidFinishLoading(connection: NSURLConnection!) {         LF.log("didFinished")         //println(self.data)     }       deinit {         println("deiniting")     } }

To test it (comment/uncomment the first/second line to compare):

    let remote = Remote<NSObject>()     //let remote = Remote()     remote.connect("")

Any idea please?

Update1: to answer comment 1, it's a REST client that handles network connection and parsing for you. I'd write a blog about this later (since it's still under development), but to give you the idea here's some demo code from my project:

        let client = ICRestClient<ICCategoryModel>(api:IC.api.category_list)         client.func_array = {             (results: [ICCategoryModel]?, error: NSError?) -> Void in             block!(results, error)         }         client.execute()

And ICCategoryModel is like:

class ICSubCategoryModel: ICModel {     var name: String?     var category_id: Int = 0 }

The idea is that you pass the API URL in, you get an array (or error) with some reflected objects instead of Dictionary. It's from my LSwift library and supports various authentications methods (buildin-parameters, cookie, header, authentication challenge etc.)

回答1:

One of the problem is that I can't access the delegate object of NSURLConnection. I came up with a solution by creating another RemoteDelegate class, which is not generic type, and set it as the delegate of "conn". It works for now but it's just a work-around, and I'm still looking for the answer to the question.

My delegate class:

class LRestConnectionDelegate: NSObject {      var func_done: ((NSURLResponse?, NSData!, NSError!) -> Void)?     var credential: NSURLCredential?     var response: NSURLResponse?     var data: NSMutableData = NSMutableData()      func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {         if challenge.previousFailureCount > 0 {             challenge.sender.cancelAuthenticationChallenge(challenge)         } else if let credential = credential {             challenge.sender.useCredential(credential, forAuthenticationChallenge:challenge)         } else {             LF.log("REST connection will challenge", connection)         }     }     func connection(connection: NSURLConnection, didReceiveResponse a_response: NSURLResponse) {         //LF.log("CONNECTION response", response)         response = a_response     }     func connection(connection: NSURLConnection, didReceiveData data_received: NSData) {         //LF.log("CONNECTION data", data.length)         data.appendData(data_received)     }     func connectionDidFinishLoading(connection: NSURLConnection) {         //LF.log("CONNECTION finished", connection)         if func_done != nil {             func_done!(response, data, nil)         }     }     func connection(connection: NSURLConnection, didFailWithError error: NSError) {         //LF.log("CONNECTION failed", error)         if let func_done = func_done {             func_done(response, nil, error)         }     }     deinit {         //LF.log("DELEGATE deinit", self)     } }

And this works in class LRestClient<T: LFModel>:

        let delegate = LRestConnectionDelegate()         delegate.credential = credential         delegate.func_done = func_done         connection = NSURLConnection(request:request, delegate:delegate, startImmediately:true)


回答2:

Because you're using NSURLConnection synchronously, you have to schedule the operation in the main run loop. Add the following code to the end of your connect function:

conn?.scheduleInRunLoop(NSRunLoop.currentRunLoop, forMode: NSDefaultRunLoopMode)

Alternatively, set startImmediately to NO and call conn?.start().



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!