Swift

Swift_ CoreData Model , extension , Struct

JunsC 2024. 8. 2. 13:47
728x90

코어 데이터 모델과 일반 Struct 과 같이 사용하려고 생각했다. 

AOS 에서는 한 모델을 기준으로 Sqlite 도 같은 형변환이 될 수 있도록 치환이 가능했기 때문이다.

그 부분때문에 당연히 IOS 에서도 가능하겠지 하고 계속 시도해보았지만 잘 안됐다. 흠...

enum Gender: String, Codable {
    case M = "M"
    case F = "F"
    case NULL = "NULL"
}


enum CurrentStatus: String, Codable {
    case IN = "IN"
    case OUT = "OUT"
    case NULL = "NULL"
}

enum Time: String, Codable {
    case afternoon = "afternoon"
    case NULL = "NULL"
    case night = "night"
}

enum Grade: String, Codable {
    case A = "A"
    case B = "B"
    case C = "C"
    case D = "D"
    case E = "E"
    case NULL = "NULL"
}

struct MemberStruct: Codable, Comparable {
    var clubName: String
    var name: String
    var gender: Gender
    var memberOwnId: String
    var currentStatus: CurrentStatus
    var age: Int
    var grade: Grade
    var time: Time
    
    enum CodingKeys: String, CodingKey {
        case memberOwnId = "m_Id"
        case name
        case gender
        case currentStatus
        case clubName
        case grade
        case age
        case time
    }
    
    
    init(clubName: String = "", name: String = "", gender: Gender = .NULL, memberOwnId: String = "", currentStatus: CurrentStatus = .NULL, age: Int = 0, grade: Grade = .NULL, time: Time = .NULL) {
        self.clubName = clubName
        self.name = name
        self.gender = gender
        self.memberOwnId = memberOwnId
        self.currentStatus = currentStatus
        self.age = age
        self.grade = grade
        self.time = time
    }
    
    init() {
        self.clubName = ""
        self.name = ""
        self.gender = .NULL
        self.memberOwnId = ""
        self.currentStatus = .NULL
        self.age = 0
        self.grade = .NULL
        self.time = .NULL
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        clubName = try container.decode(String.self, forKey: .clubName)
        name = try container.decode(String.self, forKey: .name)
        gender = try container.decode(Gender.self, forKey: .gender)
        memberOwnId = try container.decode(String.self, forKey: .memberOwnId)
        currentStatus = try container.decode(CurrentStatus.self, forKey: .currentStatus)
        age = try container.decode(Int.self, forKey: .age)
        grade = try container.decodeIfPresent(Grade.self, forKey: .grade) ?? .NULL
        time = try container.decode(Time.self, forKey: .time)
    }
    
    static func < (lhs: MemberStruct, rhs: MemberStruct) -> Bool {
        return lhs.name < rhs.name
    }
    
    static func == (lhs: MemberStruct, rhs: MemberStruct) -> Bool {
        return lhs.name == rhs.name
    }
    
    func toMembers(context: NSManagedObjectContext) -> Members {
        let members = Members(context: context)
        members.clubName = self.clubName
        members.name = self.name
        members.gender = self.gender.rawValue
        members.memberOwnId = self.memberOwnId
        members.currentStatus = self.currentStatus.rawValue
        members.age = String(self.age)
        members.grade = self.grade.rawValue
        members.time = self.time.rawValue
        return members
    }
    
}

 

이 일반적인 Struct 를 하나로 전부 이용하고 싶었지만,
CoreData 에서는 CoreDataProperties.swift 파일은 Core Data의 속성 확장만을 포함해야 해서 일반적으로 이 파일에 메서드 확장보다는 속성 관련 코드만 넣는다고 한다.

따라서, 별도의 extension으로 정의하는 것이 좋다고 하는 ChatGpt 의 말에 따라 하는 수 없이 별도 분리를 하는 수밖에 없었다.

 

//
//  Members+CoreDataProperties.swift
//
//
//  Created by macbookpro on 7/24/24.
//
//

import Foundation
import CoreData


extension Members  {
    
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Members> {
        return NSFetchRequest<Members>(entityName: "Members")
    }
    
    @NSManaged public var clubName: String?
    @NSManaged public var name: String?
    @NSManaged public var gender: String?
    @NSManaged public var memberOwnId: String?
    @NSManaged public var currentStatus: String?
    @NSManaged public var age: String?
    @NSManaged public var grade: String?
    @NSManaged public var time: String?
    
    
    
    
    func update(from member: MemberStruct) {
        self.clubName = member.clubName
        self.name = member.name
        self.gender = member.gender.rawValue
        self.memberOwnId = member.memberOwnId
        self.currentStatus = member.currentStatus.rawValue
        self.age = String(member.age)
        self.grade = member.grade.rawValue
        self.time = member.time.rawValue
    }
    
    
    func toMemberStruct() -> MemberStruct? {
        guard
            let clubName = self.clubName,
            let name = self.name,
            let gender = self.gender,
            let memberOwnId = self.memberOwnId,
            let currentStatus = self.currentStatus,
            let ageString = self.age,
            let age = Int(ageString),
            let grade = self.grade,
            let time = self.time
        else {
            return nil
        }
        return MemberStruct(
            clubName: clubName,
            name: name,
            gender: Gender(rawValue: gender) ?? .NULL,
            memberOwnId: memberOwnId,
            currentStatus: CurrentStatus(rawValue: currentStatus) ?? .NULL,
            age: age,
            grade: Grade(rawValue: grade) ?? .NULL,
            time: Time(rawValue: time) ?? .NULL
        )
    }
    
    
    override public var description: String {
        return """
            Member{
                clubName: \(String(describing: clubName)),
                name: \(String(describing: name)),
                gender: \(String(describing: gender)),
                memberOwnId: \(String(describing: memberOwnId)),
                currentStatus: \(String(describing: currentStatus)),
                age: \(String(describing: age)),
                grade: \(String(describing: grade)),
                time: \(String(describing: time))
            }
            """
    }
    
}

 

위의 코드는 이제 잘못된 코드이다.. 

저런 부가적인 함수들은 따로 extension 파일을 만들어 정리하도록 해야겠다.

 

그렇다면 내가 이해한 바로는 , 

코어데이터와 일반적인 Struct 는 각 독립적인 모델로 생각해야 하고 서로 상호호환을 하려면 형변환을 해주어야 한다는 의미로 생각되었당

그래서 우선 코어데이터로 저장하는건 코어데이터 모델을 사용하고 그리고 그 데이터를 가져올땐 Struct 로 형변환 후 사용하는 것이 깔끔한듯 하다

AOS IOS 각각의 장단점이 있는 듯 하다..