Lecture 6: Protocol Shapes

강의 링크

# 프로토콜에서도 제너릭을 쓸 수 있다..!

  • 대신 프로토콜에서 제너릭을 쓰려면 < > 이 아니라 associated type 키워드를 통해 선언한다
protocol Identifiable {
    associatedtype ID: Hashable
    var id: ID { get }
}

# @ViewBuilder

  • View 를 리턴하는 함수를 ViewBuilder 로 만들어준다
  • 함수 혹은 인자 앞에 해당 키워드를 붙여서 ViewBuilder 를 만듦!
    • 인자 앞에 붙이는 경우 init 메서드가 필요?! 그냥 변수 선언 시에 붙여도 되긴 했음....
// 인자 
    init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) {
        ...
    }


// 함수
@ViewBuilder 
func someViewBuider() -> some View { }

# @escaping

  • 커스텀 init 을 통해 인자로 함수를 받을 때, 인자는 기본적으로 value type 이므로 해당 함수가 init 밖에서 쓰인다면 메모리 할당을 통해 힙에 저장해야 하기 때문에 escaping 으로 표기해줘야 함
struct AspectVGrid<Item, ItemView>: View where ItemView: View, Item: Identifiable{
    ...
    let content: (Item) -> ItemView
    
    init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) {
        ...
        self.content = content
    }
        
    var body: some View {
        GeometryReader { geometry in
            VStack {
                ...
                LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) {
                    ForEach(items) { item in
                        content(item).aspectRatio(aspectRatio, contentMode: .fit)  // 여기서 content 클로저가 이용됨
                    }
                }
                ...
            }
        }
    }
}

# 그림 그리기는 Path가 다 해줌!

  • Path 구조체 는 이차원 그림을 그리는 데 필요한 다양한 함수를 갖고 있다!
  • 그림을 그릴 때, 유의할 점
    • 0도 가 시계 시침이 3시 를 가리키는 시점부터 시작하므로 통상적으로 생각하는 0도12시 부터 시작하는 방식으로 각도를 구하려면 -90도 를 해주면 됨

      Pie(startAngle: Angle(degrees: 0 - 90), endAngle: Angle(degrees: 110 - 90))
    • (0,0) 좌표 가 우리가 통상적으로 생각하는 좌측 하단이 아니라 좌측 상단 즉, 좌표계가 뒤집혀 있음!

		0 -------------- x
		|
		|
		|
		|
		|
		y
struct Pie: Shape {
    var startAngle: Angle
    var endAngle: Angle
    var clockwise = false
    
    func path(in rect: CGRect) -> Path {
        var p = Path()
        
        let center = CGPoint(x: rect.midX, y: rect.midY)
        let radius = min(rect.width, rect.height) / 2
        let start = CGPoint(
            x: center.x + radius * CGFloat(cos(startAngle.radians)),
            y: center.y + radius * CGFloat(sin(startAngle.radians))
        )
        
        p.move(to: center)
        p.addLine(to: start)
        p.addArc(
            center: center,
            radius: radius,
            startAngle: startAngle,
            endAngle: endAngle,
            clockwise: !clockwise
        )
        p.addLine(to: center)
        
        return p
    }
}

☀️ TIL

  • Path 구조체 를 거의 마지막에 배웠는데 오랜만에 보는 삼각함수...나중에 다시 한 번 찾아봐야할 것 같다...
  • 그동안 혼자 LectureMemorizeApp.swift 파일의 LectureMemorizeApp 구조체 내부에서 선언한 EmojiMemoryGame 인스턴스EmojiMemoryGameView.swift 파일의 ContentView_Previews 구조체 내부에서 선언한 EmojiMemoryGame 인스턴스 는 별도의 인스턴스인 것이 뭔가 석연치 않았는데(동기화되어야 하는 게 아닌가 하는 멍청한 생각을 함) 오늘 생각해보니 그냥 로직을 테스트할 수 있기만 하면 되므로 개별 인스턴스여도 무관한 것 같다!



# @viewBuilder

  • on func or when arguments are being passed that will accept a viewBuilder
  • make a function that returns a view as a viewbuilder

# @escaping

  • gets assigned to another var and used later on
  • thus u need to make memory for it(save it in heap)

좋은 웹페이지 즐겨찾기