ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • iOS) Singleton View와 viewController (feat. programmers iOS 실력체크)
    iOS 2020. 10. 24. 17:53

    View와 View Controller

    view는 viewController에 귀속되어 모든 기능의 시작과 끝을 VC에서 관리한다.

    보통 view의 객체는 viewController 안에서 생성되고 VC의 rootView에 addSubView()를 통해 view 계층에 추가 된다.

    viewController가 화면에서 사라진다 하더라도 메모리에는 viewController가 남아있고 따라서 VC의 view 계층에 있는 subView들도 살아 있다.

    First VC의 Life Cycle과 rootView의 subViews

    VC의 viewDidLoad()에서 구성 했던 view들은 다른 VC로 넘어 갔다 온 이후에도 여전히 VC의 rootView에 남아있다.

    이 말은 각 view들에 붙어있는 function이나 gestureRecognizer, Notification등은 계속 기능을 유지한 다는 뜻이다.

    이들을 메모리에서 해지하기 위해선 removeFromeSuperview() 또는 viewController가 iOS의 ARC에 의해서 자동으로 deinit 또는 override를 통해 deinit 시켜주어야 한다.

    Singleton View

    그렇다면 view를 singleton 형태로 만들어 view controller에서 사용한다면 어떻게 해야 하고 view controller 안에선 어떤 과정이 이루어지는지 궁금하였다.

     

    우선 custom View를 만들어서 그안에 버튼을 추가 해준다.

    class CustomView: UIView {
    
        static let staticView = CustomView()
        
        let button = UIButton()
        
        override init(frame: CGRect) {
            super.init(frame: .zero)
            self.backgroundColor = .black
            self.addSubview(button)
            
            button.setTitle("button in the static View", for: .normal)
            
            button.translatesAutoresizingMaskIntoConstraints = false
            button.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
            button.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        }
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    두 개의 view controller의 view에 static view를 붙혀준다.

     

    VC1

    class ViewController: UIViewController {
      
        let staticView = CustomView.staticView
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setCustomView()
        }
        
        func setCustomView() {
            view.addSubview(staticView)
            
            staticView.button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
            
            staticView.translatesAutoresizingMaskIntoConstraints = false
            staticView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -20).isActive = true
            staticView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2).isActive = true
            staticView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            staticView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
        }
        
        @objc func buttonAction() {
            view.backgroundColor = .brown
        }
        
    }

     

    VC2

    class SecondVCViewController: UIViewController {
    
        let staticView = CustomView.staticView
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setCustomView()
        }
        func setCustomView() {
            view.addSubview(staticView)
            staticView.translatesAutoresizingMaskIntoConstraints = false
            staticView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -20).isActive = true
            staticView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2).isActive = true
            staticView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            staticView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
        }
    
    }

     

    VC1에 view의 backgroundColor를 brown으로 만들어주는 함수를 추가 해준다.

     

    결과

                          

    VC1에 붙어있던 staticView의 버튼은 VC2에서 사용하자 VC1에서 자동으로 사라진다.
    이 결과를 통해 singleton view는 한번에 하나의 VC에서만 사용 할 수 있고, 다시 사용하기 위해선 VC1에 다시 진입할 때 view에 추가 해줘야 한다.

    또한 VC1의 view subView였던 staticView는 사라졌지만, addTarget으로 만든 staticView의 함수는 그대로 유지 되는 것을 볼 수 있다.

     

     

    이번엔 VC2에도 view의 backgroundColor를 blue로 만들어주는 함수를 추가 해준다.

     

     

    결과

    각 VC에서 static view에 추가된 함수들이 동시에 작동한다.

     

     

    그렇다면 VC2에 추가된 static view의 함수가 VC1에서도 작동 할까?

     

    결과는 그렇지 않다.

    이유는 VC2에서 static view를 작동 시킬시 메모리에 VC1에 대한 데이터가 존재 하지만, VC2를 dismiss하는 시점에서 VC2의 데이터는 메모리에서 사라진다.

     

     

    응용

    singleton view를 이용한 음악 재생 어플리케이션

     

    programmers에서 과제관이란 새로운 카테고리가 생겨서 과제를 수행 해보았다.

    programmers.co.kr/skill_check_assignments

     

    실력 체크

    코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

    programmers.co.kr

     

    화면 하단의 조작 버튼들과 재생 바를 singleton view로 선언하여 메인 화면과 가사 화면에서 동시에 사용하였다.

     

    문제점과 해결

     

    매끄러운 transition 애니메이션을 위해 각 VC에서 singleton view의 추가 타이밍이 중요했다.
    VC2의 viewDidLoad() 메소드가 불리울 때 아직 VC1의 viewDidDisappear() 메소드가 불리우지 않았기 때문에(singleton view는 아직 VC1에 남아있다) VC2의 viewDidAppear() 메소드에서 singleton view를 추가 해주어야 했다.

     

    VC에 존재하는 다른 view들의 함수 호출 문제

    똑같은 기능이라도 VC마다 반복 호출 해주어야 하기 때문에 notification을 통해서 massive VC가 되는 것을 방지하였다.

    각 VC에서 addTarget()으로 붙혀주는 메소드의 경우 singlton 객체에 VC를 파라미터로 넘겨서 해결

     

    결론

    singleton을 활용 한다면, 하나의 객체를 여러 화면에서 사용할 수 있는 동시성과 재사용성에서 우위를 가져온다.

    혹시 모를 side effect를 조심해야 한다.

    화면에서 사라진 VC도 notification을 받는다.

    댓글

Designed by Tistory.