代码之家  ›  专栏  ›  技术社区  ›  Andrew Ebling

核心数据中的自定义setter方法

  •  66
  • Andrew Ebling  · 技术社区  · 15 年前

    我需要为字段编写一个自定义setter方法(我们将调用它 foo )在我的子类 NSManagedObject . 在数据模型中定义,Xcode已自动生成 @property @dynamic .h和.m文件中的字段。

    如果我这样写设置器:

    - (void)setFoo: (NSObject *)inFoo {
        [super setFoo: inFoo];
        [self updateStuff];
    }
    

    然后在调用 super .

    或者,如果我这样做:

    - (void)setFoo: (NSObject *)inFoo {
        [super setValue: inFoo forKey: inFoo];
        [self updateStuff];
    }
    

    然后我进入了一个无限循环。

    那么,为nsmanagedObject的子类编写自定义setter的正确方法是什么?

    5 回复  |  直到 7 年前
        1
  •  6
  •   malhal Benzy Neez    7 年前

    下面是在.m中覆盖nsmanagedObject属性(不破坏kvo)的Apple方法:

    @interface Transaction (DynamicAccessors)
    - (void)managedObjectOriginal_setDate:(NSDate *)date;
    @end
    
    @implementation Transaction
    @dynamic date;
    
    - (void)setDate:(NSDate *)date
    {
        // invoke the dynamic implementation of setDate (calls the willChange/didChange for you)
        [self managedObjectOriginal_setDate:(NSString *)date;
    
        // your custom code
    }
    

    managedObjectOriginal_propertyName 是内置的 魔术 方法,您只需添加的定义。如本页底部所示 What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0

        2
  •  101
  •   Gabriele Petronella    12 年前

    根据 the documentation 应该是:

    - (void) setFoo:(NSObject *)inFoo {
      [self willChangeValueForKey:@"foo"];
      [self setPrimitiveValue:inFoo forKey:@"foo"];
      [self didChangeValueForKey:@"foo"];
    }
    

    当然,这忽略了 NSManagedObjects 只想 NSNumbers , NSDates , NSDatas NSStrings 作为属性。

    然而,这可能不是最好的方法。因为你想在你的价值 foo 属性改变,为什么不只是观察它 Key Value Observing ?在这种情况下,这听起来像是“kvo的方法”。

        3
  •  19
  •   ma11hew28    14 年前

    以下是我在 id A的属性 Photo : NSManagedObject . 如果照片的ID发生更改,请下载新照片。

    #pragma mark NSManagedObject
    
    - (void)awakeFromInsert {
        [self observePhotoId];
    }
    
    - (void)awakeFromFetch {
        [self observePhotoId];
    }
    
    - (void)observePhotoId {
        [self addObserver:self forKeyPath:@"id"
                  options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:NULL];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change
                           context:(void *)context {
        if ([keyPath isEqualToString:@"id"]) {
            NSString *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
            NSString *newValue = [change objectForKey:NSKeyValueChangeNewKey];        
            if (![newValue isEqualToString:oldValue]) {
                [self handleIdChange];
            }
        }
    }
    
    - (void)willTurnIntoFault {
        [self removeObserver:self forKeyPath:@"id"];
    }
    
    #pragma mark Photo
    
    - (void)handleIdChange {
        // Implemented by subclasses, but defined here to hide warnings.
        // [self download]; // example implementation
    }
    
        4
  •  17
  •   Martin Brugger    15 年前

    我认为有一个小错误: 使用

     [self setPrimitiveValue:inFoo forKey:@"foo"];
    

    而不是

     [self setPrimitiveFoo:inFoo];
    

    这对我有用。

        5
  •  0
  •   David    9 年前

    以下是你如何处理1-n(我假设n-m)关系:

    假设关系名称在名为“school”的对象中称为“students”。

    首先,您需要为nsmutableset定义基本访问器方法。Xcode不会自动为您生成这些。

    @interface School(PrimitiveAccessors)
    - (NSMutableSet *)primitiveStudents;
    @end
    

    接下来,您可以定义访问器方法。在这里我要重写setter。

    - (void)addStudentsObject:(Student *)student
    {
      NSSet *changedObjects = [[NSSet alloc] initWithObjects:&student count:1];
    
      [self willChangeValueForKey:@"students"
                  withSetMutation:NSKeyValueUnionSetMutation
                     usingObjects:changedObjects];
    
      [[self primitiveStudents] addObject:value];
    
      [self didChangeValueForKey:@"students"
                 withSetMutation:NSKeyValueUnionSetMutation
                    usingObjects:changedObjects];
    }
    
    推荐文章