- NSObjcet 음.. SwiftUI에선?2025년 02월 16일
- 2료일
- 작성자
- 2025.02.16.:16
흠..이거 관련된건 개발쪽인가 면접준비쪽인가..면접에서 안물어볼거같긴한데. both인가
뭐 우리가 UIKit으로 개발을 하다보면 NSObject를 상속해야하는 경우를 많이 만날 수 있다. 없으면 추가하라고 빨간 이슈가 뜬다. 대체 뭐길래??사실 이건 Objective-C의 잔해?라 하긴 그렇고 뭐라해야하지 어쨋거나 Objective-C관련된 것이다.
NSObject는 Objective-C Runtime 시스템의 최상위 클래스로, 모든 Objective-C 및 Swift 클래스의 기반이 된다. Cocoa 및 Cocoa Touch 프레임워크의 루트 클래스로, 이 클래스를 상속받음으로써 런타임 시스템과 상호작용할 수 있는 기능을 포함하게 된다.
NSObject를 상속받으면?
• Objective-C 객체처럼 동작할 수 있는 능력을 얻게 된다.
• 런타임 시스템에 대한 기본 인터페이스를 상속받는다.
• 메모리 관리(Reference Counting): ARC(Automatic Reference Counting) 기반의 메모리 관리 기능이 활성화된다.
• ARC는 Objective-C 런타임 위에서 동작하므로, NSObject를 상속하지 않으면 ARC 기반의 자동 메모리 관리를 사용할 수 없다.
NSObject의 주요 기능
🧩 1. 객체의 생성, 초기화, 해제 관련 메서드 제공
• init(): 객체 초기화
• alloc(): 메모리 할당
• dealloc(): 객체 해제 (ARC에서는 직접 호출하지 않고 시스템이 자동 호출)
⚙️ 2. 런타임과 상호작용 (Objective-C Runtime)
동적 메시지 처리 (Dynamic Message Dispatch):
- Objective-C는 메서드 호출 시 컴파일 시점이 아닌 런타임 시점에 메서드를 탐색한다.(우리가 아는 @objc dynamic이이에 해당한다. swift는 기본적으로 정적 디스패치지만 저걸 통해 런타임시 동적으로 동작이 결정이 되므로 프로퍼티가 변경되었을때 KVO를 통해 관찰 가능하다.)
- NSObject는 이때 필요한 런타임 시스템과의 인터페이스를 제공한다.
- perform(_:with:) 메서드를 통해 동적으로 메서드를 호출할 수 있다.
객체의 런타임 정보 조회
3. KVO지원. NSObject 상속받으면 자동으로 KVO 활성화
4.메모리 관리(ARC)
자 그러면 우리가 언제 명시적으로 NSObject를 상속해야할까?
1. UIKit 컴포넌트가 아닌 클래스에서 KVO가 필요한 경우(즉 @objc 사용할때)
2. Objective-C런타임 기능 필요한 경우. 메서드 스위즐링 기능 필요한 경우(잉? 이게몬데? Runtime 시점에 기존 메서드를 다른 메서드로 바꾸어 실행 하는 것. 언제 사용하나 찾아봤더니 앱에 분석기능을통합할때, 특정 기능을 클래스 & 서브 클래스 모두 한번에 적용시키고 싶을때 등 사용한다고 함. 뭐 예를들어 뷰컨이 얼마나 생성되는지 분석하고 싶다면 method Swizzling을 이용하여 모든 뷰컨 viewDidLoad될때마다 분석기능 적용할수 있다고 한다. )
extension UIViewController { @objc public func swizzleViewdidLoad(animated: Bool) { print("나닛! swizzleViewdidLoad") } // 그 후 이 메서드 스위즐링을 적용하는 타입메서드를 만들어준다. class func swizzleMethod() { let originalSelector = #selector(viewDidLoad) let swizzleSelector = #selector(swizzleViewdidLoad) guard let originMethod = class_getInstanceMethod(UIViewController.self, originalSelector), let swizzleMethod = class_getInstanceMethod(UIViewController.self, swizzleSelector) else { return } method_exchangeImplementations(originMethod, swizzleMethod) } }
class_getInstanceMethod는 2개의 파라미터 가진다. 첫번째 파라미터는 클래스 자체를 가진다 여기엔 바꿔주고 싶은 메서드 클래스 자신을 넣는것이고 두번째 파라미터로는 해당클래스에서 어떤 메서드를 가져올지 Selector로 넣어준다. 여기서 주의해야할것이 Selector는 함수 자체를 가리키는 함수포인터가아니다@!!!!@ 바로 런타임 시접에 함수 테이블에서 내가 지정한 함수 이름을 찾아 실행하는 것이다. 그래서 Objective-C에는 존재하지 않는 함수명을 넣어도 컴파일타임에 에러가 안난다. 런타임때 찾으면서 에러가 생김. Selector에 대응하는 메서드가 함수 테이블에 없을수도 있으니 옵셔널 형식이고...마지막으로 method_exchangeImplementatoions 메서드 호출하면 끝.
그리고 AppDelegate에서 최초로 한번 실행해주면 모든 뷰DidLoad될때마다 우리가 바꾼 것이 실행된것이다.
하지만 메서드스위즐링은 런타임시점에 메서드를 임의로 바꾸는 것이기에 에러가 날 가능성이있고 버전 바뀌면서 문제가 생길수도 있다고 한다.
3. UIKit의 Delegate 패턴사용하는 경우
우리가 테이블뷰나 콜렉션뷰를 사용할때 딜리게이트 구현을 위해 상속받는데 여기에 NSObject를 상속받아야한다!!
왜? UITableViewDelegate나 UICollectionViewDelegate가 NSObjectProtocol을 상속받기 때문이다. NSObjectProtocol은 Objective-C 런타임 기능(동적 메시지 디스패치 등)을 사용하기 위한 최소한의 인터페이스를 정의한 프로토콜이겟고.
그렇다면 SwiftUI에서는 왜 NSObject를 잘 만나보지 못했을까
이전 글에 썻던 선언형 프로그래밍과 명령형 프로그래밍이 여기서 또 나온다.
UIKit은 명령형프로그래밍이며 클래스 기반으로 설계되었다.
이로 인해 많은 객체들이 NSObject를 상속하여 런타임에 동적으로 동작하는 Objective-C의 특징을 활용한다.
뭐 앞에서 말했던 Dynamic Dispatch, KVO, NSNotification등을 활용한다.
하지만 SwiftUI는 선언형 프로그래밍 기반으로 구조체 중심으로 설계되엇다. 그러므로 불변성을 강화하여 유킷보다 안전하고 예측 가능한 UI 상태관리를 제공한다. 더 나아가 컴파일타임때 상태를 분석하고 최적화하기에 NSObject의 런타임에 의존하는것과 맞지않다.
Combine을 활용한 반응형 상태관리로 데이터를 관리한다. 이러한 이유로 NSObject없이도 대부분의 상태관리가 가능하다.
오늘 정말 도움이 되었던 자료이다. iOS의 인플루언서 그린님이시다. 참고로 얼마전에 컨퍼런스 가서 뵈었다. 아싸
https://green1229.tistory.com/534
NSObject에 대하여
안녕하세요. 그린입니다 🍏이번 포스팅의 주제는 NSObject에 대해 한번 정리해보려 합니다 🙋🏻 사실, NSObject는 Swift 카테고리보다는 Objective-C에 더 가깝긴하죠.또, iOS 개발의 근간이라고 볼 수
green1229.tistory.com
'면접준비' 카테고리의 다른 글
근본으로 돌아가자(5) - 프로토콜 (0) 2025.03.03 Dynamic Dispatch는 어떻게 이루어지는가? 클래스 VS 프로토콜 (0) 2025.03.02 함수형 프로그래밍 & 명령형과 (유킷 스유) (0) 2025.02.16 SwiftUI runLoop (0) 2025.02.05 메모리관리(weak self와 guard의 만남) (0) 2025.01.12 다음글이전글이전 글이 없습니다.댓글