본문 바로가기
Ios/Swift UI

이것저것 Swift 메모용(찾아갈만한게 있을 수도 있고 없을 수도 있어요)

by 잘먹는 개발자 에단 2024. 7. 23.

Range<Double>

import Foundation

let range : Range<Double> = 0.0..<5.0

 

0.0 .. < 5.0 은  0.0 이상 5.0 미만

0.0 ... 5.0 은 0.0 이상 5.0 이하

 

 

 

 

구조체가 Hashable 프로토콜을 채택하는 경우

- Hashable 프로토콜은 구조체나 클래스가 해시값을 가질 수 있도록 해주는 프로토콜

- 해시 값은 특정 객체를 빠르게 찾거나 비교할 때 사용하는데, Hashable을 채택한 구조체는 Set이나 Dictionary 같은 컬렉션에서 키로 사용할 수 있게 된다. 

 

 

 

Identifiable 프로토콜

- 객체를 고유하게 식별할 수 있도록 해주는 프로토콜

- 이 프로토콜을 채택하면 객체마다 고유한 식별자를 가지게 되어, 컬렉션이나 리스트에서 특정 객체를 쉽게 찾거나 업데이트할 수 있다.

 

주요 조건은 다음과 같다.

1. id라는 이름의 프로퍼티를 !반드시! 가져야 한다. 이 id 프로퍼티는 고유한 식별자로서 보통 UUID나 기본타입(int, string)을 사용한다.

2. 프로토콜 선언 - Identifiable 프로토콜은 id 프로퍼티가 필요하다는 것만 명시할 뿐, 어떤 타입을 사용할 지는 지정하지 않는다. 따라서 id는 사용자 정의 타입도 사용이 가능하다. 

 

 

 

 

AnyTransition 프로토콜

- 뷰가 화면에 나타나거나 사라질 때 사용할 전환 애니메이션을 정의

- 이 프로토콜을 사용한다면 다양한 사용자 정의 전환효과를 적용할 수 있다.

 

Swift UI는 몇가지 기본 전환 효과를 제공한다.

- 1. slide : 뷰가 슬라이드 하면서 나타나거나 사라지게

- 2. opacity : 뷰가 투명도 변화를 통해서 나타나거나 사라지게

- 3. scale  : 뷰가 크기 변화를 통해 나타나거나 사라지게

 

 

 

var categories : [ String : [Landmark] ] {
    Dictionary (
        grouping : landmarks, 
        by : { $0.category.rawValue }
    )
}

다음 코드를 풀어봐가며 살펴보자.

- 먼저 categories는 딕셔너리인데 키는 !문자열! 값은 !랜드마크배열!이다.

    - 이 딕셔너리는 특정 기준에 따라서 그룹화된 Landmark 객체들을 저장한다.

 

- Dictionary(grouping : landmarks by : .. )

- 딕셔너리 초기화 메서드로서 landmarks 배열의 요소들을 그룹화한다.

- grouping : by : { $0.category.rawValue }는 그룹화의 기준이다. 

 

- $0은 배열의 각 요소를 가리킨다. 

코드로 살펴보면

import Foundation

struct Landmark : Identifiable, Codable{
	var id : UUID
    var name : String
    var category : Category
}

enum Category : String, CaseIterable, Codable{
	case lakes = "Lakes"
    case rivers = "Rivers"
    case mountains = "Mountains"
}



// 예제용 데이터
let landmarks = [
	Landmark( id : UUID(), name = "Lake Tahoe", Category : .lakes ),
    Landmark( id : UUID(), name = "Amazon River", Category : .rivers),
    Landmark( id : UUID(), name = "Rocky Mountain", Category : .mountains),
    Landmark( id : UUID(), name = "Nile River", Category : .rivers),
]


// 그룹화된 딕셔너리 생성
var categories : [ String : [Landmark] ] {
	Dictionary(
        grouping : landmarks,
        by : { $0.category.rawValue }
        // $0 === landmarks 각 요소인 Landmark 객체
    )
}

// 결과 출력
for (category, landmarks) in categories{
	print("\(category)")
    
    for( landmark in landmarks ){
    	print(" ---- \(landmark.name)
    }
    
    
 
}

 

이렇게 하면 출력은

Lakes :

  - Lake Tahoe

Rivers :

  - Amazon River

  - Nile River

Mountains : 

  - Rocky Mountains

 

- category에 따라서 분류했기 때문에 Rivers에는 2개가 저장된다. 다시 말해서

 

호수 : 레이크 타호

강 : 아마존 강

산 : 로키 산

강 : 나일 강

 

에서

 

 

호수 : 레이쿠 타호

강 : 아마존, 나일 강

산 : 로키 산

 

이런식으로 묶이게 된다. 

 

 

 

 

 

 

Swift Tutorials 4에 보면 다음과 같은 코드가 나온다.

import SwiftUI

struct CategoryHome: View {
    @Environment(ModelData.self) var modelData
    
    
    var body: some View {
        NavigationSplitView{
            Text("Hello world")
                .navigationTitle("Featured")
        } detail: {
            Text("select a Landmark")
        }
    }
}

#Preview {
    CategoryHome()
        .environment(ModelData())
}

1. @Environment 프로퍼티 래퍼

- @Environment는 뷰가 특정 타입의 환경 데이터를 사용하도록 해주는 프로퍼티 래퍼이다. 

- 예를 들어서, @Environment(ModelData.self) var modelData는 뷰가 ModelData 객체에 접근할 수 있게 한다. 

 

2. #Preview 에 있는 .environment(ModelData())

- 프리뷰가 독립적인 테스트 환경을 제공하기 위함이다. 

- 프리뷰는 CategoryHome이랑 같다고 생각하면 안된다.

- 별개로 동작하는 테스트용 화면이다. 

 

 

 

 

ForEach와 id : .self

- ForEach는 SwiftUI에서 리스트나 컬렉션의 각 요소를 반복하여 뷰를 생성하는데 사용한다.

- 이 때 각 요소를 고유하게 식별할 수 있는 키를 제공해야하는데, id : \.self는 각 요소 자체를 식별자로 사용한다는 것이다.