ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Ch2. NSManagedObject Subclasses
    Ray Wenderlich/CoreData 2022. 10. 27. 22:33

    Modeling your data

    XCode Editor에서 attribute를 원하는대로 추가할 수 있다. 원하는 이름과 타입을 선언하면 된다. 타입은 매우 종류가 많다.

    Boolean, Date, Double, String, Integer16, Integer32, Integer64, UUID, URI 등

    그리고 Binary Data도 있다. (blob형태로 저장하는 기능이 지원됨)

    그런데 바이너리를 저장했다가는 이 엔티티에 접근할 때마다 바이너리 데이터가 메모리에 올라가기 때문에 비효율적이다. XCode는 이를 방지하고자 Attributes Inspector에서 Allows External Storage옵션을 제공한다.

    Allows External Storage → 데이터베이스에 바로 파일을 저장하지 않고 별도의 저장소에 저장한 뒤 포인터만 데이터베이스에 저장한다. 이 옵션은 Binary Data타입에만 사용할 수 있다.

    Storing non-standard data types in Core Data

    UIColor같은 값을 저장할 수 있을까? UIColor를 data로 변환하고 이를 저장하는 방법이 있을 수 있겠다.

    하지만 Attribute에는Transformable이라는 타입이 있다. 하지만 이 타입을 사용하기 위해서는 3가지 과정이 필요하다.

    1. 저장하려는 타입이 NSSecureCoding 프로토콜을 따라야 한다.
    2. NSSecureUnarchiveFromDataTransformer의 서브클래스를 생성한 뒤 register해야한다.
    3. 커스텀 Data Transformer 서브클래스와 저장하려는 타입을 연결해주어야 한다. (Core Data 에디터에서 해주면 됨)
    class ColorAttributeTransformer: NSSecureUnarchiveFromDataTransformer {
      override static var allowedTopLevelClasses: [AnyClass] {
        [UIColor.self]
      }
      
      static func register() {
        let className = String(describing: ColorAttributeTransformer.self)
        let name = NSValueTransformerName(className)
        let transformer = ColorAttributeTransformer()
        
        ValueTransformer.setValueTransformer(transformer, forName: name)
      }
    }
    

    Managed object subclasses

    이전 챕터에서 Entity의 Attribute에 접근하기 위해 Key-Value coding을 사용했다.

    person.setValue(aName, forKeyPath: "name") // Set
    let name = person.value(forKeyPath: "name") // Get
    

    이렇게 KVC를 사용해도 좋지만 직접 프로퍼티로 접근하는 것이 훨씬 안전하다.

    XCode는 Manually or Automatically 서브클래스를 생성한다. 즉, 우리가 코드로 Entity에 해당하는 클래스를 만들지 않더라고 어딘가에 XCode가 생성해둔다는 것이다. XCode8부터 엔티티별로 서브클래스를 생성하는 방식을 선택할 수 있다. (자동으로 생성하면 Derived Data에 저장됨)

    Data Model Inspector에서 Codegen에서 Manual/None을 선택해보자.

    이 작업은 컴파일을 하기 전에 하도록 하자. 컴파일을 하면 XCode가 이미 Derived Data에 서브클래스를 생성하기 때문에 컴파일 이후에 이 옵션으로 변경하면 클래스가 중복으로 선언되는 것과 같다.

    Editor/Create NSManagedObject Subclass에서 엔티티를 선택하고 서브클래스를 생성하면 SubClass+CoreDataClass.swift, SubClass+CoreDataProperties.swift 2개의 파일이 생성된다.

    // BowTie+CoreDataClass.swift
    
    import Foundation
    import CoreData
    
    @objc(BowTie)
    public class BowTie: NSManagedObject {
    
    }
    
    // BowTie+CoreDataProperties.swift
    
    import Foundation
    import CoreData
    import UIKit
    
    extension BowTie {
    
        @nonobjc public class func fetchRequest() -> NSFetchRequest<BowTie> {
            return NSFetchRequest<BowTie>(entityName: "BowTie")
        }
    
        @NSManaged public var name: String?
        @NSManaged public var isFavorite: Bool
        @NSManaged public var lastWorn: Date?
        @NSManaged public var rating: Double
        @NSManaged public var searchKey: String?
        @NSManaged public var timesWorn: Int32
        @NSManaged public var id: UUID?
        @NSManaged public var url: URL?
        @NSManaged public var photoData: Data?
        @NSManaged public var tintColor: UIColor?
    
    }
    
    extension BowTie : Identifiable {
    
    }
    

    @dynamic 키워드와 마찬가지로 @NSManaged 키워드도 Swift 컴파일러에게 이 프로퍼티는 Objective-C의 런타임을 사용할 것임을 알려준다. 일반적으로 인스턴스 변수는 메모리에 올라가게 된다. Managed object의 프로퍼티는 조금 다르다. Managed Object Context의 도움을 받기 때문에 컴파일타임에 이 데이터의 원천을 알 수 없다. (원문: The normal pattern is for a property to be backed by an instance variable in memory. A property on a managed object is different: It’s backed by the managed object context, so the source of the data is not known at compile time.)

    Data validation in Core Data

    Data Model Editor에서는 데이터의 Validation을 지정할 수 있다. 예를 들어, Double 타입의 Attribute는 min, max 값을 가질 수 있다. 만약 이 범위를 벗어나는 값을 save하려고 하면 에러가 발생할 것이다.

    'Ray Wenderlich > CoreData' 카테고리의 다른 글

    Ch8. Measuring & Boosting Performance  (0) 2022.10.31
    Ch7. Unit Testing  (0) 2022.10.31
    Ch6. Versioning & Migration  (0) 2022.10.27
    Ch5. NSFetchedResultsController  (0) 2022.10.27
Designed by Tistory.