[iOS] Combine 알아보기

Han's·2023년 6월 25일
0
post-thumbnail
post-custom-banner

ObservableObject

  • @ObservedObject가 되기 위해서는 반드시 ObservableObject 프로토콜을 따르는 클래스여야 합니다.
  • 각 프로퍼티 값이 바뀌었을 때 제대로 업데이트가 된 것을 모니터링하려면 해당 프로퍼티에는 @Published를 붙여서 퍼블리셔로 쓸 수 있도록 해야 합니다.
class HomeVM: ObservableObject {
    @Published var isNeedToReload = false {
        didSet {
            guard isNeedToReload == true else { return }
            coffeeMenu.shuffle()
            events.shuffle()
            isNeedToReload = false
        }
    }
    
    @Published var coffeeMenu: [CoffeeMenu] = [
        CoffeeMenu(image: Image("coffee"), name: "아메리카노"),
        CoffeeMenu(image: Image("coffee"), name: "드립커피"),
        CoffeeMenu(image: Image("coffee"), name: "카푸치노"),
        CoffeeMenu(image: Image("coffee"), name: "콜드브루"),
        CoffeeMenu(image: Image("coffee"), name: "아인슈페너"),
        CoffeeMenu(image: Image("coffee"), name: "에스프레소"),
        CoffeeMenu(image: Image("coffee"), name: "아이스 아메리카노")
    ]
    
    @Published var events: [Event] = [
        Event(image: Image("coffee"), title: "제주도 한정 메뉴", description: "제주도 한정 음료가 출시되었습니다. 꼭 드셔보세요!"),
        Event(image: Image("coffee"), title: "여름 한정 메뉴", description: "여름에는 시원한 아이스 커피~ 무더운 여름에 어울리는 아이스 커피를 드셔보세요.")
    ]
}

@ObservedObject

  • observable 객체를 구독하는 property wrapper
  • observable 객체가 변경되면 뷰에 업데이트 시켜주는 기능
struct HomeView: View {
   @ObservedObject var viewModel = HomeVM()
   
   var body: some View {
       ScrollView(.vertical) {
           HomeHeaderView(isNeedToReload: $viewModel.isNeedToReload)
           MenuSuggestionSectionView(coffeeMenu: $viewModel.coffeeMenu)
           Spacer(minLength: 32)
           EventSectionView(events: $viewModel.events)
       }
   }
   
}

@Published

  • @Published를 사용하여 선언된 프로퍼티는
    ObservableObject를 구현한 클래스 내에서 사용되어야 합니다. (구조체 X)
  • @Published는 property wrapper로, 값의 변경을 관찰하고 구독자에게 알릴 수 있는 기능을 제공합니다.
  • 사용하는 쪽에서 $기호를 사용하여 퍼블리셔에 접근할수 있습니다.

@Binding

  • @Binding을 사용하면 상위 뷰에서 전달된 값을 하위 뷰에서 수정하고 업데이트할 수 있습니다.
enum HeaderButton {
    case refresh
    case new
    case coupon
    case bell
    
    var buttonName: String {
        switch self {
        case .refresh:
            return "arrow.triangle.2.circlepath"
        case .new:
            return "mail"
        case .coupon:
            return "ticket"
        case .bell:
            return "bell"
        }
    }
    
    static var buttonSize: CGFloat {
        return 16
    }
}

struct HomeHeaderView: View {
    @Binding var isNeedToReload: Bool
    
    var body: some View {
        VStack(spacing: 16) {
            HStack(alignment: .top) {
                Text("\(User.shared.userName)님~\n반갑습니다! 😄")
                    .font(.largeTitle)
                    .frame(maxWidth: .infinity, alignment: .leading)
                Button {
                    isNeedToReload = true
                } label: {
                    Image(systemName: HeaderButton.refresh.buttonName)
                }
            }
            HStack {
                Button {
                    print("New")
                } label: {
                    Image(systemName: HeaderButton.new.buttonName)
                        .foregroundColor(.secondary)
                    Text("What's New")
                        .foregroundColor(.primary)
                        .font(.system(size: HeaderButton.buttonSize, weight: .semibold))
                }
                Button(action: {
                    print("Coupon")
                }) {
                    Image(systemName: HeaderButton.coupon.buttonName)
                        .foregroundColor(.secondary)
                    Text("Coupon")
                        .foregroundColor(.primary)
                        .font(.system(size: HeaderButton.buttonSize, weight: .semibold))
                }
                Spacer()
                Button(action: {
                    print("Bell")
                }) {
                    Image(systemName: HeaderButton.bell.buttonName)
                        .foregroundColor(.secondary)
                }
            }
        }
        .padding(16)
    }
}
profile
🍎 iOS Developer
post-custom-banner

0개의 댓글