2014-10-07 2 views
15
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 

     } 
    }) 

Dieser Code befindet sich in einer @Ibaction-Schaltfläche. Ich kann nicht bauen, weil der Aufruf von problemFunc() die Fehlermeldung im Titel dieses Beitrags auslöst. Wenn ich die var-Definition first_name in die problemFunc verschiebe, wird es funktionieren. Aber ich brauche es, weil eine andere Funktion auf ihren Wert zugreifen muss. Ich bin wirklich nicht sicher, was dieses Problem verursacht, wenn Sie eine Ahnung haben, bitte helfen Sie.Kann keine lokale Funktion mit Erfassung von einer anderen lokalen Funktion referenzieren (swift)

Antwort

27

Verwenden Sie einen Verschluss statt einer Funktion:

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

Dank benötigen, funktioniert aber aus irgendeinem Grund hatte ich zu entfernen, um: ->() –

+0

Vielen Dank! Gute Idee, dieses hässliche Ding zu vermeiden – iiFreeman

2

@fluidsonic Antwort sollte das Problem lösen. Beachten Sie jedoch, dass Sie etwas Spaghetti-Code eingeben, weil Sie eine Variable ändern, die von einer Schließung erfasst und im Kontext einer anderen Funktion ausgeführt wird. Das ist schwer nachzuvollziehen, wenn Sie debuggen müssen, und es ist im Allgemeinen schwieriger, zu verfolgen, wann und wie diese Variable geändert wird.

eine linearere und besser lesbarer Strömung problemFunc als eine Funktion zu definieren, um eine Funktion als Parameter genommen wird, und ruft diese Funktion nicht direkt den Wert in der first_name Stellgröße:

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) 
     } 
    } 
} 

und machen die eigentliche Zuordnung zu first_name in einem Verschluss Sie definieren, wenn problemFunc Aufruf:

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

danke, werde das auch versuchen –

11

Hier sind die Grundprinzipien im Spiel: (von der Apple-docs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID103)

"Globale und verschachtelte Funktionen, wie sie in Funktionen eingeführt wurden, sind eigentlich Sonderfälle von Verschlüssen. Verschlüsse haben eine von drei Formen:

  • Globale Funktionen sind Schließungen, die einen Namen haben und keine Werte erfassen.
  • Verschachtelte Funktionen sind Verschlüsse, die einen Namen haben und Werte aus ihrer umschließenden Funktion erfassen können.
  • Closure Ausdrücke sind unbenannte Verschlüsse in einem leichten Syntax geschrieben, die Werte aus dem sie umgebenden Kontext erfassen kann.“

dh das ok ist

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

aber das ist nicht

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

Wenn Sie dies in Xcode betrachten, gibt Ihnen die dritte Funktion (func nestedFunc2) den Fehler "Kann eine lokale Funktion nicht mit einem Capture von einem anderen lokalen f referenzieren "

Die obere Funktion (func someFunc) ist eine globale Bereichsfunktion und diese funktionieren wie normale Funktionen/Methoden.

Die zweite Funktion (func nestFunc) ist eine verschachtelte -Funktion, die ein Name Schließung eine Ebene tief ist, die den Bereich der übergeordneten globalen Funktion erfassen kann.

Verschachtelte Funktionen, können den Gültigkeitsbereich einer globalen Funktion erfassen, aber nicht der Bereich einer anderen verschachtelten Funktion.

Deshalb haben wir einen Schließung heißt

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

yup genau! +1 den ganzen Weg –

+1

Hervorragende Erklärung. Ich hatte keine Ahnung, was vor sich ging, aber du hast es wirklich leicht verständlich gemacht. +1 – TaylorAllred

Verwandte Themen