구조체를 혹은 클래스를 설계한 후 실체가 된 것을 인스턴스라 하고, 이러한 타입과 연관된 값을 보관하는 곳 을 프로퍼티
라 한다. 구조체와 클래스의 이니셜라이저는 이들의 프로퍼티가 옵셔널 타입이 아닌 한 인스턴스화할 때 값을 채워줄(초기화) 해줄 의무가 있다. 하지만 구조체 타입에 비해 클래스 타입을 설계하여 프로퍼티를 초기화하는 과정에서 에러를 맞닥뜨릴 경우가 많다.
구조체 같은 경우 자동적으로 구조체 내부에서 프로퍼티를 초기화해주는 프로퍼티 이니셜라이저가 있어 커스터마이징이 필요한 이니셜라이저가 필요하지 않는 한 개발자가 별도로 구현하지 않아도 된다. 이것을 멤버와이즈 이니셜라이저
라고 한다. 반면에 클래스는 이니셜라이저를 반드시 구현해주어야 프로퍼티가 초기화 된다.
가장 큰 이유는 상속
가능 여부에 있다. 상속이 불가능한 구조체의 경우 앞으로 확장에 의해 초기화의 대상이 될 프로퍼티가 더 이상 발생하지 않음을 설계가 끝난 시점부터 확신할 수 있다. 반면에 클래스는 상속에 의해 초기화할 프로퍼티가 늘어날 수 있기 때문에 이니셜라이저를 개발자가 직접 작성하는 것이 프로그램 구동 측면에서 더 안전한 방식이라 할 수 있다. 참고자료
// 이니셜라이저가 없어도 문제 없음 (멤버와이즈 이니셜라이저 지원)
struct Person {
var name: String
var money: Int
// init(name: String, money: Int) // 이들이 없어도 문제 없음 (생략해도 됨)
// self.name = name
// self.money = money
}
}
// 이니셜라이저가 있어야 함
class Student {
var name: String
var school: String
init(name: String, money: Int) {
self.name = name
self.money = money
}
}
앱 안에서 일어나는 이벤트를 감지하여 관심이 있다고 표현한 대상들에게 알려주는 방송국. 무언가를 구독하고 있는 상황에 빗대어 설명할 수 있다. 관심있는 대상의 행동(이벤트)을 구독한다고 Notification Center
에 등록해두면 대상이 해당 행동을 한다고 알릴 때 (post
) Notification Center
가 해당 대상의 행동을 구독하고 있는 모두에게 알림을 주는 방식이다.
왜 Notification Center를 사용하나요?
한 번에 여러 인스턴스들에게 이벤트를 발송할 수 있기 때문입니다.
앱을 사용하며 시스템과 앱 내 변화, 사용자의 행동까지 발생하는 여러 이벤트를 구독할 수 있다. 사용자의 인터넷 연결 상태가 변하거나, 키보드가 올라오거나, 사용자가 터치를 하거나, 흔들거나, 아이폰이 감지할 수 있는 모든 요소가 구독의 대상이 될 수 있다. 아래는 캠퍼 세 명이 리더인 야곰을 따라가는(..) 예시이다.
import Foundation
class Stalker {
let name: String
init(name: String) {
self.name = name
}
@objc func follow(notification: Notification) {
print("\(name)이 yagom을 따라가요...")
if let userInfo = notification.userInfo {
print("부가정보: " + userInfo.description)
}
NotificationCenter.default.removeObserver(self) // 한 번 이벤트 구독하고 다음 번부터 안 받을래
}
}
let ryan = Stalker(name: "라이언")
enum YagomNotification {
static let didGoOutHome = NSNotification.Name.init("didYagomGoOutHome")
static let willReturnHome = NSNotification.Name.init("willReturnHome")
}
NotificationCenter.default.addObserver(ryan, //누가 받을거야?
selector: #selector(Stalker.follow(notification:)), // 받으면 뭐할거야?
name: YagomNotification.didGoOutHome, // 어떤 이벤트를 구독할거야?
object: nil)
NotificationCenter.default.post(name: YagomNotification.didGoOutHome,
object: nil,
userInfo: ["name": "yagom",
"address": "Cheongju",
"time": "2021-03-14 10:47:43"])
// 이벤트 발생, userInfo로 부가정보를 딕셔너리 형태로 함께 보내줄 수 있음.
// prints "라이언이 yagom을 따라가요..."
Notification Center
와 달리 능동적으로 관심 대상이 어떻게 변했는지 지켜보는 방식. 비유하자면Notification Center
에 알려달라고 하기보다 속성의 변화가 있는지 망원경으로 지켜보고 있는 방식이라 할 수 있다. Notification Center
는 발신(post
)을 해주어야 볼 수 있는데, KVO
는 철저하게 능동적으로 동작하므로 이런 과정 없이 볼 수 있다.
import Foundation
class Idol: NSObject {
var name: String
@objc dynamic var money: Int
init(name: String, money: Int) {
self.name = name
self.money = money
}
}
class Fan: NSObject {
var name: String
init(name: String) {
self.name = name
}
}
let pengsu = Idol(name: "펭수", money: 1000000000)
let summer = Fan(name: "썸머")
pengsu.money = 0
pengsu.money = 10000
pengsu.money = 100
pengsu.observe(\.money, options: [NSKeyValueObservingOptions.new,
NSKeyValueObservingOptions.old,
NSKeyValueObservingOptions.initial]) { (idol,value) in
print(idol)
print(value)
}
화면 안의 요소들을 예쁘게 정렬하고 싶은데 화면 크기에도 대응하면서 등간격이 되게 만들 수 없을까하다 StackView
라는 것을 활용해보았다. 자세한 내용은 다음 프로젝트에서 공부해도 된다고 하니 당장은 등간격 기능을 사용해서 UI 요소 배치에 들이는 시간을 줄이는데 활용했다.
이번 프로젝트에서는 유독 버튼이 많은데, 버튼의 크기는 한정되어 있는 만큼 버튼에 들어갈 글자수가 많은 경우에 어쩔 수 없이 줄바꿈하여 글을 작성하여야할 경우가 있다. 줄바꿈되었을 때 버튼 안의 글자를 가운데 정렬하는 기능을 아직 storyboard에서 찾지 못하였기에 ViewController
에서 각 버튼을 @IBOutlet
변수로 생성한 후 titleLabel?.textAlignment
프로퍼티를 .center
로 적용하여 사용하고 있는데, 동일한 스타일 적용을 위해 동일한 코드를 반복하는게 맞나 하는 생각이 든다. (코드를 보면 전혀 아닌 것 같단 말이지 🧐...)
UI Library
에서 Stack View
를 스토리보드의 View
에 드래그 앤 드랍 방식으로 놓고 Stack View
에 넣어 정렬하고 싶은 요소들을 마찬가지로 드래그 앤 드랍하여 Stack View
에 넣는다.Stack View
의 Attributes Inspector
에서 Distribution
방식을 Equal Spacing
으로 변경한 후 요소 간 간격을 Spacing
에 기입해준다. 끝.