NSURLConnection leak in Swift - ios

I've found several other articles about memory issues with NSURLConnection however none of them related to projects using ARC. My problem is that I make NSURLConnections every 0.5s (yes I know it would be better with sockets, but I don't have control over the API). When I open the debug inspector of xCode I could clearly see my used memory rising:
When I profile my application with instruments however - no leaks, no persistent storage across mark generations, simply nothing:
I've purposely decoupled all my other logic and created simple application to show my problem.
This is the main(and only) ViewController
import UIKit
class ViewController: UIViewController {
private var timer: NSTimer!
private var requests = [ServerRequest]()
override func viewDidAppear(animated: Bool)
{
self.timer = NSTimer(timeInterval: 0.5, target: self, selector: "refresh", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
}
#objc private func refresh()
{
let urlRequest = NSURLRequest(URL: NSURL(string: "https://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=stackoverflow")!)
let serverRequest = ServerRequest(request: urlRequest){
[unowned self] result, error, request in
println("yaba daba duu")
self.requests.removeAll(keepCapacity: false)
}
requests.append(serverRequest)
serverRequest.send()
}
}
And here's my async connection delegate:
import Foundation
class ServerRequest: NSObject
{
private var request: NSURLRequest!
typealias completionType = (NSData?, NSError?, ServerRequest) -> ()
private var completion: completionType!
private var receivedData: NSMutableData?
private var connection: NSURLConnection?
init(request: NSURLRequest, completion: (NSData?, NSError?, ServerRequest) -> ())
{
super.init()
self.request = request
self.completion = completion
self.connection = NSURLConnection(request: self.request, delegate: self, startImmediately:false)
//this line will help connection is fired even while tere are touch events
self.connection?.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
NSURLCache.sharedURLCache().removeAllCachedResponses()
}
func send()
{
receivedData = NSMutableData()
self.connection?.start()
}
func abort()
{
self.connection?.cancel()
}
}
extension ServerRequest: NSURLConnectionDataDelegate, NSURLConnectionDelegate
{
func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse)
{
self.receivedData?.length = 0
}
func connection(connection: NSURLConnection, didReceiveData data: NSData)
{
self.receivedData?.appendData(data)
}
func connection(connection: NSURLConnection, didFailWithError error: NSError)
{
self.connection = nil
self.completion(nil, error, self)
}
func connectionDidFinishLoading(connection: NSURLConnection)
{
self.connection = nil
self.completion(receivedData, nil, self)
}
//MARK: https specific(canAuthenticateAgainstProtectionSpace is depraceted first in iOS 8)
func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool
{
return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
}
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge)
{
challenge.sender.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust), forAuthenticationChallenge: challenge)
challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
}
func connection(connection: NSURLConnection, willCacheResponse cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse? {
return nil
}
}
Please note that I need to connect to https server, so I need corresponding delegate methods. Also I've implemented cache methods because of some suggestions in SO that caching responses in NSURLConnection may cause my issues. Finally request is scheduled in "NSRunLoopCommonModes" mode because I need it alive while scrolling(although removing this line doesn't affect the issue anyway).
UPDATE
I've jut tried even without custom class with delegate and the result is pretty much the same. Just copy-paste following:
import UIKit
class ViewController: UIViewController {
private var timer: NSTimer!
override func viewDidAppear(animated: Bool)
{
self.timer = NSTimer(timeInterval: 0.5, target: self, selector: "refresh", userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(self.timer, forMode: NSRunLoopCommonModes)
}
#objc private func refresh()
{
let urlRequest = NSURLRequest(URL: NSURL(string: "https://api.stackexchange.com/2.2/questions?order=desc&sort=activity&site=stackoverflow")!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue())
{
response, data, error in
println("yaba daba duu")
}
}
}
And my memory pressure is again rising:

Related

IOS swift Web Socket SRWebSocket set response timeout

I am using SRWebSocket/SocketRocket library in my app I am unable to set response timeout for it . I want to show a message if socket does not receive any data after few seconds
Following is my code
socketRocket = SRWebSocket(url: URL(string: streamUrl)!)
socketRocket?.delegate = self
socketRocket?.open()
Using following callback methods as well
func webSocketDidOpen(_ webSocket: SRWebSocket!) {
print("webSocketDidOpen")
showTableView()
}
func webSocket(_ webSocket: SRWebSocket!, didCloseWithCode code: Int, reason: String!, wasClean: Bool) {
getConversationId()
}
func webSocket(_ webSocket: SRWebSocket!, didFailWithError error: Error!) {
print("didFailWithError\(error)")
showLErrorView()
}
func webSocket(_ webSocket: SRWebSocket!, didReceiveMessage message: Any!) {
}
here is link to library
https://github.com/facebook/SocketRocket
If you want to display some message when you don't get a response you can use a Timer, the basics it looks like that:
var timer: Timer?
var responseTimeout: TimeInterval = 15
func startTimer() {
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: responseTimeout, repeats: false, block: {[weak self] timer in
self?.onResponseTimeout()
})
}
func onResponseTimeout() {
print("Didn't get response")
}
func webSocket(_ webSocket: SRWebSocket!, didReceiveMessage message: Any!) {
print(message)
timer?.invalidate() //invalidate timer when you get a message
}
and then you can call startTimer() when it is needed i.e. when the socket is opened:
func webSocketDidOpen(_ webSocket: SRWebSocket!) {
print("webSocketDidOpen")
showTableView()
startTimer()
}
or after you send a message:
socketRocket?.send(message)
startTimer()
If you also want to set a timeout for connection (it is something separate from resopone timout), you can use URLRequest instead of URL:
let request = URLRequest(url: url, timeoutInterval: 30) //it is 30 sec connection timeout
socketRocket = SRWebSocket(urlRequest: request)
socketRocket?.delegate = self
socketRocket?.open()
Full class that supports both connection and response timeout:
import Foundation
import SocketRocket
class WebSocket: NSObject, SRWebSocketDelegate {
var socketRocket: SRWebSocket?
var timer: Timer?
var responseTimeout: TimeInterval = 15
func open(url: URL, connectionTimeout: TimeInterval = 10) {
let request = URLRequest(url: url, timeoutInterval: connectionTimeout)
socketRocket = SRWebSocket(urlRequest: request)
socketRocket?.delegate = self
socketRocket?.open()
}
func send(message: String) {
socketRocket?.send(message)
startTimer()
}
func startTimer() {
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: responseTimeout, repeats: false, block: {[weak self] timer in
self?.onResponseTimeout()
})
}
func onResponseTimeout() {
print("Didn't get response")
}
func webSocketDidOpen(_ webSocket: SRWebSocket!) {
print("webSocketDidOpen")
startTimer()
}
func webSocket(_ webSocket: SRWebSocket!, didCloseWithCode code: Int, reason: String!, wasClean: Bool) {
print("closed with code: \(code), reason: \(reason), wasClean: \(wasClean)")
timer?.invalidate()
}
func webSocket(_ webSocket: SRWebSocket!, didFailWithError error: Error!) {
print("didFailWithError\(error)")
timer?.invalidate()
}
func webSocket(_ webSocket: SRWebSocket!, didReceiveMessage message: Any!) {
print(message)
timer?.invalidate()
}
}

