I had the same problem with Xcode 11 but I just updated CocoaPods and it worked.

  1. Update CocoaPods to latest version with sudo gem install cocoapods
  2. Run pod install again

'프로그래밍 > ios(Swift)' 카테고리의 다른 글

Notification Center  (0) 2020.03.22
[Objective-C] nil vs null  (0) 2020.03.21

flutter의 BLoC 패턴

 

플러터에서도 Provider나 stream을 제공하는데 Notification Center은 Swift에서 비슷할 역활을 한다고 보면 된다. 아직 Design Pattern에 대해 수박 겉햟기 식으로만 보았는데 아마 이것들이 base일 것이다.

 


 

NotificationCenter은 등록된 Observer에게 동시에 Notification을 전달하는 클래스이다. 특정 객체가 NotificationCenter에 등록된 Event를 발생시키면(Post라고 한다.) NotificationCenter에 등록된 Observer들이 Event에 대한 행동을 처리하고 이를 대기한다. 여기서 전체 흐름은 동기적으로 흘러가는데, 이를 aysnc으로 사용하려면 NotificationQueue를 사용하면 된다.

 

 

사용 방법은 아래와 같다.

 

Post

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func postBtnTapped(_ sender: Any) {
        NotificationCenter.default.post(
            name: NSNotification.Name(rawValue: "PostButton"), 
            object: nil)
    }
}

코드가 굉장히 직관적이다.

버튼을 Tap하였을 경우, NotificationCenter에 "PostButton" 이라고 하는 Event를 등록하고 이를 발생시킨다는 뜻.

이때, object 파라미터를 통해 Event를 발생시킬 때 특정 Object를 같이 넘길 수 있다. 

 

 

Event...너를 지켜보고 있다

 

Observer

class ObserverOneViewController: UIViewController {

    @IBOutlet weak var hiddenLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, 
            selector: #selector(showLabel), 
            name: NSNotification.Name(rawValue: "PostButton"),
            object: nil)
    }
    
    @objc func showLabel(){
        hiddenLabel.layer.isHidden = false
    }
}

NotificationCenter에 Observer을 추가하는 것을 한눈에 찾아볼 수 있다.

여기서 이 객체(self)를 name(위에서 설정한 "PostButton"이라는 Event가 발생했을 경우,

selector에 지정되어 있는 함수(showLabel)를 동작시킨다.

 

추가의 방법에는 두가지의 방법이 존재한다. 위 예제에선 후자

func addObserver(forName name: NSNotification.Name?, 
                 object obj: Any?, 
                 queue: OperationQueue?, 
                 using block: @escaping (Notification) -> Void) -> NSObjectProtocol

NotificationQueue를 만들어서 이걸 사용하고 싶다면 필요할 경우 Main Thread에서 사용하도록 잘 처리해야 한다.

 

func addObserver(_ observer: Any, 
                 selector aSelector: Selector, 
                 name aName: NSNotification.Name?, 
                 object anObject: Any?)

 

 

중요한 것은 생성한 Observer는 추후에 제거를 해주어야 하는데,

이는 flutter에서는 생성한 스트림을 close해주는 것이 있었는데 비슷한 이치이다.

func removeObserver(_ observer: Any, 
                    name aName: NSNotification.Name?, 
                    object anObject: Any?)
                    
//NotificationCenter.default.removeObserver(self, name: .changeLabel, object: nil)

 

제대로 제거해 주지 않으면 Observer가 소속된 오브젝트가 해제 되었을 때, Notification 이 전달되면 문제가 생긴다.

"이 변수가 절대로 Null이 될 수 없을꺼라 장담하니?","물론이지!" 

 

 

 

간단히 말해서 nil은 객체 참조에, null은 그 밖의 포인터 자료형에 사용된다.

//nil 사용
MyClass *obj = nil

// null 사용
int *ptr = NULL;

 

 

Java 에서는 객체 참조값이 null 일 경우, NullPointerException이 발생하게 되지만, Objective-C의 경우는 Java와 달리 내부에서 null 확인작업이 이루어진다. 메시지 전송 과정에서 중앙 메시지 전송 함수가 수신자의 포인터 값을 확인하는데,

이 때 수신자의 포인터가 nil 값인 경우 메시지 전송 함수는 즉시 반환되기 때문이다. 

 

 

Objective-C는 Exception은 발생시키지 않으나 메시지에 전달되는 인자는 정상적으로 진행된다.

증가연산자(++)가 사용되는 경우에도 메시지 수신 객체가 nil 이라 하더라고 인자값은 정상적으로 처리가 되버린다...

 

 

 

nil 수신자에 메세지를 전송할 경우 반환되는 값은 아래와 같다.

반환타입 반환 값
id nil
객체 포인터 NULL
BOOL NO
(unsigned)char '\0'
(unsigned)int 0
(unsigned)long int 0L
(unsigned)long long int 0LL
float 0.0f
double 0.0
long double 0.0

반환 값으로 구조체를 넘겨받는 경우에는 nil 수신자가 정상적으로 동작하지 않는데, 이 경우 Java에서와 같이 메시지 전송 전 nil 여부를 확인할 필요가 있다.


nil 특성을 이용해 프로그램을 구성하려면 프로퍼티 접근자(property accessor), 부재중 동작(absent behavior), 없음의 일관성(consistency with nothing) 등의 세가지 원칙을 지키는 것이 좋다.

 

 

1) 프로퍼티 접근자

프로퍼티의 접근 메소드를 만들어 사용하면 프로퍼티 소유 객체의 값이 nil 인 경우에도 문제가 없다. 하지만 프로퍼티의 접근 메소드를 만들지 않고, myObject -> myProperty 와 같이 직접 접근을 하는 경우엔 메무리 주소 오류가 발생한다.

 

2) 부재중 동작

객체가 부재중(=nil)인 경우 상황에 따라 추가적인 동작을 지정해야 하는 경우가 있다.

  • 로그 객체 : 로그 출력 객체가 설정되어 있다면 전달받은 메시지를 로그에 출력하고, nil로 설정되면 아무런 작업을 하지 않는다.

  • 리스너 객체 : 리스너 객체는 설정된 상태에서만 변경된 정보에 대한 메시지를 전송한다. nil로 설정되면 더이상 변경 사항이 전달되지 않는다.

  • 위임 객체 : 위임 객체는 설정된 상태에서만 위임 객체 기능을 호출하고 없으면 기본 기능만 호출한다.

3) 없음의 일관성

클래스의 프로퍼티에서는 0 또는 nil의 개념이 없는 객체로 일관되게 설계하는 것이 좋다. 프로퍼티를 긍적적인 값을 표현하게 정의하는 것이 좋다. 즉, isEmpty라는 메소드 대신 hasObject라는 메소드 형식으로 정의하는 것이 바람직하다.

 

 

 

 

 

 

 

 

 

+ Recent posts