ios - Firebase调用回调函数后如何回到main_thread?

标签 ios swift multithreading firebase firebase-realtime-database

Firebase 将在闭包中运行,因此在另一个线程中运行。当 Firebase 完成加载数据时,我尝试调用完成处理程序。

但是我运行它时出错。 “Thread 1: EXC_BAD_ACCESS(Code=EXC_1386_GPFLT)” 我知道问题出在错误的线程上,但不知道如何解决。我正在尝试编辑 View Controller 上组件的状态。请帮忙

func refreshData(completionHandler:@escaping (Bool)->() ) {
    //I ignore some unrelated statements here
    //....
    //Reloading the database
    ref.observe(.value, with: { snapshot in
        var newItems: [Task] = []
        self.num_of_tasks = Int(snapshot.childrenCount)
        for item in snapshot.children {
            let taskItem = Task(snapshot: item as! DataSnapshot)
            newItems.append(taskItem!)
        }
        let merged = drafts + newItems
        self.items = merged
        self.tableView.reloadData()
        completionHandler(true) //The line causes error
    })
}

我在 viewDidLoad 中调用了这个函数。

override func viewDidLoad() {
    super.viewDidLoad()
    self.refreshControl = UIRefreshControl()
    self.refreshControl!.addTarget(self, action: #selector(refreshData),for: .valueChanged)
    self.refreshControl!.attributedTitle = NSAttributedString(string: "Update the data")
    refreshData{ _ in
        self.refreshControl!.endRefreshing()
    }
}

更新崩溃日志:

> * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x111606db0)
>     frame #0: 0x0000000111606db0 CoreFoundation`__NSSingleObjectArrayI
>     frame #1: 0x000000010f61248a MGSupport`thunk at TaskTableViewController.swift:0   * frame #2: 0x000000010f612294
> MGSupport`TaskTableViewController.(self=0x00007fa6ead25860,
> completionHandler=0x000000010f6124e0 MGSupport`partial apply forwarder
> for reabstraction thunk helper from @callee_unowned @convention(block)
> (@unowned ObjectiveC.ObjCBool) -> () to @callee_owned (@unowned
> Swift.Bool) -> () at TaskTableViewController.swift) -> ()) ->
> ()).(closure #1).(closure #1) at TaskTableViewController.swift:95
>     frame #3: 0x000000010f6122d7 MGSupport`thunk at TaskTableViewController.swift:0
>     frame #4: 0x00000001140c94a6 libdispatch.dylib`_dispatch_call_block_and_release + 12
>     frame #5: 0x00000001140f205c libdispatch.dylib`_dispatch_client_callout + 8
>     frame #6: 0x00000001140d340b libdispatch.dylib`_dispatch_main_queue_callback_4CF + 411
>     frame #7: 0x0000000111311909 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
>     frame #8: 0x00000001112d7ae4 CoreFoundation`__CFRunLoopRun + 2164
>     frame #9: 0x00000001112d7016 CoreFoundation`CFRunLoopRunSpecific + 406
>     frame #10: 0x000000011548ea24 GraphicsServices`GSEventRunModal + 62
>     frame #11: 0x0000000111e59134 UIKit`UIApplicationMain + 159
>     frame #12: 0x000000010f62c687 MGSupport`main at AppDelegate.swift:14
>     frame #13: 0x000000011413e65d libdyld.dylib`start + 1

调试更新: 我尝试设置断点,我发现只有第一次从 viewDidLoad() 调用函数时才能成功调用 completionHandler。但是如果用户向下滚动屏幕并通过 refreshControl 的自动调用再次调用 refreshData 函数,则它无法再访问 completionHandler。有什么想法吗?

最佳答案

这是因为 refreshControl 选择器。选择器没有任何完成处理程序,当 refreshControl 值更改时,完成 block 正在尝试执行,但没有用于刷新控制的完成 block 。

所以最好为你的 refreshData(_:) 提供默认的完成 block

func refreshData(completionHandler:@escaping (Bool)->() = { _ in }) {
    //You code is here.
}

关于ios - Firebase调用回调函数后如何回到main_thread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45206808/

相关文章:

java - Android线程在进程中间随机停止

ios - UICollection NumberOfItemsInSection 向 vars 添加常量的问题

android - NoSuchMethodError : The method 'of' was called on null 错误

ios - 运行 iOS 应用程序时,矢量图像以灰度显示

ios - 默认手势事件在谷歌地图中不起作用

iOS 套接字输入流阻塞 UI,但未安排在主线程上

iphone - UITableViewCell 中的 UIView 动画

c# - 为什么此backgroundworker代码导致此错误: Parameter count mismatch

swift - 从 Parse.com 获取数据到 swift

swift - 在 swift 中以什么顺序将项目添加到 "map"?