Custom NSURLProtocol with NSURLSession

I'm trying to implement this tutorial which implements a custom NSURLProtocol with NSURLConnection.
https://www.raywenderlich.com/76735/using-nsurlprotocol-swift
It works as expected, but now that NSURLConnection is deprecated in iOS9, I'm trying to convert it to NSURLSession.
Unfortunatly it didn't work.
I'm loading a website in uiwebview, if I use NSURLConnection it loads and everything work as expected, all http requests from the webview is captured, but not when using NSURLSession.
Any help is appreciated.
here is my code
import UIKit
class MyProtocol: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate, NSURLSessionDelegate {
//var connection: NSURLConnection!
var mutableData: NSMutableData!
var response: NSURLResponse!
var dataSession: NSURLSessionDataTask!
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if NSURLProtocol.propertyForKey("MyURLProtocolHandledKey", inRequest: request) != nil {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override class func requestIsCacheEquivalent(aRequest: NSURLRequest,
toRequest bRequest: NSURLRequest) -> Bool {
return super.requestIsCacheEquivalent(aRequest, toRequest:bRequest)
}
override func startLoading() {
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey", inRequest: newRequest)
self.dataSession = NSURLSession.sharedSession().dataTaskWithRequest(newRequest)
dataSession.resume()
self.mutableData = NSMutableData()
}
override func stopLoading() {
print("Data task stop")
self.dataSession.cancel()
self.mutableData = nil
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.response = response
self.mutableData = NSMutableData()
print(mutableData)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.client?.URLProtocol(self, didLoadData: data)
self.mutableData.appendData(data)
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if (error == nil)
{
self.client!.URLProtocolDidFinishLoading(self)
self.saveCachedResponse()
}
else
{
self.client?.URLProtocol(self, didFailWithError: error!)
}
}
func saveCachedResponse () {
let timeStamp = NSDate()
let urlString = self.request.URL?.absoluteString
let dataString = NSString(data: self.mutableData, encoding: NSUTF8StringEncoding) as NSString?
print("TiemStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n")
}
}
I've solved it.
Here is the code if anyone needs it.
import Foundation
class MyProtocol1: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate
{
private var dataTask:NSURLSessionDataTask?
private var urlResponse:NSURLResponse?
private var receivedData:NSMutableData?
class var CustomKey:String {
return "myCustomKey"
}
// MARK: NSURLProtocol
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if (NSURLProtocol.propertyForKey(MyProtocol1.CustomKey, inRequest: request) != nil) {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override func startLoading() {
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty("true", forKey: MyProtocol1.CustomKey, inRequest: newRequest)
let defaultConfigObj = NSURLSessionConfiguration.defaultSessionConfiguration()
let defaultSession = NSURLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil)
self.dataTask = defaultSession.dataTaskWithRequest(newRequest)
self.dataTask!.resume()
}
override func stopLoading() {
self.dataTask?.cancel()
self.dataTask = nil
self.receivedData = nil
self.urlResponse = nil
}
// MARK: NSURLSessionDataDelegate
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask,
didReceiveResponse response: NSURLResponse,
completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.urlResponse = response
self.receivedData = NSMutableData()
completionHandler(.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.client?.URLProtocol(self, didLoadData: data)
self.receivedData?.appendData(data)
}
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil && error!.code != NSURLErrorCancelled {
self.client?.URLProtocol(self, didFailWithError: error!)
} else {
saveCachedResponse()
self.client?.URLProtocolDidFinishLoading(self)
}
}
// MARK: Private methods
/**
Do whatever with the data here
*/
func saveCachedResponse () {
let timeStamp = NSDate()
let urlString = self.request.URL?.absoluteString
let dataString = NSString(data: self.receivedData!, encoding: NSUTF8StringEncoding) as NSString?
print("TimeStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n")
}
}
Swift 3 version:
// CustomURLProtocol.swift
class CustomURLProtocol: URLProtocol, URLSessionDataDelegate, URLSessionTaskDelegate {
private var dataTask: URLSessionDataTask?
private var urlResponse: URLResponse?
private var receivedData: NSMutableData?
class var CustomHeaderSet: String {
return "CustomHeaderSet"
}
// MARK: NSURLProtocol
override class func canInit(with request: URLRequest) -> Bool {
guard let host = request.url?.host, host == "your domain.com" else {
return false
}
if (URLProtocol.property(forKey: CustomURLProtocol.CustomHeaderSet, in: request as URLRequest) != nil) {
return false
}
return true
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
override func startLoading() {
let mutableRequest = NSMutableURLRequest.init(url: self.request.url!, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 240.0)//self.request as! NSMutableURLRequest
//Add User Agent
var userAgentValueString = "myApp"
mutableRequest.setValue(userAgentValueString, forHTTPHeaderField: "User-Agent")
print(mutableRequest.allHTTPHeaderFields ?? "")
URLProtocol.setProperty("true", forKey: CustomURLProtocol.CustomHeaderSet, in: mutableRequest)
let defaultConfigObj = URLSessionConfiguration.default
let defaultSession = URLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil)
self.dataTask = defaultSession.dataTask(with: mutableRequest as URLRequest)
self.dataTask!.resume()
}
override func stopLoading() {
self.dataTask?.cancel()
self.dataTask = nil
self.receivedData = nil
self.urlResponse = nil
}
// MARK: NSURLSessionDataDelegate
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask,
didReceive response: URLResponse,
completionHandler: #escaping (URLSession.ResponseDisposition) -> Void) {
self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
self.urlResponse = response
self.receivedData = NSMutableData()
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.client?.urlProtocol(self, didLoad: data as Data)
self.receivedData?.append(data as Data)
}
// MARK: NSURLSessionTaskDelegate
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if error != nil { //&& error.code != NSURLErrorCancelled {
self.client?.urlProtocol(self, didFailWithError: error!)
} else {
//saveCachedResponse()
self.client?.urlProtocolDidFinishLoading(self)
}
}
}
The problem you are having with your code is that you are using the the NSURLSession.sharedSession to contain your data task. By using the shared session, you are not able to change the session delegate so none of your delegate routines are going to be invoked.
You will need to create a custom session with your protocol established as the delegate for the session. Then, when asked to start loading you can create a data task in that session.
From the documentation of URLSession:
Important
The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you don’t invalidate the session, your app leaks memory until it exits.
Also:
Note
Be careful to not create more sessions than you need. For example, if you have several parts of your app that need a similarly configured session, create one session and share it among them.
So I would move the creation of the URLSession from the startLoading method to the URLProtocol subclass initializer:
class MyURLProtocol: URLProtocol, URLSessionDataDelegate,URLSessionTaskDelegate {
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
super.init(request: request, cachedResponse: cachedResponse, client: client)
defaultSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
private var defaultSession: URLSession?

Swift : fatal error: unexpectedly found nil while unwrapping an Optional value

I am trying to access REST web service, but its giving this - fatal error: unexpectedly found nil while unwrapping an Optional value.
Below is the code - So i have this RESTParser class -
protocol RESTParserDelegate
{
func getReceiveData(data:NSMutableData,sender:RESTParser)
}
class RESTParser: NSObject, NSURLConnectionDataDelegate
{
var receiveData: NSMutableData!
var requestConnection: NSURLConnection!
var delegate: RESTParserDelegate?
func receiveData(resData:NSMutableData){
receiveData = resData
}
func requestConnection(reqConn:NSURLConnection){
requestConnection = reqConn
}
func httpRequest(myRequest:NSMutableURLRequest){
self.requestConnection = NSURLConnection(request: myRequest, delegate: self)
}
// NSURLConnectionDataDelegate methods
func connection(connection: NSURLConnection, didReceiveData data: NSData){
self.receiveData?.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection){
self.delegate?.getReceiveData(receiveData, sender: self) // error # this line
self.delegate = nil
self.receiveData = nil
self.requestConnection = nil
}
func connection(connection: NSURLConnection, didFailWithError error: NSError){
NSLog("Failed with error - %# ",error.localizedDescription)
}
func parseData(data:NSMutableData){
}
}
Error is # this line - self.delegate?.getReceiveData(receiveData, sender: self) in connectionDidFinishLoading function.
And calling this from my project details view controller - but as soon as getReceiveData method is called this fatal error is coming.
class ProjectDetails_tab: UIViewController, RESTParserDelegate{
override func viewDidLoad() {
super.viewDidLoad();
//var projectData: NSDictionary = [String:String]()
var url:String = "http://domianName.com"
var nsURL = NSURL(string: url)
var createrequest: NSMutableURLRequest = NSMutableURLRequest(URL: nsURL!)
createrequest.HTTPMethod = "GET"
var rest = RESTParser()
rest.delegate=self
rest.httpRequest(createrequest)
}
func getReceiveData(data:NSMutableData,sender:RESTParser){
}
}
Not clear that fatal error with which line of your code. But you can recheck your delegate object or:
// NSURLConnectionDataDelegate methods
func connection(didReceiveResponse: NSURLConnection, didReceiveResponse response: NSURLResponse) {
// Recieved a new request, clear out the data object
self.receiveData = NSMutableData()
}
func connection(connection: NSURLConnection, didReceiveData data: NSData){
self.receiveData?.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
// Request complete, self.data should now hold the resulting info
}

NSURLConnection Delegate Methods Not Called In Generic Class

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.)
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)
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().

