如何在 NSURLSession 请求的处理程序中切换视图

How to switch views in the handler of an NSURLSession Request

我有一个登录视图控制器和一个其他视图控制器。我想做的是:当用户点击登录时,它会将他们的凭据发送到远程服务器。远程服务器 returns 指示凭据是否正确的响应,如果它们是正确的,应用程序将重定向到其他视图控制器。

下面的代码在调用 .performSegueWithIdentifier 时崩溃。

崩溃给出错误代码 EXC_BAD_ACCESS(code=1, address=0xbbadbeef)

问题:这样做的快捷方式是什么?

var request = NSMutableURLRequest(URL: NSURL(string: "http://url.to/my/login/handler")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"

//user initialized earlier
bodyData = "email=\(user.username)&password=\(user.password)"

request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);

var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
    // check that log in was successful by looking in 'response' arg
    // if login was successful
    self.performSegueWithIdentifier("SegueToOtherController", sender: self)
    }
task.resume()
}

如果崩溃,您应该分享崩溃的详细信息以确定原因。可能的问题包括它没有找到该标识符作为 "storyboard id" 从当前视图控制器到下一个场景的序列。但具体的错误,不能不详细说。

话虽如此,这里还有一个问题:完成块可能不会运行在主线程上,但所有UI更新必须发生在主线程上。因此,请确保将其分派回主队列,例如

let request = NSMutableURLRequest(URL: NSURL(string: "http://url.to/my/login/handler")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"

//user initialized earlier
bodyData = "email=\(user.username)&password=\(user.password)"

request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);

let task = session.dataTaskWithRequest(request) {data, response, error in
    // check that log in was successful by looking in 'response' arg
    // if login was successful
    dispatch_async(dispatch_get_main_queue()) {
        self.performSegueWithIdentifier("SegueToOtherController", sender: self)
    }
}
task.resume()

请注意,我还将所有这些 var 引用更改为 let(作为一般规则,尽可能使用 let)。此外,我还没有在这里解决它,但你真的应该转义 usernamepassword 属性。例如,如果密码包含任何保留字符,如 +&,这将失败。有很多方法可以做到这一点,例如类似于此处讨论的方法: or 。