Reactivecocoa: مرتبك بشأن المستهلكات فيما يتعلق بـ startWithNext على MutableProperties

تم إنشاؤها على ٥ سبتمبر ٢٠١٦  ·  3تعليقات  ·  مصدر: ReactiveCocoa/ReactiveCocoa

أعتقد أنني في حيرة من أمري حول كيفية عمل Disposable s. لدي فئة فرعية UITableViewCell مع خاصية viewModel . في didSet من viewModel أستدعي الوظيفة التالية:

الرمز

private func setupBindings() {

    if let friendViewModel = friendViewModel {
        disposableBindings += friendViewModel.statusLabel.producer.startWithNext({ status in
            self.statusLabel.text = status
        })
    }

}

يحتوي friendViewModel على MutableProperty يُسمى statusLabel ويبدو كما يلي:

let statusLabel = MutableProperty<String>("")

هذه الخاصية disposableBindings هي ملكية CompositeDisposable ، والتي أنا "أتصرف بها" في طريقة prepareForReuse() متجاوزة ، مثل:

override func prepareForReuse() {
    disposableBindings.dispose()
}

المشكلة

المشكلة هي أن statusLabel لا يتم تحديثه في أي وقت بعد إرسال الإشارة الأولى. لقد صححت هذا الخطأ ولم يتم استدعاء prepareForReuse() . عندما أضيف logEvents() مثل ...producer.logEvents().startWithNext({... أحصل على مخرجات في وحدة التحكم مثل:

[] Started fileName: /NotImportant/ButAllTheSame, functionName: setupBindings(), lineNumber: 60
[] Next Tap to invite... fileName: /NotImportant/ButAllTheSame, functionName: setupBindings(), lineNumber: 60
[] Interrupted fileName: /NotImportant/ButAllTheSame, functionName: setupBindings(), lineNumber: 60
[] Terminated fileName: /NotImportant/ButAllTheSame, functionName: setupBindings(), lineNumber: 60
[] Disposed fileName: /NotImportant/ButAllTheSame, functionName: setupBindings(), lineNumber: 60

أنا في حيرة من أمري لماذا يتم إرسال حدث Interrupted على المنتج؟ هذا MutableProperty ، لذا لست متأكدًا من سبب إرسال المقاطعة. يجب أن أضيف ذلك من خلال التجربة والخطأ ، لقد وجدت أن مجرد تجاهل المتاح يحل المشكلة:

friendViewModel.statusLabel.producer.logEvents().startWithNext({ status in
    self.statusLabel.text = status
})

ومع ذلك ، كما هو متوقع ، أنا متأكد من أن هذا يؤدي إلى حدوث مشكلات أخرى حيث لا تحتوي الخلايا المعاد استخدامها على إشارات من الاستدعاءات السابقة setupBindings() التخلص منها ويقومون بتغيير النص statusLabel مع القيم من منتج العرض الخاطئ statusLabel MutableProperty المنتج.

ما الذي افتقده هنا؟

question

التعليق الأكثر فائدة

andersio شكرا لك هذا رائع!

أيضًا ، لمعلوماتك فقط ، فقد ساعدك تفسيرك أيضًا. عندما قمت بتغيير الرمز ليكون بدلاً من ذلك:

private var disposableBindings = CompositeDisposable()

private func setupBindings() {
        disposableBindings += friendViewModel.statusLabel.producer.startWithNext({ status in
            self.statusLabel.text = status
        })
    }
}

override func prepareForReuse() {
    disposableBindings.dispose()
    disposableBindings = CompositeDisposable()
}

تستمر الإشارة حتى إعادة استخدام الخلية. أعتقد أن المشكلة كانت مني في إعادة استخدام CompositeDisposable. كنت أعامله مثل NSCache أو شيء من هذا القبيل.

شكرا لك مرة أخرى!

ال 3 كومينتر

يرسل المنتج حدثًا interrupted عندما يتم مقاطعته يدويًا (عبر المتاح).

إذا تخلصت من المنتجين المبتدئين (المعروفين أيضًا باسم الإشارة المنتجة) ، فستحتاج إلى إعادة التأسيس بعد ذلك.

علاوة على ذلك ، لا يمكن إعادة استخدام Disposable التخلص منه ، وفي حالتك يجب استبدال CompositeDisposable بمثيل جديد عند إعادة الاستخدام.

ومع ذلك ، يمكنك بدلاً من ذلك التفكير في تخزين نموذج العرض في MutableProperty واستخدام flatMap لتحقيق نفس الهدف.

// Assume viewModel is optional.
viewModel.producer.ignoreNil()
    .flatMap(.latest) { $0.statusLabel.producer }

بهذه الطريقة لن تضطر إلى إدارة المستهلكات بنفسك ، بينما تتم معالجة الروابط تلقائيًا عند تحديث خاصية نموذج العرض. تحتاج فقط إلى ربط هؤلاء المنتجين المسطحين مرة واحدة بوجهتهم ، على سبيل المثال في awakeFromNib .

ملاحظة: يمكنك تسوية الخصائص مباشرة في Swift 3.0.

andersio شكرا لك هذا رائع!

أيضًا ، لمعلوماتك فقط ، فقد ساعدك تفسيرك أيضًا. عندما قمت بتغيير الرمز ليكون بدلاً من ذلك:

private var disposableBindings = CompositeDisposable()

private func setupBindings() {
        disposableBindings += friendViewModel.statusLabel.producer.startWithNext({ status in
            self.statusLabel.text = status
        })
    }
}

override func prepareForReuse() {
    disposableBindings.dispose()
    disposableBindings = CompositeDisposable()
}

تستمر الإشارة حتى إعادة استخدام الخلية. أعتقد أن المشكلة كانت مني في إعادة استخدام CompositeDisposable. كنت أعامله مثل NSCache أو شيء من هذا القبيل.

شكرا لك مرة أخرى!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات