代码之家  ›  专栏  ›  技术社区  ›  alekop

刷新可观察到的响应另一个

  •  0
  • alekop  · 技术社区  · 5 年前

    我有一个observable,它会发出CNContacts列表,当Contacts数据库发生变化时,我想重新加载该列表( .CNContactStoreDidChange ).

    因此,可观察对象应该在订阅时发出一个值,并且每当其他可观察对象(通知)发出一个值时。这听起来像是把它们和 withLatestFrom ,但它不发出任何东西。

    let myContactKeys = [
        CNContactIdentifierKey as CNKeyDescriptor,
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
    ]
    
    func fetchContacts(by identifiers: [String],
                     contactKeys: [CNKeyDescriptor]) -> Observable<Event<[CNContact]>> {
    
        return Observable<[String]>.just(identifiers)
            .withLatestFrom(NotificationCenter.default.rx.notification(Notification.Name.CNContactStoreDidChange)) { ids, _ in ids}
            .flatMap { ids in
                Observable<[CNContact]>.create { observer in
                    let predicate = CNContact.predicateForContacts(withIdentifiers: ids)
                    do {
                        let contacts = try CNContactStore().unifiedContacts(matching: predicate, keysToFetch: contactKeys)
                        observer.onNext(contacts)
                    } catch {
                        observer.onError(error)
                    }
    
                    return Disposables.create()
                }
                .materialize()
            }
            .observeOn(MainScheduler.instance)
            .share(replay: 1)
            .debug()
    }
    
    fetchContacts(by: ["123"], contactKeys: myContactKeys)
        .subscribe(
            onNext: { contacts in
                contacts.forEach { print($0.fullName) }
            },
            onError: { error in
                print(error.localizedDescription)
            })
        .dispose(by: disposeBag)
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   Daniel T.    5 年前

    你的代码的问题是你从 Observable<[String]>.just(identifiers) 它将发出您的标识符并立即完成。您不希望它完成,而是希望它在收到通知时继续发出值。

    根据你的描述,听起来你想要下面这样的东西。它会在通知发出时发出,并从联系人开始。

    let myContactKeys = [
        CNContactIdentifierKey as CNKeyDescriptor,
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
    ]
    
    func fetchContacts(by identifiers: [String], contactKeys: [CNKeyDescriptor]) -> Observable<Event<[CNContact]>> {
    
        func update() throws -> [CNContact] {
            let predicate = CNContact.predicateForContacts(withIdentifiers: identifiers)
            return try CNContactStore().unifiedContacts(matching: predicate, keysToFetch: contactKeys)
        }
        return Observable.deferred {
            NotificationCenter.default.rx.notification(Notification.Name.CNContactStoreDidChange)
                .map { _ in }
                .map(update)
                .materialize()
            }
            .startWith({ () -> Event<[CNContact]> in
                do {
                    return Event.next(try update())
                }
                catch {
                    return Event.error(error)
                }
            }())
            .share(replay: 1)
            .debug()
    }