Nice programing

Core-Data의 사용자 지정 setter 메서드

nicepro 2020. 11. 7. 10:31
반응형

Core-Data의 사용자 지정 setter 메서드


foo내 하위 클래스에 있는 필드에 대한 사용자 지정 setter 메서드를 작성해야합니다 NSManagedObject. foo데이터 모델에 정의되어 있고 Xcode는 .h 및 .m 파일에 각각 자동 생성 @property@dynamic필드가 있습니다.

내 세터를 다음과 같이 작성하면 :

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

그런 다음 호출에 대한 컴파일러 경고가 나타납니다 super.

또는 이렇게하면 :

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

그런 다음 무한 루프로 끝납니다.

그렇다면 NSManagedObject의 하위 클래스에 대한 사용자 지정 setter를 작성하는 올바른 접근 방식은 무엇입니까?


다음은 .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정의를 추가하기 만하면 되는 내장 마법 방법입니다. 이 페이지 하단에 표시된대로 macOS 10.12, iOS 10.0, tvOS 10.0 및 watchOS 3.0의 핵심 데이터의 새로운 기능


문서 에 따르면 다음과 같습니다.

- (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가가는 길"처럼 들립니다.


.NET Framework의 id속성에 대해 KVO를 수행하는 방법은 다음과 같습니다 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
}

약간의 실수가 있다고 생각합니다.

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

대신에

 [self setPrimitiveFoo:inFoo];

이것은 나를 위해 작동합니다.


다음은 1-n (그리고 나는 nm로 추정) 관계를 수행하는 방법입니다.

"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];
}

참고 URL : https://stackoverflow.com/questions/2971806/custom-setter-methods-in-core-data

반응형