在Swift中异步关闭问题解决不起作用?

时间:2018-01-12 21:12:46

标签: ios swift asynchronous

我已将问题归结为此

这个关闭:

  override func viewDidLoad() {
    super.viewDidLoad()
    let data = homeDataSource()
    getPrivatePosts { (posts) in
        print("postsCOUNT" , posts!.count)
        data.posts = posts!
    }
    self.datasource = data
    collectionView?.reloadData()

}

打印出" postCOUNT 1 postCOUNT 3"

然后当我打印data.posts的时候,我得到0 ...那是怎么回事?这是完整的代码

这是一个自定义的UICollectionView:

import LBTAComponents
import Firebase
class homeView: DatasourceController {

override func viewDidLoad() {
    super.viewDidLoad()
    let data = homeDataSource()
    getPrivatePosts { (posts) in
        print("postsCOUNT" , posts!.count)
        data.posts = posts!
    }
    self.datasource = data
    collectionView?.reloadData()

}

override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width , height: 150)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width: view.frame.width, height: 0   )
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    return CGSize(width: view.frame.width, height: 0)
}
// just to test
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    performSegue(withIdentifier: "goToNewPost", sender: self)
}


func getPrivatePosts(completion : @escaping (_ privatePosts : [Post]?) ->()){
    // fill posts array with posts from all buddys "privataPosts only"


    var ret = [Post]()
    staticValuesForData.instance.dataBaseUserref.child((Auth.auth().currentUser?.uid)!).child("contacts").observe( .value , with: { (snapshot) in

        let dict = snapshot.children.allObjects as! [DataSnapshot]
        for d in dict{
            if let contactUid = d.childSnapshot(forPath: "uid").value as? String{


                staticValuesForData.instance.dataBaseUserref.child(contactUid).child("privatePosts").observe( .value, with: { (snapshot) in

                    let posts = snapshot.children.allObjects as! [DataSnapshot]
                    print("postval" , posts)

                    for post in posts{

                        if let dict = post.value as? [String : AnyObject]{
                            let fullname = dict["fullname"] as! String
                            let picUrl = dict["picUrl"] as! String
                            let postContent = dict["postContent"] as! String
                            let time = dict["time"] as! Int
                            let uid = dict["uid"] as! String
                            let username = dict["username"] as! String

                            print("first name of person who did the post" , fullname)

                            let reposts = dict["reposts"] as! [String]

                            let downs = dict["downs"] as! [String]
                            // possible issue
                            var comments = [Comment]()

                            let commentArr = snapshot.childSnapshot(forPath: "comments").children.allObjects as! [DataSnapshot]

                            for c in commentArr{
                                if let dict = c.value as? [String : AnyObject]{

                                    let cuid = dict["uid"] as! String
                                    let ccommentText = dict["commentText"] as! String
                                    let cpicUrl = dict["picUrl"] as! String
                                    let cusername = dict["username"] as! String
                                    let ctime = dict["time"] as! Int

                                    let com = Comment(uid: cuid, commentText: ccommentText, time: ctime, picUrl: cpicUrl, username: cusername)

                                    comments.append(com)

                                }

                            }

                            print("HERE : post content\(postContent) username : \(username) commentArr \(comments)")

                            let postToAdd = Post(postContent: postContent, picUrl: picUrl, userName: username, fullName: fullname, postID: uid, postTime: time, downs: downs, reposts: reposts, comments: comments)

                            print("LOOK AT MEE   \(postToAdd.userName) is the username of the post object \(postToAdd.postContent) is the contetn")

                            ret.append(postToAdd)
                            print("RET" , ret)
                        }
                    }
                    completion(ret) // this is where the completion block should be called
                })

            }
        }
    })
}

}

这是一个数据源对象:

import LBTAComponents
class homeDataSource: Datasource {

var posts = [Post]()



override func numberOfItems(_ section: Int) -> Int {
    print("COUNT " , posts.count)
    return posts.count

}

override func headerClasses() -> [DatasourceCell.Type]? {
    return [userHeader.self]
}

override func footerClasses() -> [DatasourceCell.Type]? {
    return [userFooter.self]
}

override func cellClasses() -> [DatasourceCell.Type] {
    return [userCell.self]
}

override func item(_ indexPath: IndexPath) -> Any? {
    return posts[indexPath.item]
}

}

