【问题标题】:Observing NSMutableArray , used Array Accessors but still no luck观察 NSMutableArray ,使用了数组访问器,但仍然没有运气
【发布时间】:2013-09-13 10:12:37
【问题描述】:

我想在我的班级 cSoundChannel 中观察 NSMutableArray。因此,在阅读了这篇文章后 Observing an NSMutableArray for insertion/removal 我以这种方式实现了关键观察。

对于 cSoundChanel 类,

可变数组的属性是

 @property (assign, nonatomic) NSMutableArray* midiDevices;

我在类中使用kvo数组访问器介绍的函数如下:

- (void) addmidiDevicesObject:(NSObject *) str {
    [self insertObject:str inMidiDevicesAtIndex:[_midiDevices count]];
}

- (void)insertObject:(NSObject *)str inMidiDevicesAtIndex:(NSUInteger)index {
    [self.midiDevices insertObject:str atIndex:index];
    return;
}

对于需要观察 midiDevices 的 ViewController.m 文件,我做了以下操作。

[self.cSoundChannel addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

并期望能够在 ...

中观察可变数组
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"midiDevices"]) {
        NSLog(@"Let's see!");
    }
}

但是,唉...它没有打印“让我们看看!” 观察其他东西...... NSString 等工作......

有什么我错过的吗?帮助!

【问题讨论】:

  • 你在哪个类中拥有每一部分的代码?最重要的是 -(void)observeValueForKeyPath: 在同一个类中作为观察者在 addObserver:self 中发送。
  • 您好,我编辑了课程,谢谢...

标签: ios objective-c arrays nsmutablearray


【解决方案1】:

您的代码在midiDevices 上不完全符合 KVC。你还需要实现removeObjectFromMidiDevicesAtIndex:

- (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices removeObjectAtIndex:index];
}

详情请参阅Key-Value Coding Programming Guide。具体请参阅可变索引访问器。


编辑:以下示例代码演示了我所描述的内容,并打印“让我们看看!”正如预期的那样。删除 removeObjectFromMidiDevicesAtIndex: 将重新引入 OP 代码中出现的错误。

#import <Foundation/Foundation.h>

@interface Observed : NSObject
@property (nonatomic) NSMutableArray* midiDevices;
@end

@implementation Observed

- (id)init {
  self = [super init];
  if (self) {
    _midiDevices = [NSMutableArray new];
  }
  return self;
}

- (void) addmidiDevicesObject:(NSObject *) str {
  [self insertObject:str inMidiDevicesAtIndex:[_midiDevices count]];
}

- (void)insertObject:(NSObject *)str inMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices insertObject:str atIndex:index];
}

- (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index {
  [self.midiDevices removeObjectAtIndex:index];
}

@end

@interface Observer : NSObject
@property (nonatomic) Observed *observed;
@end

@implementation Observer

- (id)init {
  self = [super init];
  if (self) {
    _observed = [Observed new];
    [_observed addObserver:self forKeyPath:@"midiDevices" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  }
  return self;
}

- (void)dealloc {
  [_observed removeObserver:self forKeyPath:@"midiDevices"];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  if ([keyPath isEqualToString:@"midiDevices"]) {
    NSLog(@"Let's see!");
  }
}

@end

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    Observer *observer = [Observer new];
    [observer.observed addmidiDevicesObject:@"test"];
  }
  return 0;
}

【讨论】:

  • 这不是问题所在,也不是答案。将其更改为可能对他的代码进行注释作为提示。
  • 这是这里的问题,通过使其符合 KVC,观察者将被调用。
  • 太棒了。我只需要添加 - (void)removeObjectFromMidiDevicesAtIndex:(NSUInteger)index 正如你所说的。谢谢!
  • 我这里有个新问题。在被观察的类中的 mididevices nsmutablearray 中有超过 1 个项目的情况下,当我执行 NSMutableArray *midiDevicesArray = [change objectForKey:NSKeyValueChangeNewKey]; 时,我只看到 1 个对象。这是为什么呢?
  • 我意识到由于某种原因观察值只显示了 NSMutableArray 中的变化,并且对于添加到正在观察的数组中的 2 个项目,它被调用了 2 次。
【解决方案2】:

仅仅拥有NSMutableArray 不会让您有能力观察变化。您需要使用NSKeyValueCoding 协议创建一个可变数组 - “mutableArrayValueForKey”。这个数组是一个“特殊”数组,只要数组的内容发生变化,就会触发 KVO 消息。

这里需要两个数组。一个是我的“真实”数据,在您的情况下是 midiDevices,然后是第二个数组,以这种方式创建:

mutableMidiDevices = [self mutableArrayValueForKey:@"midiDevices"];

从这里开始,您只需向“mutableMidiDevices”添加/删除对象,根本不访问原始“midiDevices”(您需要定义的 KVO 例程除外。

这是您的 KVO 例程:

- (NSUInteger) countOfMidiDevices;
- (id) objectInMidiDevicesAtIndex:(NSUInteger)index;
- (void) replaceObjectInMidiDevicesAtIndex:(NSUInteger)index withObject:(id)object;
- (void) insertObject:(id)midiDevice inMidiDevicesAtIndex:(NSUInteger)index;
- (void) removeObjectFromMidiDevicesAtIndex:(NSUInteger)index;

我现在不确定您是否需要定义所有这些例程,但这就是我上次做 KVO 时所做的。这些例程中的每一个都应该修改 original midiDevices 数组。

因此,您的想法是从对象外部和内部添加/删除“mutableMidiDevices”。这将保证 KVO 消息触发。

在您的对象内部,您可以通过定义 KVO 例程来修改真正的“midiDevices”数组。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-23
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多