ReactiveCocoa 问题

ReactiveCocoa Issue

我正在尝试在我的项目中使用 ReactiveCocoa 来处理 UITableView 的填充。

如果 none 可用,当我加载数据时,我想将 tableView.backgroundViewhidden 属性 设置为 false。这是我目前所拥有的:

func loadData() {
    let dataSource = tableView.dataSource as! BlockedTableViewDataSource
    let load = dataSource.load(currentUser) # RACSignal

    load.map {
        return ([=10=] as! [AnyObject]).count > 0
    }.startWith(true).distinctUntilChanged().setKeyPath("hidden", onObject: tableView.backgroundView!)

    load.subscribeError({ error in
        println(error)
    }, completed: {
        self.tableView.reloadData()
        self.refreshControl?.endRefreshing()
    })
}

然而,这会出错,提示我需要等待网络请求完成。我正在使用 Parse 获取数据,但我认为我的 ReactiveCocoa 代码设置不正确并导致此错误。如果我注释掉 load.map... 部分,table 会按预期填充。

如何在 "Reactive Way" 中实现这一点?

更新 #1

这里是dataSource

load函数
func load(user: User) -> RACSignal {
    return self.getBlocks(user).doNext {
        self.blocks = [=11=] as! [Block]
    }
}

private func getBlocks(fromUser: User) -> RACSignal {
    let query = Block.query()!
    query.whereKey("fromUser", equalTo: fromUser)
    query.includeKey("toUser")

    return query.rac_findObjects()
}

更新#2

2015-04-28 08:20:02.612 ohio[90547:2154845] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This query has an outstanding network connection. You have to wait until it's done.'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010b840c65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010bc5dbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010b840b9d +[NSException raise:format:] + 205
    3   ohio                                0x0000000107facb1b -[PFQuery checkIfCommandIsRunning] + 77
    4   ohio                                0x0000000107facb71 -[PFQuery markAsRunning:] + 46
    5   ohio                                0x0000000107fad105 -[PFQuery _findObjectsAsync:after:] + 234
    6   ohio                                0x0000000107faf0a0 -[PFQuery findObjectsInBackgroundWithBlock:] + 288
    7   ohio                                0x0000000107d9532d _TFFE4ohioCSo7PFQuery15rac_findObjectsFS0_FT_CSo9RACSignalU_FGSQPSo13RACSubscriber__GSQCSo13RACDisposable_ + 205
    8   ohio                                0x0000000107d6639e _TTRXFo_oGSQPSo13RACSubscriber___oGSQCSo13RACDisposable__XFo_iGSQPS____iGSQS0___ + 30
    9   ohio                                0x0000000107d944c1 _TPA__TTRXFo_oGSQPSo13RACSubscriber___oGSQCSo13RACDisposable__XFo_iGSQPS____iGSQS0___ + 81
    10  ohio                                0x0000000107d663d4 _TTRXFo_iGSQPSo13RACSubscriber___iGSQCSo13RACDisposable__XFo_oGSQPS____oGSQS0___ + 36
    11  ohio                                0x0000000107d66418 _TTRXFo_oGSQPSo13RACSubscriber___oGSQCSo13RACDisposable__XFdCb_dGSQPS____aGSQS0___ + 56
    12  ohio                                0x0000000107eeacca __30-[RACDynamicSignal subscribe:]_block_invoke + 74
    13  ohio                                0x0000000107f35b8e -[RACSubscriptionScheduler schedule:] + 478
    14  ohio                                0x0000000107eeab9d -[RACDynamicSignal subscribe:] + 765
    15  ohio                                0x0000000107f28f1d -[RACSignal(Subscription) subscribeNext:error:completed:] + 1133
    16  ohio                                0x0000000107f004cc __32-[RACSignal(Operations) doNext:]_block_invoke + 396
    17  ohio                                0x0000000107eeacca __30-[RACDynamicSignal subscribe:]_block_invoke + 74
    18  ohio                                0x0000000107f35b8e -[RACSubscriptionScheduler schedule:] + 478
    19  ohio                                0x0000000107eeab9d -[RACDynamicSignal subscribe:] + 765
    20  ohio                                0x0000000107f2999e -[RACSignal(Subscription) subscribeError:completed:] + 766
    21  ohio                                0x0000000107dc5fdb _TFC4ohio26BlockedTableViewController8loadDatafS0_FCS_4UserT_ + 3083
    22  ohio                                0x0000000107dc6775 _TFC4ohio26BlockedTableViewController11viewDidLoadfS0_FT_T_ + 501
    23  ohio                                0x0000000107dc7702 _TToFC4ohio26BlockedTableViewController11viewDidLoadfS0_FT_T_ + 34
    24  UIKit                               0x000000010a142210 -[UIViewController loadViewIfRequired] + 738
    25  UIKit                               0x000000010a14240e -[UIViewController view] + 27
    26  UIKit                               0x000000010a167297 -[UINavigationController _startCustomTransition:] + 633
    27  UIKit                               0x000000010a1733bf -[UINavigationController _startDeferredTransitionIfNeeded:] + 386
    28  UIKit                               0x000000010a173f0e -[UINavigationController __viewWillLayoutSubviews] + 43
    29  UIKit                               0x000000010a2be715 -[UILayoutContainerView layoutSubviews] + 202
    30  UIKit                               0x000000011915093e -[UILayoutContainerViewAccessibility layoutSubviews] + 43
    31  UIKit                               0x000000010a091a2b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 536
    32  QuartzCore                          0x0000000109d12ec2 -[CALayer layoutSublayers] + 146
    33  QuartzCore                          0x0000000109d076d6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    34  QuartzCore                          0x0000000109d07546 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
    35  QuartzCore                          0x0000000109c73886 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
    36  QuartzCore                          0x0000000109c74a3a _ZN2CA11Transaction6commitEv + 462
    37  QuartzCore                          0x0000000109c750eb _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
    38  CoreFoundation                      0x000000010b773ca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    39  CoreFoundation                      0x000000010b773c00 __CFRunLoopDoObservers + 368
    40  CoreFoundation                      0x000000010b769a33 __CFRunLoopRun + 1123
    41  CoreFoundation                      0x000000010b769366 CFRunLoopRunSpecific + 470
    42  GraphicsServices                    0x000000010cfc8a3e GSEventRunModal + 161
    43  UIKit                               0x000000010a011900 UIApplicationMain + 1282
    44  ohio                                0x0000000107d86df7 main + 135
    45  libdyld.dylib                       0x000000010c3c1145 start + 1
    46  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

方法 rac_findObjects() returns a cold signal. It means that each time someone subscribes to this signal, its side effects (that is, executing the underlying network request) will be repeated. And it seems that PFQuery doesn't allow to send more than one simultaneous request,因此出现错误消息。

在您的情况下,您正在为 load 信号制作 两个 订阅,因为调用 setKeyPath 也会创建一个。所以网络请求被执行了两次,这导致了你发布的错误。

如链接 GitHub 问题中所建议,您可以使用 RACMulticastConnection 来确保副作用(网络请求)只执行一次,无论有多少订阅者。例如:

let load = dataSource.load(currentUser).publish().autoconnect()