2015-12-28 1 views
1

Я пытаюсь наблюдать изменения значений NSMutableArray в объекте, написанном в ObjectiveC. Однако наблюдатель является UIViewController, написанным в Свифте. Я не могу получить уведомления KVO. Это мои изменения:Может ли UIViewController, написанный в Swift, действовать как наблюдатель для объекта, написанного в ObjC

@interface Record : BaseObject 
@property (nonatomic) NSMutableArray *commentsArray; 


-(NSUInteger) countOfCommentsArray { 
    return _commentsArray.count; 
} 
-(id) objectInCommentsArrayAtIndex:(NSUInteger)index { 
    return [_commentsArray objectAtIndex:index]; 
} 
-(void) insertObject:(Comment *)comment inCommentsAtIndex:(NSUInteger)index { 
    [_commentsArray insertObject:comment atIndex:index]; 
} 

-(void) insertComments:(NSArray *)array atIndexes:(NSIndexSet*)indexes { 
    [_commentsArray insertObjects:array atIndexes:indexes]; 
} 

-(void) removeCommentsAtIndexes:(NSIndexSet *)indexes { 
    [_commentsArray removeObjectsAtIndexes:indexes]; 
} 

-(void) removeObjectFromCommentsAtIndex:(NSUInteger)index { 
    [_commentsArray removeObjectAtIndex:index]; 
} 
-(void) replaceObjectInCommentsAtIndex:(NSUInteger)index withObject:(id)object { 
    [_commentsArray replaceObjectAtIndex:index withObject:object]; 
} 

BaseObject происходит от NSObject.

В моем классе Observer, который является Viewcontroller и написан в Swift, у меня есть следующее.

В одном из способов установки.

myInspectionRecord?.addObserver(self, forKeyPath: "commentsArray", options: NSKeyValueObservingOptions.New, context: nil); 

У меня есть метод overrriden.

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 
     print("Value Changed"); 
    } 

Но почему-то, когда я добавить новый объект в массив, используя сам API, то observeValue метод не кажется, срабатывать. Любые указатели на то, что мне здесь не хватает? Или не работает KVO между файлами Swift и Objective C?

Любая помощь будет оценена по достоинству. Спасибо!

+0

Связанный: http://stackoverflow.com/questions/24092285/ is-key-value-monitoring-kvo-available-in-swift – kennytm

+0

Является ли 'myInspe ctionRecord' фактически указывает на конечный объект, который вы хотите наблюдать, ко времени выполнения кода? Другими словами: поставьте точку останова на строку 'addObserver' и посмотрите, является ли' myInspectionRecord' 'nil'. Если вы назначаете эту переменную, перед ее установкой обязательно всегда регистрируйте и перерегистрируйте. – DarkDust

+0

BTW, так как ваш класс Swift происходит от 'UIViewController' (и, следовательно, от' NSObject'), KVO отлично работает с ним. – DarkDust

ответ

0

Вы использовали код ключа для многих - (!) В соответствии с Apple's KVC guide, но имена методов неверны.

Поскольку ваше имущество называется commentsArray, все методы должны включать это полное имя. Например, ваш insertObject:inCommentsAtIndex: должен быть назван insertObject:inCommentsArrayAtIndex:.

В соответствии с this answer это должно дать вам бесплатные звонки KVO, но вы должны их фактически называть: компилятор, похоже, осознает, что ему необходимо ввести требуемые вызовы KVO для этих методов.

Проблема сейчас с вашим кодом, ни один из ваших методов изменить свойство и даже если компилятор впрыснуть Кво код, он будет делать это для неправильного ключа пути (comments вместо commentsArray). Есть два решения: кажется, что эти KVC-методы дают вам KVO бесплатно, но я никогда не использовал эту магию, поэтому по опыту я не знаю, будет ли это работать. Это должно быть.

Там является «грубой силы» способ, которым вы могли бы использовать, если вы хотите изменить массив в совершенно другим способом: вызовите KVO methods willChangeValueForKey: and didChangeValueForKey: или даже лучше, willChange:valuesAtIndexes:forKey: and didChange:valuesAtIndexes:forKey: себя, как это:

[self willChangeValueForKey:NSStringFromSelector(@selector(commentsArray))]; 
// Modify commentsArray 
[self didChangeValueForKey:NSStringFromSelector(@selector(commentsArray))]; 

// or better, for an insertion: 

NSIndexSet *set = [NSIndexSet indexSetWithIndex:someIndex]; 
NSString *key = NSStringFromSelector(@selector(commentsArray)); 
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:set forKey:key]; 
[_commentsArray insertObject:someObject atIndex:someIndex]; 
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:set forKey:key]; 

(Мне нравится использовать NSStringFromSelector(@selector(commentsArray)) вместо @"commentsArray", так как компилятор тогда знает, что это селектор, и рефакторинг затем предупредит вас, когда вы переименуете свойство, например.)

+0

Имущество не должно меняться - до тех пор, пока массив изменяется с помощью тех специально названных методов, вы получите уведомления об изменениях для вставок/удалений в этом массиве. Вы правы в названии, но это главная проблема. Хорошее место. Я думаю, что если OP фиксирует их как «insertObject: inCommentsArrayAtIndex:», тогда уведомления KVO будут работать. –

+0

Спасибо. Это помогло. Эта переменная раньше называлась 'comments'. Полагаю, причина, по которой Xcode предложил метод. Исправлены имена методов, и это сработало. –

Смежные вопросы