Swift access REST Web Service failed

Following this tutorial tutorial
I'm able to invoke my web service which released base on springMVC, however the connectionDidFinishLoading does not seem to fire, and there isn't any error message either.
Here is my code.
import Foundation
class Requestor {
var data: NSMutableData = NSMutableData();
func connect() {
var urlParth = "http://localhost:8080/webservice/request/public/key";
var url = NSURL(string: urlParth);
var request:NSURLRequest = NSURLRequest(URL: url!);
var connection = NSURLConnection(request: request, delegate: self, startImmediately: false);
connection?.start();
}
//NSURLConnection Connection failed
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Failed with error:\(error.localizedDescription)")
}
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
println("didReceiveResponse")
}
func connection(connection: NSURLConnection!, didReceiveData conData: NSData!) {
self.data.appendData(conData)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
println(self.data)
println("did");
}
}
here is my service code:
#RestController
#RequestMapping("/webservice")
public class PublicService extends Service {
#RequestMapping("/request/public/key")
public String requestPublicKey() {
String result = String.format("{\"code\":\"%s\",\"publicKey\":\"%s\"}", "200", Base64.encodeBase64String(rasFactory.getPublicKeyInByte()));
return result;
}
}
I debugged for a quite long time by putting a break point in service, seems I can reach service, but after service returns the result, iOS side doesn't have any reaction.
Is there anything wrong with my code?
Thanks.

Resources