ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Core Data) CoreData에서 enum 값으로 검색하기
    iOS 2021. 8. 16. 17:05

    enum 값을 가지는 NSManagedObject를 enum 값에 따라 filtering 하고 싶었습니다.

     

    그런데 별 짓을 다해봐도 쉽지않더라구요 ... 사실 NSPredicate로 enum 값을 비교할 수 있겠지 싶었는데, NS가 붙은 걸 보면 알 수 있듯이 Objective-C 프레임워크라 enum의 개념이 없다고 하네요.

    결국 enum이 아닌 기본 타입을 저장해야 될 것 같았어요😩 마지막이라고 생각하고 아래의 참고 문서를 따라해봤습니다.

    https://stackoverflow.com/questions/60142435/issue-with-fetching-core-data-managed-object-using-nspredicate-by-objects-enum

    그리고 성공했습니다! 사실 enum 값으로 검색하는 건 아니지만 어쨌든 의도하는 바를 이루었으니 한번 같이 살펴볼게요 💡

     

     

    예시 상황을 설정해 볼게요!

    악기(Instrument)라는 엔티티가 있고, 애트리뷰트로 type을 가지고 있을 거에요.

    이 애트리뷰트는 Int16을 rawValue로 가지는 enum 입니다.

    @objc
    public enum InstrumentType: Int16 {
        case string,
        case wind,
        case percussion 
    }

    코드로 보면 이렇게 구성되어 있겠죠? CoreData에 enum을 저장할 때는 이런 식으로 원시값을 가지는 enum으로 만들어줍니다.

     

    extension Instrument {
        @NSManaged public var name: String
        @NSManaged public var type: InstrumentType
    }

    Instrument 엔티티에는 다음과 같이 2가지 애트리뷰트를 가집니다. (예시니까 최소한으로 ㅎㅎ) 물론 지금은 xcdatamodel 파일에서 엔티티의 codegen을 manual로 설정해서 NSManagedObject subclassing 파일을 만들어 준 상태에요.

     

     

    이제 이 instrumentType으로 검색하기 위한 변수를 추가해주겠습니다.

    extension Instrument {
        @NSManaged public var name: String
        @NSManaged private var typeValue: Int16
    
    public var type: InstrumentType {
        get {
            return InstrumentType(rawValue: self.typeValue)! }
        }
        set {
            self.typeValue = newValue.rawValue
        }
    }

     

    먼저 type 변수를 Int16 typeValue으로 변경해줬습니다. 이제 core data store에는 이 변수가 저장 될거에요.

    또한 이 변수를 이용하여 접근하지 않을 것이기 때문에 private로 접근지정자를 설정해주었어요.

     

     

     

     

    그럼 원래의 type은요 ?

     

    원래의 type 변수는 get-set을 가지는 computed property(연산 프로퍼티)로 지정해줍니다. get을 할 때는 저장된 typeValue로 InstrumentType을 생성해서 반환해주고, set을 할 때는 대입해준 InstrumentType의 rawValue를 typeValue에 대입해줍니다.

    결국엔 typeValue의 값을 InstrumentType으로 변환해서 뱉어주거나

    InstrumentType의 값을 typeValue로 변환해서 저장해주는 중간 역할(?)을 해주게 됩니다.

     

     

     

    자 이제 검색을 해봅시다.

    let request: NSFetchRequest<Instrument> = Instrument.fetchRequest()
    
    let instrumentType: InstrumentType = .string
    let predicate = NSPredicate(format: "typeValue == %d", instrumentType.rawValue)
    request.predicate = predicate 
    
    let instruments = try! context.fetch(request)

    검색을 위한 NSPredicate를 생성했습니다. int16 타입으로 검색해주기 때문에 %d로 argument를 지정해주면 해당 case의 int16 값으로 filtering되어서 결과들을 얻을 수 있어요!

     

     

     

    CoreData에서 enum 사용은 꽤나 까다롭네요 🥲

     

     

     

     

    암튼 누군가에겐 도움이 되길 바라며,,,

     

     

     

     

    댓글

Designed by Tistory.