在Objective-C中创建NSURLSessionDownloadTask
:
NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithURL:[NSURL URLWithString:@"google.com"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if (task.state == NSURLSessionTaskStateCompleted) {
// Do things
}
}];
[task resume];
我可以在完成模块中访问我正在创建的任务task
,也没有问题。
然而,在Swift中,如果我尝试同样的事情:
let URL = NSURL(string: "google.com")
let task = NSURLSession.sharedSession().downloadTaskWithURL(URL, completionHandler: { location, response, error in
if task.state == .Completed {
// Do things
}
}
task.resume()
我可以错误地说“变量正在其自己的初始值中使用”。
我该如何规避这个?
答案 0 :(得分:3)
更新回答 我现在意识到我没有仔细阅读你的代码。您没有将闭包传递给初始化器,而是传递给方法。在将闭包传递给初始化程序时,我最初编写的内容仍然有效,但不是在你的情况下。
你的问题很相似。
您有一个task
变量,该变量使用函数的返回值进行初始化。您将闭包传递给函数,并在闭包内引用task
变量。
编译器不知道关闭何时执行(至少我认为它不会检查它,它是downloadTaskWithURL()
内部实现细节) - 它&#39 ;它可能在函数体中执行(而不是将它存储在属性中并在以后执行)。如果闭包是在函数体中执行的,那么当它尚未被赋值时它将访问task
变量(因为该函数仍在执行)。
如果有一种方法让编译器知道闭包没有在函数体中执行,那么编译器就可以处理这种情况。但斯威夫特并没有实现这样的目标。
结论:我很感激编译器为此抛出一个错误,因为否则我会期待一个运行时异常 - 尽管可能不是在你的特定情况下(因为后面会执行闭包)。
原始回答
正如您可能知道的那样,在所有类/结构属性都已正确初始化并且已调用基本初始化程序(对于继承的类)之前,swift self
不可用
您正在将闭包传递给类初始化程序 - 编译器无法确定何时执行闭包,因此闭包本身不能包含对self
的任何(直接或间接)引用。
在您的情况下,task
是要实例化的变量,因此当您在闭包中使用它时,就像您使用self
一样。这是不允许的,所以你有错误。
在Objective C中没有发生同样的事情,因为初始化器中没有这样的约束。
但请注意,从概念上讲,你所做的并不是一个好习惯。您正在读取之前的类实例的属性已正确初始化。要确定调用的状态,您应该依赖传递给闭包的参数,理想情况下应该提供您需要的所有信息。
答案 1 :(得分:0)
您的task.state尚未初始化但有一些价值。您正在尝试在类实例初始化之前读取它们的属性。
答案 2 :(得分:0)
现在,我能够解决这个问题的唯一方法是在初始化程序之前声明变量,然后在闭包内部访问它:
let URL = NSURL(string: "google.com")
var task: NSURLSessionTask?
task = NSURLSession.sharedSession().downloadTaskWithURL(URL, completionHandler: { location, response, error in
if task?.state == .Completed {
// Do things
}
}
task?.resume()