[Effective Objective-C] #39 핸들러 블록을 사용해 코드가 여러 개로 나뉘는 것을 막으라
출처 : Effective Objective-C
-
특정 상황에서 앱이 특정 시간 동안 응답하지 않으면 자동으로 종료될 수 있다.
특히 iOS 앱은 반드시 종료된다.
시스템 와치독(system watchdog)은 특정 시간 동안 메인 스레드가 중단된 앱은 강제로 종료시킨다.
-
비동기 메서드를 쓰면 일을 끝냈을 때 완료 사실을 알고 싶어 하는 것들에 완료 사실을 알려주는 방법이 필요하다.
이를 할 수 있는 방법이 몇 가지 있다.
일반적으로 쓰는 방법은 객체가 따를 수 있는(conform) 델리게이트 프로토콜을 이용하는 것이다.
델리게이트 객체는 비동기 작업의 완료 같은 적절한 이벤트가 발생하면 알림을 받을 수 있다.
-
블록을 이용하면 같은 일을 더 명확한 방법으로 할 수 있다.
블록은 이와 같은 API 를 더 엄격한 방법으로 사용할 수 있다.
그리고 사용자도 훨씬 깔끔한 방법으로 API 를 사용할 수 있다.
그 방법은 바로 완료 핸들러(completion handler)로 사용할 블록 타입을 정의해 메서드에 직접 전달하는 것이다.
-
델리게이트 방법의 단점은 서로 다른 데이터를 다운로드하는 다수의 네트워크 페처를 사용하는 클래스라면,
콜백하는 네트워크 페처에 따라 delegate 메서드에서 바꿔서 처리해야 한다는 것이다.
-
블록 방법의 장점은 네트워크 페처를 저장할 필요가 없다는 것.
그리고 네트워크 페처에 따른 스위칭도 필요하지 않다.
각 완료 핸들러의 비지니스 로직이 각 페처와 함께 정의되어 있다.
-
최신 블록 기반 API 가 에러 처리를 위해 블록을 사용한다.
두 가지 방법으로 사용할 수 있다.
첫 번째 방법은 두 개의 핸들러가 성공했을 경우와 실패했을 경우를 위해 각각 사용될 수 있다.
두번째 방법으로는 하나의 완료 블록(completion block)으로 성공한 경우와 실패한 경우를 모두 처리하도록 하는 것이다.
-
하나의 완료 블록 코드의 단점은 모든 로직을 한곳에 넣는다는 것이다.
블록이 길어지고 복잡해질 수 있다.
그러나 단일 블록 방법의 장점은 매우 유연하다는 것이다.
-
성공과 실패에 대한 로직을 한 블록에 넣을 때 생기는 또 다른 장점은 성공한 응답을 처리하는 도중 에러가 발견된 때에 발휘된다.
이 같은 에러는 네트워크 페처에서 발생한 에러를 처리하는 것과 동일하게 다루어져야 한다.
이 같이 단일 블록에 로직이 모두 모여 있으면 데이터에 에러가 있을 때 처리할 수 있을 뿐 아니라 네트워크 페처에서 발생한 에러도 같이 처리할 수 있다.
-
저자는 전체적으로 성공과 실패 처리를 핸들러 블록 하나에 두는 것을 추천한다.
이 방법은 또한 애플 API 에서 사용하는 방법이다.
-
핸들러 기반 API 를 작성할 때 고려해야 할 것이 또 있는데,
몇몇 코드는 반드시 특정 스레드에 동작해야 한다는 사실이다.
예를 들면 코코아와 코코아 터치 둘 다 UI 작업은 메인 스레드에서 해야 한다.
그렇기 때문에 핸들러 기반 API 사용자는 핸들러를 실행할 큐를 신중하게 결정해야 한다.
그런 API 중 하나가 NSNotificationCenter 다.
메서드를 하나 가졌는데 이 메서드로 알림 센터에서 알림을 받기 위해 등록할 수 있다.
나중에 알림 센터에서 등록한 블록이 실행되어 특정 알림을 받을 수 있다.
블록을 등록할 큐를 지정할 수 있지만 꼭 지정할 필요는 없다.
큐를 지정하지 않으면 기본 행동이 호출된다.
그리고 블록은 알림을 발생시킨 스레드에서 실행된다.
기억할 점
-
객체를 생성하는 곳에 핸들러의 비지니스 로직을 인라인으로 같이 선언하는 게 유용하다면 핸들러 블록을 이용해 하라.
-
핸들러 블록은 델리게이트와는 다르게 직접 객체에 연관될 수 있는 장점이 있다.
델리게이트를 사용할 때 관찰해야 할 인스턴스가 여러 개이면 인스턴스에 따라 바꾸어 처리해야 한다.
-
핸들러 블록을 사용하는 API 를 설계할 때 블록이 들어갈(enqueue) 큐를 API 파라미터로 전달하라.
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[Effective Objective-C] 목차와 요약을 통해 한 눈에 알아보는 Effective Objective-C #33 ~ #40 (0) | 2017.10.05 |
---|---|
[Effective Objective-C] #40 블록이 자신을 소유한 객체를 다시 소유함으로써 발생하는 리테인 순환을 조심하라 (0) | 2017.10.04 |
[Effective Objective-C] #38 많이 사용하는 블록 타입은 typedef 를 이용해 타입을 생성하라 (0) | 2017.10.02 |
[Effective Objective-C] #37 블록을 이해하라 (0) | 2017.10.01 |
[Effective Objective-C] #36 retainCount 를 사용하지 말라 (0) | 2017.09.30 |
댓글