无法使用本地函数捕获本地函数(swift)

问题描述:

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 

     } 
    }) 

此代码位于@Ibaction按钮内。我无法构建,因为调用problemFunc()会触发此帖子标题中的错误消息。如果我移动problemFunc中的first_name var定义,它将正常工作。但我需要它,因为另一个功能需要访问它的价值。 我真的不确定导致此问题的原因,如果您有线索,请帮助。无法使用本地函数捕获本地函数(swift)

使用闭包,而不是一个功能:

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 

    } 
}) 
+0

感谢,工作原理,但由于某些原因,我不得不删除: - >() – 2014-10-07 15:42:43

+0

非常感谢!好主意,以避免这个丑陋的东西 – iiFreeman 2014-12-17 14:54:08

@fluidsonic答案应该解决的问题。但是请注意,你正在做一些意大利面代码,因为你正在修改一个闭包捕获的变量,并在另一个函数的上下文中执行。如果您需要调试,那么很难跟踪,而且更一般地难以追踪何时以及如何修改该变量。

更线性的和更好的可读流是定义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) 
     } 
    } 
} 

,并执行实际调用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 
     } 
    } 
}) 
+0

谢谢,也会尝试那 – 2014-10-07 15:43:09

下面是游戏的基本原则:(来自苹果的文档:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103

“函数中引入的全局函数和嵌套函数实际上是闭包的特例。关闭采取以下三种形式之一:

  • 全局函数是具有名称并且不捕获任何值的闭包。
  • 嵌套函数是具有名称并可从其封闭函数捕获值的闭包。
  • 闭合表达式是写在一个轻量级的语法,可以从他们的周围上下文捕捉值无名倒闭。”

即这是确定

func someFunc() { 
    func nestFunc() {} 
} 

但这不是

func someFunc() { 
    func nestFunc() { 
    func nestedFunc2() { } 
    } 
} 

如果你在Xcode中查看这个函数,第三个函数(func nestedFunc2)会给你错误:“不能用本地函数捕获另一个局部函数f联合“

*函数(func someFunc)是一个全局作用域函数和那些像常规函数/方法一样工作。

第二个函数(func nestFunc)是一个嵌套函数它是一个深度为一级的命名闭包,可以捕获其父级全局函数的作用域。

嵌套函数,可以捕获全局函数的作用域但不是另一个嵌套函数的作用域。

这就是为什么我们需要一个封闭

func someFunc() { 
    func nestFunc() { 
     let strictClosure = {() ->() in 
     //this is where you write the code 
     } 
    } 
} 
+0

正好! +1一路 – 2015-01-17 19:00:48

+1

精湛的解释。我不知道发生了什么事,但是你让它很容易理解。 +1 – TaylorAllred 2015-04-17 01:56:10