관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] Self vs self (대문자 Self와 소문자 self) 본문

iOS 기본 (swift)

[iOS - swift] Self vs self (대문자 Self와 소문자 self)

jake-kim 2021. 7. 6. 00:38

소문자 self

  • 인스턴스 자체 접근 시 사용되는 참조값
  • self는 참조 타입
    • value type에서의 self는 stack영역에 존재하는 instance를 가리키는 형태
    • reference type에서의 self는 heap 영역에 존재하는 instance를 가리키는 형태

대문자 Self

  • 대문자로 시작하는 것에서 알 수 있듯이, Self는 타입을 의미
  • self 프로퍼티의 타입은 Self

Self.self

  • Self는 type그 자체를 의미: 타입을 정의할때 사용
  • Self.self는 type object를 의미: 타입을 넘길때 사용
static var defaultFileName: String {
    return NSStringFromClass(Self.self).components(separatedBy: ".").last! // 넘길때 Self.self 사용
}
static func instantiateViewController(_ bundle: Bundle? = nil) -> Self // 타입 정의할때 Self 사용

  • Self.self가 아니더라도 다른 곳에서도 동일
    • 타입.self > 타입의 객체를 의미

  • instance.self는 값
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let a = 123
        type(of: a) // Int
        a.self // 123
        Self.self // ViewController
    }
}

문맥에 따라 의미가 다른 Self

  • protocol 내부에서의 Self 의미: 해당 protocol을 채택한 타입을 의미
// Self의미: protocol 자신이 아닌, 자기 자신을 채택한 타입을 의미

protocol Repository {
    associatedtype Value
    init?(value: Self.Value)
    var value: Self.Value { get }
}

// Self를 생략 가능
protocol Repository {
    associatedtype Value
    init?(value: Value)
    var value: Value { get }
}
  • Class에서의 Self 의미
    • 해당 인스턴스의 타입 자체를 표현
    • 메소드 시그니처에서 결과값으로만 사용 가능
    • 메소드 몸체에는 사용 불가
class TestClass {
    func someFunc() -> Self {
        return self
    }
}

ex) Self를 사용하여 코드로 xib파일을 부르는 StoryboardInstantiable 프로토콜 구현

  • protocol 정의
public protocol StoryboardInstantiable {
    associatedtype T
    static var defaultFileName: String { get }
    static func instantiateViewController(_ bundle: Bundle?) -> T
}
  • default implementation
    • protocol을 채택한 타입을 return하는 함수 intantiateViewController(:)함수
    • 타입 캐스팅을 위하여 Self사용
public extension StoryboardInstantiable where Self: UIViewController {
    static var defaultFileName: String {
        return NSStringFromClass(self).components(separatedBy: ".").last!
    }

    static func instantiateViewController(_ bundle: Bundle? = nil) -> Self {
        let fileName = defaultFileName
        let storyboard = UIStoryboard(name: fileName, bundle: bundle)
        guard let vc = storyboard.instantiateInitialViewController() as? Self else {
            fatalError("Cannot instantiate initial view controller \(self) from storyboard with name \(fileName)")
        }
        return vc
    }
}

cf) Metatype(메타 타입)의 개념

 

* 참고

http://iosbrain.com/blog/2018/09/26/self-versus-self-in-swift-4-capital-s-and-lowercase-s/

https://www.hackingwithswift.com/example-code

Comments