框架工作可以在这里使用:

pod' LBTAComponents'

2 个答案:

答案 0 :(得分:2)

你有两次相同的基本误解。

在第二个代码部分中,您创建的ret变量最初为空,然后触发一些异步任务。但是,您在异步任务之外调用完成(ret),因此它将在异步任务完成之前立即触发,因此返回您的初始空值。

第一个代码也会遇到同样的问题,因为你创建postArray最初是空的,然后调用你的getPrivatePosts函数提供一个完成处理程序,但是在异步任务中调用完成处理程序,所以可能有一个延迟,但你使用值立即,因此将返回空的初始值。

答案 1 :(得分:0)

您不应该以这种方式创建帖子数组。你应该创建一个可变数组:

var posts = [Post]()

然后在视图控制器的viewDidLoad中,您应该从服务(Firebase)填充数组。

override func viewDidLoad() {
    super.viewDidLoad()

    getPrivatePosts() { posts in
        self.posts = posts ?? []
    }
}

您发布的功能也永远不会从服务中返回您想要的数据,因为您在服务请求范围之外调用完成块。将完成块移动到staticValuesForData.instance.dataBaseUserref.child函数的getPrivatePosts部分中for循环的底部,如下所示:

class func getPrivatePosts(completion : (_ privatePosts : [Post]?) ->.   ()){
    // fill posts array with posts from all buddys "privataPosts only"


    var ret = [Post]()
    staticValuesForData.instance.dataBaseUserref.child((Auth.auth().currentUser?.uid)!).child("contacts").observe( .value , with: { (snapshot) in

        let dict = snapshot.children.allObjects as! [DataSnapshot]
        for d in dict{
            if let contactUid = d.childSnapshot(forPath: "uid").value as? String{


                staticValuesForData.instance.dataBaseUserref.child(contactUid).child("privatePosts").observe( .value, with: { (snapshot) in

                    let posts = snapshot.children.allObjects as! [DataSnapshot]
                    print("postval" , posts)

                    for post in posts{

                        if let dict = post.value as? [String : AnyObject]{
                            let fullname = dict["fullname"] as! String
                            let picUrl = dict["picUrl"] as! String
                            let postContent = dict["postContent"] as! String
                            let time = dict["time"] as! Int
                            let uid = dict["uid"] as! String
                            let username = dict["username"] as! String

                            print("first name of person who did the post" , fullname)

                            let reposts = dict["reposts"] as! [String]

                            let downs = dict["downs"] as! [String]
                            // possible issue
                            var comments = [Comment]()

                            let commentArr = snapshot.childSnapshot(forPath: "comments").children.allObjects as! [DataSnapshot]

                            for c in commentArr{
                                if let dict = c.value as? [String : AnyObject]{

                                    let cuid = dict["uid"] as! String
                                    let ccommentText = dict["commentText"] as! String
                                    let cpicUrl = dict["picUrl"] as! String
                                    let cusername = dict["username"] as! String
                                    let ctime = dict["time"] as! Int

                                    let com = Comment(uid: cuid, commentText: ccommentText, time: ctime, picUrl: cpicUrl, username: cusername)

                                    comments.append(com)

                                }

                            }

                            print("HERE : post content\(postContent) username : \(username) commentArr \(comments)")

                            let postToAdd = Post(postContent: postContent, picUrl: picUrl, userName: username, fullName: fullname, postID: uid, postTime: time, downs: downs, reposts: reposts, comments: comments)

                            print("LOOK AT MEE   \(postToAdd.userName) is the username of the post object \(postToAdd.postContent) is the contetn")

                            ret.append(postToAdd)
                            print("RET" , ret)
                        }
                    }
                    completion(ret) // this is where the completion block should be called
                })

            }
        }

    })
}

我希望这会有所帮助。