Memory
- Automatic Reference Counting
- Reference 타입(class)은 heap 메모리에 저장된다
- 메모리는 자동으로 관리된다
- 가르키는 포인터의 카운터를 세다가 0이되면 놓아버리는 형식의 메모리 관리
- ARC에 영향을 주는 세가지
- strong
- 디폴트
- 레퍼런스 카운트 증가(선언된 변수가 힙에 머물도록 하는 타입)
- weak
- 메모리에 참조되어 있는 값이 없다면 nil로 만드는 타입
- 힙에 있는 무엇가를 가르키고 있지만 관심이 없어서 사라져버리면 nil로 설정
- nil로 설정 가능하다는 것은 optional 포인터여야만 한다는 의미
- 대표적인 예로 UILabel을 보여주기 위한 Outlet등이 있다.
- unowned
- 참조 횟수를 세지마라는 의미
- 가르키는 값이 사라지면 크래쉬 발생
Closures
- Capturing
- 클로저는 Heap 메모리에서 사용 되고, 레퍼런스 타입이다.
- 클로저는 클로저를 둘러쌓고 있는 변수들을 사용할 수 있고 이 captured 변수들은 클로저가 heap에 머무는 동안 함께 머물게 된다.
- 이것은 메모리 사이클을 만들 수 있음
- 메모리 사이클이란
- 클로저가 어떤 객체를 가르키고, 객체도 클로저를 가르키게 된다면 서로 가르키게 되고 순환 참조가 발생하게 된다
addUnaryOperation("루트") { [self weakSelf = self] in
weakSelf?.display.textColor = UIColor.redColor()
return sqrt($0)
}
Extensions
- Extensions
- 메소드나 프로퍼티를 다른 클래스에게 추가하게 해줌
- class, struct, enum 모두 사용 가능
- 이제 존재하는 메소드를 다시 구현할 수는 없다
- 추가된 요소들은 계산된 요소여야만 한다
Protocol
- protocols
- API를 더욱 간결하게 표현하는 방법
- 선언된 메소드와 프로퍼티들로 된 집합체
- 프로토콜은 타입이다
- 프로토콜을 실행하는 class, struct, enum에서 사용 가능
- protocol 과 extension은 저장 공간이 없다.
- extension을 사용할 수 있음
- four aspects
- protocol declaration
- 프로토콜에 들어갈 메소드와 프로퍼티를 선언하는 작업
- class, struct, enum이 자기가 이 프로토콜을 실행하겠다고 선언
- 프로토콜에 있는 값들을 구현하고 실행
- 프로토콜을 실행한다면, 프로토콜에 있는 모든 것들을 실행해야함
- ObjectiveC에서는 optional을 통해 필요한 것만 구현 가능
- @objc protocol로 objectiveC버전으로 프로토콜 실행가능
- optional 키워드로 func 나 var 앞에 붙일 수 있음
- optional 프로토콜을 실행하는 클래스는 NSObject를 상속 받아야만 한다.
- 프로토콜은 다중 상속 받을 수 있음
- 상속 받은 프로토콜의 모든 것들을 실행해야한다.
- var 에 get 이나 get and set 설정 해주어야 함
- 변경될 예정인 함수들은 mutating 키워드 붙어야함 (struct(값 타입)에 변경이 발생하는 경우)
- protocol Somprotocol: class 하면 class만 해당 프로토콜 상속 가능
- 프로토콜 안에 initializer 사용 가능
- 프로토콜 안에 init이 있고 클래스가 그것을 실행한다면 그 init을 required로 만들어야 한다.
- extension에 추가 가능
Delegation
- 프로토콜을 사용하는 대표적인 예
- 델리게이션은 눈에 보이지 않는 소통을 하는 방식(blind communication between a View and Controller)
- 프로토콜을 이용하여 델리게이션 하는 방법
- 뷰에서 델리게이션 프로토콜을 선언한다.
- MainTableViewController: ToDoProtocol
- 뷰의 API는 weak delegate를 가지고 있을 것이고 이것은 델이게이션 프로토콜 타입이다.
- AddTodoViewController { weak var delegate: TodoProtocol? }
- weak or unowned인 이유: 컨트롤러가 뷰를 메모리에 저장할 수 있지만, 뷰가 컨트롤러를 메모리에 저장하게 하고 싶진 않을테니까
- 사용하지 않으면 nil로 초기화
- 뷰가 delegate 사용: 뷰가 메시지를 보내길 원할 때
- should, will, did, count, data ... etc
- 컨트롤러는 이 프로토콜을 실행한다고 선언한다
- 컨트롤러는 자기자신(self)을 delegate라고 지정한다
- addViewController.delegate = self
- 컨트롤러는 프로토콜을 실행
- 뷰에서 델리게이션 프로토콜을 선언한다.
- 모든 델리게이트 들은 오프젝티브C로 구성되어 있어서 IOS의 대부분의 델리게이트(ScrollVeiwDelegate, TableViewDelegate)의 거의 모든 메소드들은 옵셔널이다.
- 위에 과정을 걸치면 뷰는 컨트롤러에 연결된 상태지만 뷰는 어떤 오프젝트가 will, should, did를 실행하고 있는지 모른다.
- closure방식으로 델리게이트 처리할 수 있음
- 프로토콜이 처리하게 하느냐고 많은 비용이 들 수 있는데 클로져가 있으면, 클로져의 인자가 무엇인지 알고 있고 무엇을 반환할지 알고 있기 때문에 사실상 프로토콜을 정하는것과 동일하다
- ScrollView를 예를 들면 스크롤이 끝나면 이 클로져를 실행해라 라는 의미 -> 클로저에게 처리를 맡기는 것
- 클로져와 프로토콜 둘다 사용가능하지만 서로 완전히 대체가능하지는 않다.
- 프로토콜은 이 오브젝트가 무엇을 위임할 수 있는지를 매우 분명히 할때 좋다.
- 클로져는 에러 콜백(Error Callback), Multi-Thread 환경 어떤 처리가 오래 걸리다가 나중에 완료되면 끝났다고 알려줄때 좋다
- Example
- UIScrollView
- weak var delegate: UIScrollViewDelegate?
- @objc protocol UIScrollViewDelegate{ optional func ~~ optional func ~~ }
ImageView
- URL에서 이미지 가져오는 방법
- let url = imageURL
- let imageData = NSData(contentOf: url as URL)
- UIImage image = UIImage(data: imageData as Data)
- UIImageView set
- image { set { imageView.image = newValue imageView.sizeToFit() scrollView?.contentSize = imageView.frame } }
Mulithreading
멀티 쓰레딩이란, 일을 처리하는 별도의 쓰레드를 갖추는 것이다.
싱글코어프로세서에서도 시분할 방식으로 문맥교환을 통해 여러 쓰레드를 작동시킨다
IOS에서 멀티 쓰레딩은 queue와 같다
이 큐는 IOS 함수들을 포함하고 있다 (대부분 여기에 들어간 함수는 클로져로 되어 있다)
큐는 여러개가 존재할 수 있고 스시템은 각각의 큐에서 꺼내서 각각의 쓰레드에서 동작시킨다
시리얼큐(serial)는 큐에 있는 첫 번째 테스크가 끝나면 그 다음 테스크는 꺼내는 방식의 큐이다.
병렬큐(concurrent)는 큐에서 테크를 꺼내 처리하는 동안 놀고있는 다른 쓰레드에서 다음 것들을 바로 처리하는 방식
Main Queue
- 가장 중요한 큐 (very special serial queue)
- 메인 큐는 모든 UI가 작동해야 할 곳에서 사용된다.
- 이와 반대로 시간이나 리소스를 잡아먹는 UI외의 모든 처리는 메인큐 밖에서 처리해야만 한다.
- 메인 큐에서 동작하는 것들은 직렬로 처리된다.
- UI가 순서대로 예상가능하게 표현되어야 하기 떄문인다.
- 메인 큐가 클로져나 함수를 꺼내 작업을 처리하는 유일한 떄는 메인큐가 한가할 때이다.
Other Queue
- UI가 아닌 것들을 처리하는데 사용하는 큐
큐에 뭔가를 집어넣는 방법
- dispatchasync(queue) { / do what you want to do here _/ <- 클로저임 }
- 2개의 arguments를 받음
- queue
- func(closure)
The Main Queue
- main queue call
- dispatch_get_main_queue() 함수 사용 -> swift 3.0 미만
- DispatchQueue.main.async
- main queue call
The Other Queue
- 다른 큐를 사용하는 방법은 시스템이 제공하는 병렬 큐들을 사용
- 시스템이 제공하는 4가지 큐
- 4개의 큐는 각자 맡고 있는 서비스(Quality Of Service)가 있다.
- QOS는 시스템이 얼마나 특정 서비스에 중점을 두느냐를 말한다 -> 우선순위로 이해해도 된다.
- 4가지 QOS
- USER_INTERACTIVE: 가장 우선순위가 높은 큐 메인큐는 아니지만 즉각 처리가 필요한 부분
- USER_INITIATED: 유저가 처리를 요청했지만 상호작용이 필요한 처리는 아님 시간은 조금 걸리지만 바로 처리해야함
- UTILITY: 뒤에서 오랫동안 작동하는 작업 데이터를 가져오거나 데이터 베이스를 비운다던지 하는 경우
- BACKGROUND: 오늘 해도 되고 내일 해도 되는 작업
- other queue call
dispatch_get_global_queue(<one of the QOS>, 0) // 0 is a "reserved for future" 언젠가를 위해 남겨둔다는 의미로 항상 0으로 세팅
- DispatchQueue.global.async
User Create Queue
- custome queue call
- dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL)
- DispatchQueue(label:"queuename")
- 메인 큐 까지는 아니지만 높은 우선순위의 직렬큐로 생성된다.
- custome queue call
GCD(Grand Central Dispatch)
- 따로 공부해라
추상적인 API
- NSOpertaionQueue and NSOperation
- 서로 다른 쓰레드에서 동작하는 2개의 객체가 서로 의존성이 있을때 사용
IOS API관점에서 멀티 쓰레딩
- IOS 전반에는 쓰레드를 사용해서 비동기적으로 처리하는 수많은 메소드가 있다
- 메소들의 인자중 하나인 클로저를 살펴보면 된다.
- 클로저는 비동기으로 메인 큐 바깥에서 처리될 것
- 대표적인 예 URLSession
UITextField
- UITextField는 UILabel과 같지만 텍스트를 편집할 수 있다.
- UITextField가 "first responder"가 되면 키보드가 나타난다.
- 키보드를 숨기고 싶으면 resignFirstResponder를 사용하면 된다.
- Delegate 주로 return키와 함께 사용된다.
- 키보드를 설정하려면 UITextField를 통하면 된다.
- 키보드위에 커스텀 뷰 올릴때 inputAccessoryView