SWIFTUI/Grammar

SwiftUI : Identifiable protocol

서근 2021. 5. 3. 12:48
반응형

Identifiable 

SwiftUI에서 identifiable은 자주 쓰이기 때문에 반드시 알아둬야 할 프로토콜입니다. 이것에 대해 알아보기 전에 이 프로토콜이 생겨난 배경에 대해서 먼저 알아보도록 하겠습니다.

 

만약 앱 내에 다음 Product 구조체타입을 정의했다고 가정해보도록 하겠습니다.

Struct Product {
 let name: String 
 let price: Int
}

그리고 Product 타입을 사용하여 제품명과 가격이 같은 객체를 생성해보도록 하겠습니다.

let PS5 = Product(name: "controller", price: 100)
let PS4 = Product(name: "controller", price: 100)

이것을 Equatable 프로토콜을 채택하고 바교해보면 서로 다른 종류의 제품을 의도했더라도 같은 타입에 이름과 가격이 모두 같으므로 결과는 true가 됩니다.

 

그런데 만약 고유 값을 통해 각각을 구분할 수 있도록 id 프로퍼티를 추가해준다면 어떨까요? 

Struct Product {
 let name: String 
 let price: Int
 let id: Int
}

let PS5_1 = Product(id: 1, name: "controller", price: 100)
let PS5_2 = Product(id: 1, name: "controller", price: 120)

자 이렇게 비교해보면 PS5_1PS5_2false입니다. 두 개가 같은 제품이라고 해도 가격이 달라졌기 때문에 같지 않다는 결과가 나온 것이죠. 하지만 이 제품의 동일 여부를 판단하려면 id 값을 비교해보면 됩니다.

PS5_1 == PS5_2  // false

PS5_1.id == PS5_2.id  // true

Identifiable Protocol

Identifiable프로토콜은 Hashable프로토콜을 준수하는 id 프로퍼티 하나만 가지는 아주 단순한 프로토콜 입니다.

public protocol Identifiable {
  associatedtype ID: Hashable 
  var id: self.ID { get }
}

이 프로토콜을 채택한 타입은 고유 개채를 구분하기 위해서 비교 알고리즘에 이 id를 사용하게 되고 id가 다르다면 서로 다른 대상이 되는 것이며 값이 다르더라고 id가 같으면 동일한 개체로 구분되게 되는 것입니다.

 

따라서 ProductIdentifiable을 채택했다면 앞에서 구현했던 id가 필수가 되겠죠 :)  각 개체는 특정 상태와 관계없이 언제나 id에 의해 고유 개체로 구분될 수 있는 것입니다.

SwiftUI ⭐️

SwiftUI에서 ListForEach처럼 데이터를 나열하는 뷰 또는 alert, actionSheet처럼 화면을 띄울 항목을 정확히 구분지어야 할 때 Identifiable프로토콜을 요구하게 됩니다. 

 

따라서 여기에 사용되는 데이터는 데이터 간 식별이 가능하다도록 id를 제공해야 합니다.

 

예를 들어서 Listidentifiable 프로토콜을 적용하지 않았을 경우에 컴파일러가 어느 것을 식별자로 사용해야 하는지 알 수 없기 때문에 id로 사용할 항목을 매게 변수에 전달해줘야 합니다.

 

다이내믹 리스트를 만들어보겠습니다.

 

Animal이라는 구조체를 만들어주고 Identifiable프로토콜을 적용해주겠습니다. 그리고 UUID라는 변수도 아래와 같이 적어줘야 합니다.

sturct Animal: Identifiable {
  var id = UUID()
  var name: String
}

그리고 AnimalRow 뷰를 하나 만들어주고 그 아래에 Text를 작성합니다.

struct AnimalRow: View {
    var animal: Animal
    var body: some View {
        Text("현재 동물원에 있는 동물 = \(animal.name)")
    }
}

이제 contenView에 아래와 같이 코드를 넣어주면 됩니다.

struct ContentView: View {
    var body: some View {
        
        let first = Animal(name: "사자")
        let second = Animal(name: "호랑이")
        let third = Animal(name: "팬더")
        let Animals = [first,second,third]
        
        return List(Animals) { animal in
            AnimalRow(animal: animal)
        }
    }
}

만약 Identifiable을 채택하지 않으면 런타임 오류가 발생하기 때문에 반드시 Identifiable을 채택해줘야 합니다.

 

 

읽어주셔서 감사합니다🤟