如果RACSignal没有订阅者,我将如何实现停止发布?如果有订阅者则自动启动?
这是一个场景:
让我们说我有一个currentLocationSignal在AppDelegate.当视图卸载时,我LocationViewController会订阅currentLocationSignal视图加载和取消订阅(dispose).由于获取当前位置需要几秒钟,我希望始终订阅currentLocationSignal应用程序打开的时间(并在几秒钟后自动取消订阅),所以当我到达时,LocationViewController我会得到一个准确的位置.因此,信号可能有多个订户.当第一个用户收听时,它需要开始呼叫startUpdatingLocation,当没有用户需要呼叫时stopUpdatingLocation.
cocoa-touch objective-c reactive-programming ios reactive-cocoa
我有信号返回NSNumber:
RACSignal *signal = ....
然后在某些代码处我希望在执行时得到信号的值,例如:
NSNumber *value = [code that extracts current value of signal];
我正在使用https://github.com/ReactiveCocoa/ReactiveCocoa实现我的第一个代码.
用于登录用户.该行[subscriber sendNext:user];被调用两次,但我希望只有一行.并且根本没有调用地图(因此永远不会调用自动登录)
这是我的实施:
-(RACSignal *) login:(NSString *)email pwd:(NSString *)pwd
{
    DDLogInfo(@"Login user %@", email);
    RACSignal *login = [RACSignal createSignal:^ RACDisposable *(id<RACSubscriber> subscriber)
    {        
        [PFUser logInWithUsernameInBackground:email password:pwd block:^(PFUser *user, NSError *error) {
            if (error) {
                [subscriber sendError:error];
            } else {
                [subscriber sendNext:user];
                [subscriber sendCompleted];
            }
        }];
        return nil;
    }];
    [login map:^(PFUser *user) {
        return [self autoLogin:user];
    }];
    return login;
}
这样称呼:
NSString *email = data[@"email"];
NSString *pwd = data[@"pwd"];
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];
RACSignal *login = [[SyncEngine server] …我正在制作一个iOS应用程序,可让您远程控制桌面上播放的应用程序中的音乐.
最难的问题之一是能够正确地更新"跟踪器"的位置(其显示当前正在播放的歌曲的时间位置和持续时间).这里有几个输入源:
目前,跟踪器是一个UISlider,由"玩家"模型支持.每当用户更改滑块上的位置时,它都会更新模型并发送网络请求,如下所示:
在NowPlayingViewController.m中
[[slider rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UISlider *x) {
    [playerModel seekToPosition:x.value];
}];
[RACObserve(playerModel, position) subscribeNext:^(id x) {
    slider.value = player.position;
}];
在PlayerModel.m中:
@property (nonatomic) NSTimeInterval position;
- (void)seekToPosition:(NSTimeInterval)position
{
    self.position = position;
    [self.client newRequestWithMethod:@"seekTo" params:@[positionArg] callback:NULL];
}
- (void)receivedPlayerUpdate:(NSDictionary *)json
{
    self.position = [json objectForKey:@"position"]
}
问题是当用户"摆弄"滑块时,会排队一些网络请求,这些请求都会在不同时间返回.当收到响应时,用户可能已经再次移动滑块,将滑块移回到先前的值.
我的问题:如何在此示例中正确使用ReactiveCocoa,确保处理来自网络的更新,但仅限于用户之后没有移动滑块?
我试图了解如何处理计划在后台线程上运行的RACSignal.
// Start button
@weakify(self);
[[self.startButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton *sender) {
    @strongify(self);
    self.startButton.enabled = NO;
    NSDate *startDate = [NSDate date];
    RAC(self, elapsedTime) = [[[[RACSignal interval:0.1f onScheduler:
                                 [RACScheduler schedulerWithPriority:RACSchedulerPriorityDefault]]
                                startWith:[NSDate date]] map:^id(id value) {
        NSTimeInterval timeInterval = [(NSDate *)value timeIntervalSinceDate:startDate];
        return [NSNumber numberWithDouble:timeInterval];
    }] deliverOn:[RACScheduler mainThreadScheduler]];
}];
// Stop button
[[self.stopButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
    self.startButton.enabled = YES;
    // How do I stop the timer here...???
}];
RAC(self.timeLabel, text) = [RACObserve(self, elapsedTime) map:^id(NSNumber *number) {
    NSString *string = [NSString stringWithFormat:@"%.1f sec. elapsed", …我正在尝试在我用Swift编写的iOS应用程序中采用ReactiveCocoa.不幸的是,看起来rac_valuesForKeyPath不能按预期工作.这是一个例子:
class Source: NSObject {
    var observable: String = "<Original>"
    override init() {
        super.init()
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), { () -> Void in
            self.observable = "<Updated>"
            println("Updated value to \(self.observable)");
        })
    }
}
class Observer: NSObject {
    init(source: Source) {
        super.init()
        source.rac_valuesForKeyPath("observable", observer: self).subscribeNext { (value: AnyObject!) -> Void in
            println(">>> Observable value changed: \(value)")
        }
    }
}
该示例生成以下输出:
>>> Observable value changed: <Original>
Updated value to <Updated>
这意味着未调用subcribeNext块.
预期的输入是:
>>> Observable value changed: <Original>
Updated value to <Updated> …我正在构建一个UISearchController,用户将在其中键入用户名,应用程序将从Web服务获取结果.
我想在用户输入时限制减少网络呼叫的请求.使用ReactiveCocoa如何实现这一目标?
class SearchResultsUpdater: NSObject, UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        let text = searchController.searchBar.text
        let dataSource = searchResultsController.tableView.dataSource as! ...     
    }
}
ReactiveCocoa可以通过调用它将信号转换为"热"信号-subscribeCompleted:.但我认为如果你不关心结果(即没有订阅者),这种方法就相当冗长.
RACDisposable *animationDisposable = [[self play:animation] subscribeCompleted:^{
    // just to make the animation play
}];
而这三行并不足以表达我的意图.
有类似目的的方法吗?谢谢!
我有以下设置,一个GridView由GridViewCells 组成.
class GridView : UIView {
    var gridViewCells: [GridViewCell] = []
    let tapHandler: Position -> ()
    init(frame: CGRect, tapHandler: Position -> ()) {
        self.tapHandler = tapHandler
        super.init(frame: frame)
        self.gridViewCells = createCells(self)
        addCellsToView(self.gridViewCells)
    }
    func addCellsToView(cells: [GridViewCell]) {
        for cell in cells {
            self.addSubview(cell)
        }
    }
}
class GridViewCell: UIImageView {
    let position: Position
    let tapHandler: Position -> ()
    init(frame: CGRect, position: Position, tapHandler: Position -> ()) {
        self.position = position
        self.tapHandler = tapHandler …我喜欢Dwifft,但我更希望将它与ReactiveCocoa一起使用,以帮助减少我的集合视图控制器中的代码复杂性.
目前,我有一个辅助类,它接受SignalProducer<[[T]]>where 的实例T: Equatable(因此它适用于不同的).每次信号产生器发出一个新值:
    self.data.producer.observeOn(UIScheduler()).on(next: { [unowned self] in
        guard let collectionView = self.collectionView else { return }
        for (index, element) in $0.enumerate() {
            if index == self.diffCalculators.count {
                let calculator = CollectionViewDiffCalculator<T>(collectionView: collectionView, initialRows: element)
                calculator.sectionIndex = index
                self.diffCalculators.append(calculator)
            } else {
                let calculator = self.diffCalculators[index]
                calculator.rows = element
            }
            for index in self.data.value.count..<(self.diffCalculators.count >= self.data.value.count ? self.diffCalculators.count : self.data.value.count) {
                self.diffCalculators.removeAtIndex(index)
            }
        }
    })
        .takeUntil(self.willDeallocSignal())
        .start()
在这里,通过我的2d数组枚举,如果还没有存在差异计算器,则会创建一个并添加到我的存储阵列中diffCalculators.如果确实存在,rows则设置该属性.之后,我遍历其余部分并将其删除.
不幸的是,我一直难以置信地将其付诸实践.一次The number …