봄날은 갔다. 이제 그 정신으로 공부하자

2-1. SwiftUI Tutorial - Hashable, Codable, Identifiable 본문

iOS Tip

2-1. SwiftUI Tutorial - Hashable, Codable, Identifiable

길재의 그 정신으로 공부하자 2022. 3. 1. 22:22

이 글은 swiftUI Tutorial 중 2번째 항목인 "Building Lists and Navigation" 내용을 기반으로 소소하게 알아두면 좋은 내용을 설명합니다.

swiftUI Tutorial "Building Lists and Navigation""(아래 링크)와 같이 보시면 더욱 유익합니다.

https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

 

 

Hashable

정수 Hash 값을 제공하는 타입의 프로토콜로 구조체가 Hashable을 상속받아 사용하는 이유는 Hashable 상속받은 구조체의 인스턴스는 set 또는 dictionary의 key로 사용할 수 있기 때문 입니다.

 

set과 dictionary의 key로는 hashable한 것만 사용할 수 있기 때문에 사용자 정의 타입을 set에 넣거나 dictionary key로 만들고 싶다면 해당 타입이 타입이 반드시 hashable을 상속 받아야 합니다.

 

사용 방법은 아래와 같습니다.

import Foundation

struct Landmark: Hashable, Codable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
}

var landmarkSet = Set<Landmark>()
var landmarkDictionary: [Landmark: Int] = [ : ]

 

 

Codable

Codable은 Encodable과 Decodable이 합쳐 것으로 

Encodable은 data를 변환해주려는 프로토콜로 바꿔주는 것이고  Decodable은 data를 원하는 모델로 Decode 해주는 것 입니다.

 

자주 사용하는 json으로 예로 들면 아래와 같습니다.

  - Encodable은 모델을 json으로 인코드해주는 것이고

  - Decodable은 json을 내가 원하는 모델로 디코드해주는 것 입니다.

 

사용 방법은 아래와 같습니다.

 

읽어오려는 json 파일의 내용은 아래와 같습니다.

// landmarkData.json

[
    {
        "name": "Turtle Rock",
        "category": "Rivers",
        "city": "Twentynine Palms",
        "state": "California",
        "id": 1001,
        "isFeatured": true,
        "isFavorite": true,
        "park": "Joshua Tree National Park",
        "coordinates": {
            "longitude": -116.166868,
            "latitude": 34.011286
        },
        "description": "Suscipit inceptos est felis purus aenean aliquet adipiscing diam venenatis, augue nibh duis neque aliquam tellus condimentum sagittis vivamus, cras ante etiam sit conubia elit tempus accumsan libero, mattis per erat habitasse cubilia ligula penatibus curae. Sagittis lorem augue arcu blandit libero molestie non ullamcorper, finibus imperdiet iaculis ad quam per luctus neque, ligula curae mauris parturient diam auctor eleifend laoreet ridiculus, hendrerit adipiscing sociosqu pretium nec velit aliquam. Inceptos egestas maecenas imperdiet eget id donec nisl curae congue, massa tortor vivamus ridiculus integer porta ultrices venenatis aliquet, curabitur et posuere blandit magnis dictum auctor lacinia, eleifend dolor in ornare vulputate ipsum morbi felis. Faucibus cursus malesuada orci ultrices diam nisl taciti torquent, tempor eros suspendisse euismod condimentum dis velit mi tristique, a quis etiam dignissim dictum porttitor lobortis ad fermentum, sapien consectetur dui dolor purus elit pharetra. Interdum mattis sapien ac orci vestibulum vulputate laoreet proin hac, maecenas mollis ridiculus morbi praesent cubilia vitae ligula vel, sem semper volutpat curae mauris justo nisl luctus, non eros primis ultrices nascetur erat varius integer.",
        "imageName": "turtlerock"
    },
    ... 
]

 

다음으로 landmarkData.json 파일을 저장할 coable 구조체 Landmark를 아래와 같이 선언해 줍니다. 

import Foundation
import SwiftUI
import CoreLocation

struct Landmark: Hashable, Codable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
    
    private var imageName: String
    var image: Image {
        Image(imageName)
    }
    ...
}

 

다음으로 landmarkData.json 파일을 읽어올 load 함수를 생성해줍니다.

import Foundation

func load<T: Decodable>(_ filename: String) -> T {
    let data: Data
    
    guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else {
        fatalError("Couldn't find\(filename) in main bundle.")
    }
    
    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }
    
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}

 

생성한 load() 함수를 사용하여 "landmarkData.json" 파일에서 데이터를 읽어와 dictionary 형태로 생성해줍니다.

 

Identifiable

Identifiable 프로토콜은 해당 프로토콜을 상속받은 구조체를 식별 가능하게 하는 프로토콜로 아래와 같이 선언 되어 있습니다.

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
public protocol Identifiable {

    /// A type representing the stable identity of the entity associated with
    /// an instance.
    associatedtype ID : Hashable

    /// The stable identity of the entity associated with this instance.
    var id: Self.ID { get }
}

 

Identifiable을 상속 받은 구조체는 반드시  id 프로퍼티를 추가해야합니다.

구조체에 id를 추가하지 않으면 에러 납니다.

사용 방법은 아래와 같습니다.

struct Landmark: Hashable, Codable, Identifiable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
    
    private var imageName: String
    var image: Image {
        Image(imageName)
    }
    ...
}

'iOS Tip' 카테고리의 다른 글

3-1. SwiftUI Tutorial - List filter & sort  (0) 2022.03.08
2-2. SwiftUI Tutorial - List  (0) 2022.03.04
1. SwiftUI Tutorial - @main, @State, @Binding  (0) 2022.02.25
swift optional 제거 방법  (0) 2022.02.22
ViewController 호출  (0) 2022.02.10
Comments