본문 바로가기
iOS/Design Pattern

Design Pattern - MVC

by HaningYa 2020. 7. 14.
728x90

MVC Class Diagram

MVC Pattern

  • Model: 앱 데이터를 가지도 있다. struct 나 간단한 class 로 구성된다.
  • Views: 시각적인 요소들과 화면을 담당한다. UIView 의 Subclass 이다.
  • Controllers: model 과 view를 통합시킨다.

Controller 는 model 과 view의 string properties를 가져 직접 access가 가능하다. 또한 하나 이상의 view와 model 을 가질 수 있다.

반대로 model 과 view 들은 controller 에 대한 string reference 가 없어 retain cylce의 문제가 발생할 수 있다.

대신에 model 은 property observing 을 통해 controller 와 통신한다. view 는 IBActions를 통해 controller 와 통신한다.

이렇게 되면 Model 과 View를 여러 controller 에서 재사용할 수 있게 해준다.

*view 는 weak refernece 를 delegate 를 통해 가지고 있다.
예를들어 UITableView 는 delegate 와 datasource 를 통해 weark reference를 가진다.

Controller 의 경우 MVC에서 재사용 하기 힘들다.


언제 MVC를 사용할까

iOS app개발 초기에 사용하는것이 좋다.

다른 패턴들도 추후에 필요할 것이지만 필요한 그때그때 차용하는 게 좋고 시작은 MVC로 하는걸 추천


MVC 예제 코드

import UIKit

//Model
public struct Address {
    public var street : String
    public var city : String
    public var state : String
    public var zipCode : String
}
//View
public final class AddressView : UIView {
    @IBOutlet public var streetTextField : UITextField!
    @IBOutlet public var cityTextField : UITextField!
    @IBOutlet public var stateTextField : UITextField!
    @IBOutlet public var zipCodeTextField : UITextField!
}
//Controller
public final class AddressViewController : UIViewController {
	//Holding Strong referecne with Model and View
    public var address : Address? {
        didSet {
        	//Model -> Controleller
            updateViewFromAddress()
        }
    }
    public var addressView : AddressView! {
        guard isViewLoaded else {return nil}
        return (view as! AddressView)
    }
}
public override func viewDidLoad() {
    super.viewDidLoad()
    updateViewFromAddress()
}
//Controller -> Model
private func updateViewFromAddress(){
    guard let addressView = addressView,
        let address = address else {return}
    addressView.streetTextField.text = address.street
    addressView.cityTextField.text = address.city
    addressView.stateTextField.text = address.state
    addressView.zipCodeTextField.text = address.zipCode
}
//View -> Controller
@IBAction public func updateAddressFromView(_ sender : AnyObject) {
    guard let street = addressView.streetTextField.text,
    street.count > 0,
        let city = addressView.cityTextField.text,
    city.count > 0,
        let state = addressView.stateTextField.text,
    state.count > 0
    let zipCode = addressView.zipCodeTextField.text,
    zipCode.count > 0 else{
        return
    }
    address = Address(street: street, city: city, state: state, zipCode: zipCode)
}

MVC를 사용하며 주의할 점

Model, View, Controller 에 속하지 않는 Object가 있을 수 있다. 그래서 많은 logic 이 controller 에 집중될 수 밖에 없다.

결국 controller의 코드량이 많아져 Massive View Controller 가 될 수 도 있다.


한가지 알게된 점

나는 처음 iOS앱을 만들때 IBOutlet 을 Controller 에 binding 했고 따로 UIView class 를 만들지 않았다. 이 방식이 MVC 이고 View 는 그럼 storyboard 의 xib를 말하는 거였구나 생각했었는데 UIView class 를 따로 만들고 controller 에서 

 public var addressView : AddressView! {
        guard isViewLoaded else {return nil}
        return (view as! AddressView)
    }

이런식으로 view를 불러서 사용하는 지는 몰랐다.

생각해 보면 View 는 UIView 의 subclass 라고 했는데 왜 그렇게 생각했지 싶다.

728x90

'iOS > Design Pattern' 카테고리의 다른 글

Design Pattern - Singleton Pattern  (0) 2020.08.09
Design Pattern - Strategy Pattern  (0) 2020.08.07
Design Pattern - Delegation Pattern  (0) 2020.08.06
Design Pattern - Class Diagram  (0) 2020.07.14
Design Pattern - Introduction  (0) 2020.07.14

댓글