تغيير قيم القاموس خطأ عند استخدام KVO مع nsoperationqueue؟
-
26-09-2019 - |
سؤال
كنت أعمل من خلال مثال في الفصل التزامن من "More iPhone 3 Development" ، ولا يمكنني الحصول على KVO على NSOperationQueue
العمل كما هو متوقع. أنا إنشاء NSOperationQueue
ومراقبة operations
صفيف باستخدام:
NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
self.queue = newQueue;
[newQueue release];
[queue addObserver:self
forKeyPath:@"operations"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:NULL];
عندما يكون الأول NSOperation
يضاف إلى قائمة الانتظار ، وأتوقع أن تتم إضافتها إلى الأساس operations
Array (التي تقول وثائق iOS إنها متوافقة مع KVO) وبالتالي ، في قاموس التغيير ، لإيجاد رسم خرائط من NSKeyValueChangeKindKey
ل NSKeyValueChangeInsertion
, ، جنبا إلى جنب مع رسم الخرائط من NSKeyValueChangeNewKey
إلى المضافة NSOperation
. لكنني لم أر أي نوع من القيمة NSKeyValueChangeInsertion
.
أعلم أن تصحيح الأخطاء مؤيد وجميع ، ولكن من مصلحة شيء مفيد لنسخه هنا ، بدأت طريقة المراقب الخاصة بي مع:
- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
NSObject *newValue = [change objectForKey:NSKeyValueChangeNewKey];
NSObject *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
NSIndexSet *indexes = [change objectForKey:NSKeyValueChangeIndexesKey];
NSLog(@"kind=%d, newValue=%@, oldValue=%@, indexes=%@",
[kind integerValue], newValue, oldValue, indexes);
وهذا يطبع:
2010-11-18 20:01:56.249 Stalled[2692:6f07] kind=1, newValue=(
"<SquareRootOperation: 0x5f51b40>"
), oldValue=(
), indexes=(null)
2010-11-18 20:01:56.250 Stalled[2692:6f07] kind=1, newValue=(
"<SquareRootOperation: 0x5f51b40>"
), oldValue=(
"<SquareRootOperation: 0x5f51b40>"
), indexes=(null)
(SquareRootOperation
هو ببساطة الفئة الفرعية الخاصة بي من NSOperation
هذا يتجاوز main
بشكل مناسب ، و Stalled
هو ببساطة اسم المشروع.) ولكن لاحظ أن الطريقة تسمى مرتين عند إدخال عملية واحدة ، وفي كلتا الحالتين بقيمة لطيفة 1 ، وهي NSKeyValueChangeSetting
, ، ليس NSKeyValueChangeInsertion
. بالإضافة إلى ذلك، newValue
و oldValue
يبدو أن الصفيف نفسه ، وليس العنصر المضافة.
أيه أفكار؟ شكرًا!
المحلول
تقول المستندات -operations
هو متوافق مع KVO ، ولكن لا تحدد التفاصيل التي ستكون عليها الإخطارات. في الممارسة العملية ، يبدو أنك قيل لك فقط أن التغيير قد حدث ، لذلك يجب أن تقارن القيم القديمة والجديدة لمعرفة ما تم إدراجه.
لا تنسى أن هذه الإشعارات يمكن إرسالها إليك على أي موضوع!
نصائح أخرى
خاصية عمليات nsoperationQueue لا تحتوي على نوع قابل للتغيير (يعود NSArray*
). وبالتالي ، فهي لا تنفذ أساليب الامتثال المفهرسة للصفائف القابلة للتغيير ، لذا لن ترى أبدًا أحداث الإدراج ، فقط حدث التغيير للمصفوفة بأكملها.
تعديل
لقد طرح Shadowmatter حقيقة أن الكائن الذي تم إرجاعه فعليًا هو NSMutableArray
. هذا لا يغير أي شيء. أولاً، وثائق Apple واضح بشأن هذه القضية. إذا تم الإعلان عن طريقة لإرجاع كائن ثابت ، فيجب عليك احترام واجهة برمجة التطبيقات. يجب ألا تستخدم isKindOf:
لمعرفة ما إذا كان قابلاً للتغيير حقًا ويجب بالتأكيد عدم تغييره.
تقول واجهة برمجة التطبيقات إن نوع إرجاع العمليات غير قابل للتغيير ، وبالتالي يجب أن تعامله على هذا النحو. الأهم من ذلك بالنسبة لهذا السؤال ، لأنه ليس خاصية مجموعة قابلة للتغيير ، فهي ليست متوافق مع ترميز القيمة الرئيسية لقيم الصفيف القابلة للتبديل KVC. للامتثال لجمع المفهرسة القابلة للتغيير ، يتعين على الفصل
- تنفيذ واحدة أو كليهما من الأساليب
-insertObject:in<Key>AtIndex:
أو-insert<Key>:atIndexes:
.- تنفيذ واحدة أو كليهما من الأساليب
-removeObjectFrom<Key>AtIndex:
أو-remove<Key>AtIndexes:
.
(مأخوذة مباشرة من دليل Apple KVC)
مصمم NSOperationQueue
فئة صمم operations
الخاصية على أنها غير قابلة للتغيير وبالتالي تعمد الأساليب المذكورة أعلاه.