var first_name = ""
func problemFunc() {
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
first_name = fbGraphUserDict["first_name"] as NSString
println(first_name)
}
}
}
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc() // error is here
}
})
This code is inside an @Ibaction button. I cannot build because the call to problemFunc() triggers the error message in the title of this post. If I move the first_name var definition inside the problemFunc it will work ok. But I need it out, because another function will need to access its value. I'm really not sure at what causes this problem, if you have a clue, please help.
此代码位于@Ibaction按钮内。我无法构建,因为对problemFunc()的调用会触发此帖子标题中的错误消息。如果我在problemFunc中移动first_name var定义,它将正常工作。但是我需要它,因为另一个函数需要访问它的值。我真的不确定导致这个问题的原因,如果你有线索,请帮忙。
3 个解决方案
#1
27
Use a closure instead of a function:
使用闭包而不是函数:
var first_name = ""
let problemFunc = { () -> () in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
first_name = fbGraphUserDict["first_name"] as NSString
println(first_name)
}
}
}
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc() // error is here
}
})
#2
11
Here are the basic principles in play: (from Apple's docs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103)
以下是基本原则:(来自Apple的文档:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11 -ID103)
"Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
“函数中引入的全局函数和嵌套函数实际上是闭包的特例。闭包采用以下三种形式之一:
- Global functions are closures that have a name and do not capture any values.
- 全局函数是具有名称但不捕获任何值的闭包。
- Nested functions are closures that have a name and can capture values from their enclosing function.
- 嵌套函数是具有名称的闭包,可以从其封闭函数中捕获值。
- Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context."
- Closure表达式是一种未命名的闭包,用轻量级语法编写,可以从周围的上下文中捕获值。“
ie this is ok
即没关系
func someFunc() {
func nestFunc() {}
}
but this is not
但事实并非如此
func someFunc() {
func nestFunc() {
func nestedFunc2() { }
}
}
If you look at this in Xcode the third function (func nestedFunc2) will give you the error "Cannot reference a local function with capture from another local function"
如果你在Xcode中看到这个,第三个函数(func nestedFunc2)会给你错误“不能从另一个本地函数中捕获一个本地函数”
The top function (func someFunc) is a global scope function and those work like regular functions/methods.
top函数(func someFunc)是一个全局范围函数,它们像常规函数/方法一样工作。
The second function (func nestFunc) is a nested function which is a named closure one level deep that can capture the scope of its parent global function.
第二个函数(func nestFunc)是一个嵌套函数,它是一个深度的命名闭包,可以捕获其父全局函数的范围。
Nested functions, can capture the scope of a global function but not the scope of another nested function.
嵌套函数可以捕获全局函数的范围,但不能捕获另一个嵌套函数的范围。
That's why we need a closure i.e.
这就是我们需要关闭的原因,即
func someFunc() {
func nestFunc() {
let strictClosure = { () -> () in
//this is where you write the code
}
}
}
#3
2
@fluidsonic answer should solve the problem. However note that you're doing some spaghetti code, because you are modifying a variable captured by a closure, and executed in the context of another function. That's hard to track if you need to debug, and more generally hard to follow when and how that variable is modified.
@fluidsonic答案应该解决问题。但请注意,您正在执行一些意大利面条代码,因为您正在修改由闭包捕获的变量,并在另一个函数的上下文中执行。如果你需要调试那么很难跟踪,更常见的是难以跟踪修改变量的时间和方式。
A more linear and better readable flow is to define problemFunc
as a function taking a function as parameter, and calling that function rather than directly setting the value in the first_name
variable:
更线性和更易读的流程是将problemFunc定义为将函数作为参数并调用该函数而不是直接设置first_name变量中的值的函数:
let problemFunc = { (callback: (String -> Void) -> ()) in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
let first_name = fbGraphUserDict["first_name"] as NSString
callback(first_name) // << here you call the callback passing the `first_name` local variable
println(first_name)
}
}
}
and do the actual assignment to first_name
in a closure you define when calling problemFunc
:
并在调用problemFunc时定义的闭包中对first_name进行实际赋值:
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc { (name: String) -> Void in
first_name = name
}
}
})
#1
27
Use a closure instead of a function:
使用闭包而不是函数:
var first_name = ""
let problemFunc = { () -> () in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
first_name = fbGraphUserDict["first_name"] as NSString
println(first_name)
}
}
}
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc() // error is here
}
})
#2
11
Here are the basic principles in play: (from Apple's docs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103)
以下是基本原则:(来自Apple的文档:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11 -ID103)
"Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
“函数中引入的全局函数和嵌套函数实际上是闭包的特例。闭包采用以下三种形式之一:
- Global functions are closures that have a name and do not capture any values.
- 全局函数是具有名称但不捕获任何值的闭包。
- Nested functions are closures that have a name and can capture values from their enclosing function.
- 嵌套函数是具有名称的闭包,可以从其封闭函数中捕获值。
- Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context."
- Closure表达式是一种未命名的闭包,用轻量级语法编写,可以从周围的上下文中捕获值。“
ie this is ok
即没关系
func someFunc() {
func nestFunc() {}
}
but this is not
但事实并非如此
func someFunc() {
func nestFunc() {
func nestedFunc2() { }
}
}
If you look at this in Xcode the third function (func nestedFunc2) will give you the error "Cannot reference a local function with capture from another local function"
如果你在Xcode中看到这个,第三个函数(func nestedFunc2)会给你错误“不能从另一个本地函数中捕获一个本地函数”
The top function (func someFunc) is a global scope function and those work like regular functions/methods.
top函数(func someFunc)是一个全局范围函数,它们像常规函数/方法一样工作。
The second function (func nestFunc) is a nested function which is a named closure one level deep that can capture the scope of its parent global function.
第二个函数(func nestFunc)是一个嵌套函数,它是一个深度的命名闭包,可以捕获其父全局函数的范围。
Nested functions, can capture the scope of a global function but not the scope of another nested function.
嵌套函数可以捕获全局函数的范围,但不能捕获另一个嵌套函数的范围。
That's why we need a closure i.e.
这就是我们需要关闭的原因,即
func someFunc() {
func nestFunc() {
let strictClosure = { () -> () in
//this is where you write the code
}
}
}
#3
2
@fluidsonic answer should solve the problem. However note that you're doing some spaghetti code, because you are modifying a variable captured by a closure, and executed in the context of another function. That's hard to track if you need to debug, and more generally hard to follow when and how that variable is modified.
@fluidsonic答案应该解决问题。但请注意,您正在执行一些意大利面条代码,因为您正在修改由闭包捕获的变量,并在另一个函数的上下文中执行。如果你需要调试那么很难跟踪,更常见的是难以跟踪修改变量的时间和方式。
A more linear and better readable flow is to define problemFunc
as a function taking a function as parameter, and calling that function rather than directly setting the value in the first_name
variable:
更线性和更易读的流程是将problemFunc定义为将函数作为参数并调用该函数而不是直接设置first_name变量中的值的函数:
let problemFunc = { (callback: (String -> Void) -> ()) in
FBRequestConnection.startForMeWithCompletionHandler { (connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if let fbGraphUserDict = result as? Dictionary<String, AnyObject>{
let first_name = fbGraphUserDict["first_name"] as NSString
callback(first_name) // << here you call the callback passing the `first_name` local variable
println(first_name)
}
}
}
and do the actual assignment to first_name
in a closure you define when calling problemFunc
:
并在调用problemFunc时定义的闭包中对first_name进行实际赋值:
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook!")
} else {
NSLog("User logged in through Facebook!")
problemFunc { (name: String) -> Void in
first_name = name
}
}
})