Closed joho2022 closed 7 months ago
모델은 자신이 상태가 변경되면 옵저버 등록된 객체에게 알려주고, 컨트롤러는 수신완료하여 필요한 반응을 할 수 있다.
Notification이 오면 옵저버 패턴을 통해서 등록된 옵저버에게 Notification을 전달하기 위해 사용하는 클래스.
// Main뷰컨트롤러 extension Notification.Name { static let rectangleCreated = Notification.Name("rectangleCreated") static let rectangleColorChanged = Notification.Name("rectangleColorChanged") static let rectangleOpacityChanged = Notification.Name("rectangleOpacityChanged") }
// Main뷰컨트롤러 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(handleCreateRectangle(notification:)), name: .rectangleCreated, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleColorChanged(notification:)), name: .rectangleColorChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleOpacityChanged(notification:)), name: .rectangleOpacityChanged, object: nil) } @objc private func handleCreateRectangle(notification: Notification) { let rectangleModel = plane.createRectangleData() let rectangleView = plane.createRectangleView(rectangleModel) addRectangleViews(for: rectangleView, with: rectangleModel) view.bringSubviewToFront(drawableButtonStack) logger.info("사각형 생성 수신완료!!") } @objc private func handleColorChanged(notification: Notification) { guard let userInfo = notification.userInfo, let uniqueID = userInfo["uniqueID"] as? String, let randomColor = userInfo["randomColor"] as? RGBColor, let rectangleView = rectangleViews[uniqueID] else { return } updateViewBackgroundColor(for: rectangleView, using: randomColor) updateColorButtonTitle(with: randomColor) self.logger.info("배경색 변경 수신완료!") } @objc private func handleOpacityChanged(notification: Notification) { guard let userInfo = notification.userInfo, let uniqueID = userInfo["uniqueID"] as? String, let newOpacity = userInfo["opacity"] as? Opacity, let rectangleView = rectangleViews[uniqueID] else { return } updateViewOpacity(for: rectangleView, using: newOpacity) logger.info("투명도 변경 수신완료! 투명도: \(Double(newOpacity.rawValue) / 10.0)") }
// Plane 객체 mutating func updateRectangleColor(uniqueID: String) { let randomColor = getRandomColor() if let index = rectangles.firstIndex(where: { $0.uniqueID.value == uniqueID }) { rectangles[index].setBackgroundColor(randomColor) self.logger.info("배경색 변경 명령하달!") NotificationCenter.default.post(name: .rectangleColorChanged, object: nil, userInfo: ["uniqueID": uniqueID, "randomColor": randomColor]) } }
→ bringSubviewToFront(_:) 를 사용해서 사각형 생성될때마다 버튼스택뷰를 최상단으로 설정한다.
bringSubviewToFront(_:)
뷰 인스턴스 자체를 비교하기 위해 키값을 유니크ID value를 뷰 인스턴스로 딕셔너리를 만듬
두 객체가 느슨하게 연결되어 있다는 것은 상호작용은 하지만, 서로에 대해 잘 모른다는 것을 의미한다.
그래서 서로 의존성이 줄어들어서 나중에 변경사항이 생기면 유연하게 유지보수를 할 수 있다.
즉, 객체지향 시스템을 유연하게 구축할 수 있다. → 객체 사이의 상호의존성을 최소화하기 때문에
🎯주요 작업
📚학습 키워드
Observer 패턴
모델은 자신이 상태가 변경되면 옵저버 등록된 객체에게 알려주고, 컨트롤러는 수신완료하여 필요한 반응을 할 수 있다.
NotificationCenter
Notification이 오면 옵저버 패턴을 통해서 등록된 옵저버에게 Notification을 전달하기 위해 사용하는 클래스.
Notification
1. extension으로 Notification.Name 추가하기
2. Notification Center에 옵저버 등록하기
3. NotificationCenter에 Post하기
💻고민과 해결
사각형을 생성하면 버튼위에 사각형이 생성되어서 버튼이 가려지는 현상
→
bringSubviewToFront(_:)
를 사용해서 사각형 생성될때마다 버튼스택뷰를 최상단으로 설정한다.Tag값으로 subViews에 찾는 방법을 지양하고 다른 데이터 구조 모색
뷰 인스턴스 자체를 비교하기 위해 키값을 유니크ID value를 뷰 인스턴스로 딕셔너리를 만듬
🤔결과
📚추가학습
느슨하게 연결된 (loosed coupled) 구조가 왜 좋은가?
두 객체가 느슨하게 연결되어 있다는 것은 상호작용은 하지만, 서로에 대해 잘 모른다는 것을 의미한다.
그래서 서로 의존성이 줄어들어서 나중에 변경사항이 생기면 유연하게 유지보수를 할 수 있다.
즉, 객체지향 시스템을 유연하게 구축할 수 있다. → 객체 사이의 상호의존성을 최소화하기 때문에