Swift 控制流程:
Swift control flow:
在我的代码下方,我尝试使用 Facebook SDK 获取我的好友列表并在另一个视图控制器上显示他们。我在函数loginViewShowingLoggedInUser
中调用函数createFriendsInfo(data : NSArray)
。正在调用该函数并将数据填充到数组中。
问题是在createFriendsInfo
中的循环完成填充数组中的数据后,控件直接转到视图控制器。相反,它应该首先执行完函数中循环之后的语句,然后控制应该返回到 loginViewShowingLoggedInUser
应该执行 performSegueWithIdentifier:
的地方。
我是 Swift 的新手,我需要一些帮助来理解我的代码中的控制流。
import Foundation
import UIKit
class FBViewController : UIViewController, FBLoginViewDelegate {
@IBOutlet var fbLogin: FBLoginView!
var friendNames : [String] = []
var friendPics : [UIImage] = []
override func viewDidLoad() {
super.viewDidLoad()
//var fbl: FBLoginView = FBLoginView() //create login button on UIController
//self.view.addSubview(fbl)
// Do any additional setup after loading the view, typically from a nib.
self.fbLogin.delegate = self
self.fbLogin.readPermissions = ["public_profile", "email", "user_friends"]
}
func createFriendsInfo(data : NSArray)
{
println("Start Create")
for i in 0...data.count {
let valueDict : NSDictionary = data[i] as NSDictionary
let userID = valueDict.objectForKey("id") as String
self.friendNames.append(valueDict.objectForKey("name") as String)
let id = valueDict.objectForKey("name") as String
var url = NSURL (string : "http://graph.facebook.com/\(userID)/picture?type=large")
let urlRequest = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
var error: NSErrorPointer = nil
if let ImageData : NSData = NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: response, error:nil)?
{
var image = UIImage( data : ImageData)
self.friendPics.append(image!)
println("Image Appended")
}
}
println("Create Friends Info \(self.friendNames.count) \(self.friendPics.count) ")
}
// Facebook Delegate Methods
func loginViewShowingLoggedInUser(loginView : FBLoginView!) {
println("Start Fetched")
var friendsRequest : FBRequest = FBRequest.requestForMyFriends()
friendsRequest.startWithCompletionHandler{(connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
var resultdict = result as NSDictionary
println("Result Dict: \(resultdict)")
var Data : NSArray = resultdict.objectForKey("data") as NSArray
self.createFriendsInfo(Data)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
self.performSegueWithIdentifier("toFriendList", sender: self)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
//
}
//self.performSegueWithIdentifier("toFriendList", sender: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loginViewFetchedUserInfo(loginView : FBLoginView!, user: FBGraphUser) {
}
func loginViewShowingLoggedOutUser(loginView : FBLoginView!) {
println("User Logged Out")
self.friendNames = []
self.friendPics = []
println("Logout \(self.friendNames.count) \(self.friendPics.count) ")
}
func loginView(loginView : FBLoginView!, handleError:NSError) {
println("Error: \(handleError.localizedDescription)")
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if((segue.identifier == "toFriendList" ) && (self.friendNames.count > 0))
{
var fl : friendList = segue.destinationViewController as friendList
println("Prepare \(self.friendNames.count) \(self.friendPics.count) ")
fl.name1 = self.friendNames
fl.profilepics1 = self.friendPics
}
}
}
createFriendsInfo
中的for
循环上限错误;通常是 0..<data.count
。事实上,
for i in 0...data.count {
let valueDict : NSDictionary = data[i] as NSDictionary
// ...
将在 i == data.count
时 'fail'。
但是,至于控制流,friendsRequest
完成处理程序肯定不会 运行 在主队列上。这意味着 performSegueWithIdentifier
将 'get lost'。将您的代码更改为:
func loginViewShowingLoggedInUser(loginView : FBLoginView!) {
println("Start Fetched")
var friendsRequest : FBRequest = FBRequest.requestForMyFriends()
friendsRequest.startWithCompletionHandler{
(connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
var resultdict = result as NSDictionary
println("Result Dict: \(resultdict)")
var Data : NSArray = resultdict.objectForKey("data") as NSArray
self.createFriendsInfo(Data)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("toFriendList", sender: self)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
//
}
}
}
必须在主队列上执行所有 UI 操作。
请注意,您可能需要在 dispatch_async
的闭包中将 self
声明为 unowned
(我忘记了当前的 Swift 状态)
在我的代码下方,我尝试使用 Facebook SDK 获取我的好友列表并在另一个视图控制器上显示他们。我在函数loginViewShowingLoggedInUser
中调用函数createFriendsInfo(data : NSArray)
。正在调用该函数并将数据填充到数组中。
问题是在createFriendsInfo
中的循环完成填充数组中的数据后,控件直接转到视图控制器。相反,它应该首先执行完函数中循环之后的语句,然后控制应该返回到 loginViewShowingLoggedInUser
应该执行 performSegueWithIdentifier:
的地方。
我是 Swift 的新手,我需要一些帮助来理解我的代码中的控制流。
import Foundation
import UIKit
class FBViewController : UIViewController, FBLoginViewDelegate {
@IBOutlet var fbLogin: FBLoginView!
var friendNames : [String] = []
var friendPics : [UIImage] = []
override func viewDidLoad() {
super.viewDidLoad()
//var fbl: FBLoginView = FBLoginView() //create login button on UIController
//self.view.addSubview(fbl)
// Do any additional setup after loading the view, typically from a nib.
self.fbLogin.delegate = self
self.fbLogin.readPermissions = ["public_profile", "email", "user_friends"]
}
func createFriendsInfo(data : NSArray)
{
println("Start Create")
for i in 0...data.count {
let valueDict : NSDictionary = data[i] as NSDictionary
let userID = valueDict.objectForKey("id") as String
self.friendNames.append(valueDict.objectForKey("name") as String)
let id = valueDict.objectForKey("name") as String
var url = NSURL (string : "http://graph.facebook.com/\(userID)/picture?type=large")
let urlRequest = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?>=nil
var error: NSErrorPointer = nil
if let ImageData : NSData = NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: response, error:nil)?
{
var image = UIImage( data : ImageData)
self.friendPics.append(image!)
println("Image Appended")
}
}
println("Create Friends Info \(self.friendNames.count) \(self.friendPics.count) ")
}
// Facebook Delegate Methods
func loginViewShowingLoggedInUser(loginView : FBLoginView!) {
println("Start Fetched")
var friendsRequest : FBRequest = FBRequest.requestForMyFriends()
friendsRequest.startWithCompletionHandler{(connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
var resultdict = result as NSDictionary
println("Result Dict: \(resultdict)")
var Data : NSArray = resultdict.objectForKey("data") as NSArray
self.createFriendsInfo(Data)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
self.performSegueWithIdentifier("toFriendList", sender: self)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
//
}
//self.performSegueWithIdentifier("toFriendList", sender: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loginViewFetchedUserInfo(loginView : FBLoginView!, user: FBGraphUser) {
}
func loginViewShowingLoggedOutUser(loginView : FBLoginView!) {
println("User Logged Out")
self.friendNames = []
self.friendPics = []
println("Logout \(self.friendNames.count) \(self.friendPics.count) ")
}
func loginView(loginView : FBLoginView!, handleError:NSError) {
println("Error: \(handleError.localizedDescription)")
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if((segue.identifier == "toFriendList" ) && (self.friendNames.count > 0))
{
var fl : friendList = segue.destinationViewController as friendList
println("Prepare \(self.friendNames.count) \(self.friendPics.count) ")
fl.name1 = self.friendNames
fl.profilepics1 = self.friendPics
}
}
}
createFriendsInfo
中的for
循环上限错误;通常是 0..<data.count
。事实上,
for i in 0...data.count {
let valueDict : NSDictionary = data[i] as NSDictionary
// ...
将在 i == data.count
时 'fail'。
但是,至于控制流,friendsRequest
完成处理程序肯定不会 运行 在主队列上。这意味着 performSegueWithIdentifier
将 'get lost'。将您的代码更改为:
func loginViewShowingLoggedInUser(loginView : FBLoginView!) {
println("Start Fetched")
var friendsRequest : FBRequest = FBRequest.requestForMyFriends()
friendsRequest.startWithCompletionHandler{
(connection:FBRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
var resultdict = result as NSDictionary
println("Result Dict: \(resultdict)")
var Data : NSArray = resultdict.objectForKey("data") as NSArray
self.createFriendsInfo(Data)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("toFriendList", sender: self)
println("Perform \(self.friendNames.count) \(self.friendPics.count) ")
//
}
}
}
必须在主队列上执行所有 UI 操作。
请注意,您可能需要在 dispatch_async
的闭包中将 self
声明为 unowned
(我忘记了当前的 Swift 状态)