현재 Swift 버전(2.1)에서는 클로저 내에서 인스턴스 멤버에 접근할 때 self
를 사용해야 한다. 이 제안은 이를 모든 멤버 접근으로 확장하는 것을 제안한다(이것은 Objective-C에서 본질적으로 그렇듯이). 이는 인스턴스 프로퍼티와 로컬 변수를 구분하고, 인스턴스 함수와 로컬 함수 또는 클로저를 구분하는 데 유용하다.
이 제안은 인스턴스 프로퍼티와 로컬 변수, 그리고 인스턴스 함수와 로컬 함수/클로저를 명확히 구분한다. 이는 여러 가지 장점을 가진다:
self
를 요구하는 것보다 일관성이 있다.이 제안으로 방지할 수 있는 버그의 예시(Rudolf Adamkovic 제공):
class MyViewController : UIViewController {
@IBOutlet var button: UIButton!
var name: String = "David"
func updateButton() {
// var title = "Hello \(name)"
button.setTitle(title, forState: .Normal) // 이 줄을 주석 처리하지 않았지만 컴파일러는 경고하지 않고, 실수로 UIViewController의 title을 참조하게 됨
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
}
}
API 디자인 가이드라인은 API 작성용이지만, 여전히 Swift의 기본 원칙을 대표한다고 생각한다. 첫 두 가지 원칙은 다음과 같다:
이 제안은 이러한 목표와 직접적으로 일치한다고 믿는다.
커뮤니티의 두 멤버가 제기한 반론은 현재 동작이 “클로저 내에서 self의 캡처 의미를 더 두드러지게 만든다”는 것이다. 이는 사실이지만, 저자는 그 유용성이 부족하다고 생각한다.
다음 코드에서 우리는 foobar
가 예외를 던지는 함수이고 barfoo
는 예외를 던지지 않는다는 것을 명확히 알 수 있다.
try foobar()
barfoo()
그러나 클로저 내에서 self
를 사용하는 예제를 보자:
foobar({
print(self.description)
})
위 코드에서 self
키워드는 힌트를 제공하지만 확실한 정보를 제공하지는 않는다:
self
는 컴파일러에 의해 메모리 문제 가능성을 암시하기 위해 강제되었을 수 있다.self
는 프로그래머의 선택일 수 있다.반대 예제를 살펴보자:
barfoo({
print(description)
})
description
은 지역 변수를 참조할 수 있으며, 이는 escaping 클로저에서 인스턴스 프로퍼티를 가린 것일 수 있다.이 두 예제에서 self
키워드는 호출된 함수의 시그니처를 확인하지 않고서는 참조 순환 문제에 대해 주의해야 하는지 여부를 확실히 알려주지 않는다. 단지 self가 캡처되었음을 알려줄 뿐이다. 제안하는 방식에서는 self
가 다시 의미를 갖게 된다: 어떤 것이 지역 프로퍼티이고 어떤 것이 인스턴스 프로퍼티인지 나타낸다.
인스턴스 프로퍼티와 함수에 접근할 때 self
를 사용하지 않는 방식은 두 단계로 적용할 것을 제안한다. Swift 2.x에서는 경고로 시작하고, Xcode가 Fix-It을 제공할 수 있다. 그런 다음 Swift 3에서는 컴파일러 오류로 변경되고, 마이그레이터가 코드를 전환하는 데 도움을 줄 수 있다.
다음 코드는 이전에는 컴파일되었지만, 주석이 달린 줄에서 오류를 발생시킨다:
class Person {
var name: String = "David"
func foo() {
print("Hello \(name)") // 컴파일되지 않음
}
func bar() {
foo() // 컴파일되지 않음
}
}
이 코드는 다음과 같이 수정해야 정상적으로 컴파일된다:
class Person {
var name: String = "David"
func foo() {
print("Hello \(self.name)")
}
func bar() {
self.foo()
}
}
이 제안은 기존 코드에 상당한 영향을 미친다. 하지만 마이그레이션 도구와 Xcode의 Fix-It 기능으로 쉽게 해결할 수 있다.
현재 동작을 유지하는 방법도 하나의 대안이다. 하지만 이 경우 앞서 언급한 단점들이 여전히 존재한다.
다른 대안으로는 컴파일 오류를 경고 수준으로 낮추는 방법이 있다.