본문 바로가기

iOS

iOS 터치-4

728x90
반응형
SMALL

UIResponder.h


그럼 고대하던 UIResponder.h 를 읽어보는 시간 :)

#if (defined(USE_UIKIT_PUBLIC_HEADERS) && USE_UIKIT_PUBLIC_HEADERS) || !__has_include(<UIKitCore/UIResponder.h>)

이 코드는 UIKitCore 프레임워크에서 UIResponder.h 헤더 파일을 포함하고 있는지 확인하고, 만약 헤더 파일이 없다면 UIKit public 헤더 파일을 사용할 것인지를 결정하는 조건문입니다.

defined(USE_UIKIT_PUBLIC_HEADERS) && USE_UIKIT_PUBLIC_HEADERS  -> 이게 둘 다 있거나?

!__has_include(<UIKitCore/UIResponder.h>) -> UIKitCore 프레임워크에서 UIResponder.h 헤더 파일을 포함하지 않는다면?

 

(UIResponder.h 헤더 파일이 없을 수가 있나요? chatGPT 선생님께서도 재설치를 권장하셨습니다. '그냥 그런가보다' 하고 지가나야할 것 같습니다.)

 

*** UIKit public 헤더 파일이란? ***

UIKit public 헤더 파일은 iOS 애플리케이션 개발에 필요한 UIKit 프레임워크의 공개 API를 정의한 헤더 파일입니다. 이 파일은 UIKit 프레임워크에서 제공되는 클래스, 프로퍼티, 메서드 등을 사용하기 위해서는 반드시 포함되어야 하는 파일입니다. UIKit public 헤더 파일은 iOS 애플리케이션 개발에 필수적인 요소로, Objective-C나 Swift 언어로 작성된 코드에서 사용됩니다. 이 파일에는 UIKit에서 제공하는 뷰, 컨트롤러, 레이아웃, 애니메이션, 터치 이벤트 처리 등 다양한 기능들이 포함되어 있습니다.

 

#import <Foundation/Foundation.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UIEvent.h>
#import <UIKit/UIKeyCommand.h>
#import <UIKit/UIPasteConfigurationSupporting.h>
#import <UIKit/UIUserActivity.h>

헤더 파일들을 import 하고

 

*** 각 헤더의 설명***

Foundation/Foundation.h: Foundation 프레임워크에서 제공하는 클래스와 메서드를 사용하기 위한 헤더 파일입니다.

UIKit/UIKitDefines.h: UIKit 프레임워크에서 정의한 상수와 타입을 사용하기 위한 헤더 파일입니다.

UIKit/UIEvent.h: iOS 애플리케이션에서 발생하는 이벤트를 처리하기 위한 클래스와 프로토콜을 정의한 헤더 파일입니다.

UIKit/UIKeyCommand.h: 키보드 단축키를 처리하기 위한 클래스와 프로토콜을 정의한 헤더 파일입니다.
('Responder 인데 왜 단축키헤더가 들어있지? 했는데!!! 사용자 인터페이스 이벤트 및 키보드 이벤트 처리를 같이하기 때문이었습니다. 지능이슈...)

UIKit/UIPasteConfigurationSupporting.h: 클립보드 기능을 지원하는 클래스와 프로토콜을 정의한 헤더 파일입니다.

UIKit/UIUserActivity.h: 앱 간 데이터 공유를 위한 사용자 활동 정보를 처리하는 클래스와 프로토콜을 정의한 헤더 파일입니다.

(이 파일은 또 왜??? 했는데.. UIKit/UIUserActivity.h 파일이 포함하는 UIUserActivity 클래스가 앱이 실행되지 않은 상태에서 사용자 액션에 응답하고, 해당 앱을 열어 특정 상태로 이동하는 데 사용되기 때문이라고 합니다. )

 

USE_UIKIT_PUBLIC_HEADERS가 정의되어 있고, 값이 true일 경우 UIKit public 헤더 파일을 사용하며, 값이 false이거나 정의되어 있지 않은 경우에는 UIResponder.h 헤더 파일을 사용합니다. (??? 그러면  UIKit public 헤더 파일이 뭔지부터 공부해야 할 것 같은데요?...)

__has_include 매크로는 현재 컴파일 중인 환경에서 지정된 헤더 파일이 존재하는지 여부를 확인하는데 사용됩니다.

NS_HEADER_AUDIT_BEGIN(nullability, sendability)

NS_HEADER_AUDIT_BEGIN(nullability, sendability)는 Objective-C 코드에서 사용되는 *매크로로서, 코드의 가독성과 안정성을 높이기 위해 사용됩니다.

*NS_HEADER_AUDIT_BEGIN는 애초에 Apple의 Clang 컴파일러에서 매크로이며,nullability 및 sendability 정보를 감사하기(audit) 시작한다는 것을 나타냅니다.

nullability는 변수, 매개변수, 반환 값 등이 null 값을 가질 수 있는지 여부를 나타내는 속성

sendability는 객체가 분산 시스템에서 전송 가능한지 여부를 나타내는 속성

 

*** Objective-C 코드에서 사용되는 매크로란? ***

Objective-C 코드에서 사용되는 매크로는 C 언어의 매크로 기능을 상속받아 Objective-C 언어에서도 사용할 수 있는 것을 말합니다. 매크로는 코드 내에서 미리 정의된 문자열을 코드의 일부로 대체하여 사용하는 기능을 제공합니다. 대표적으로 #define을 이용해 상수나 함수를 정의하는 경우가 있습니다. Objective-C에서는 C 언어에서 사용하는 매크로 기능을 그대로 사용할 수 있으며, 더불어 Objective-C에서만 사용 가능한 특별한 매크로들도 있습니다. 예를 들어, Objective-C의 클래스 및 프로토콜을 정의할 때 사용하는 @interface와 @protocol 키워드도 사실상 매크로로 동작합니다.

typedef NSDictionary<NSAttributedStringKey, id> * _Nonnull(^UITextAttributesConversionHandler)(NSDictionary<NSAttributedStringKey, id> * _Nonnull);

이 코드는 Objective-C에서 사용되는 *블록 타입인데, UITextAttributesConversionHandler라는 이름으로 선언되어 있습니다. 이 블록 타입은 NSAttributedStringKey와 id를 key-value 쌍으로 가지는 NSDictionary를 입력으로 받고, 같은 타입의 NSDictionary를 반환합니다. 또한 반환되는 NSDictionary와 입력으로 받은 NSDictionary는 둘 다 nonnull입니다.

 

*** 코드 블록과 블록 타입이란? ***

 블록 타입코드 블록을 변수로 사용할 수 있는 타입이며, 코드 블록실행 가능한 코드의 묶음으로, 변수나 상수, 함수 등과 마찬가지로 하나의 독립된 요소로 취급됩니다. 코드 블록은 ^ 연산자를 사용하여 선언되며, 해당 블록이 수행할 작업과 입력 및 출력 매개변수의 타입을 지정할 수 있습니다.

 

코드 블록 예제

// 블록 선언
int (^multiply)(int, int) = ^(int a, int b) {
    return a * b;
};

// 블록 사용
int result = multiply(5, 10);
NSLog(@"5 * 10 = %d", result); // 5 * 10 = 50 출력

 

NS_SWIFT_UI_ACTOR

NS_SWIFT_UI_ACTOR는 Swift에서 UI 요소에 대한 비동기 처리를 위해 사용하는 어노테이션입니다. 이 어노테이션은 비동기적으로 실행되는 메서드가 해당 UI 요소에 대한 접근을 제한함으로써 UI 스레드에서의 안정성을 보장합니다.

*** 액터란? ***

액터는 Swift 5.5에서 도입된 새로운 동시성 기능으로, 여러 동시 작업(다중 스레드 환경)에서, 메서드 호출과 상태 접근을 단일 스레드로 제한함으로써, 안전하게 상태를 관리하고 동기화할 수 있습니다.

예제 코드

actor Counter {
    private var count = 0
    
    func increment() {
        count += 1
    }
    
    func getCount() -> Int {
        return count
    }
}

// Counter 인스턴스 생성
let counter = Counter()

// 동시에 수행되는 작업 1
Task {
    await counter.increment()
    print("작업 1 결과: \(await counter.getCount())")
}

// 동시에 수행되는 작업 2
Task {
    await counter.increment()
    print("작업 2 결과: \(await counter.getCount())")
}

실행결과

class와 struct, actor 각각의 예제를 통해 차이를 확인 가능합니다. :)

 

*** 클래스로 선언 ***

*** struct로 선언 ***

@State 래퍼는 SwiftUI에서 View의 상태를 저장하기 위한 프로퍼티 래퍼입니다. 이 래퍼는 View를 구성하는 값들을 저장하고, 값이 변경되면 View를 업데이트하도록 설계되어 있습니다.

하지만 struct는 값 타입이므로, 값을 복사하여 사용합니다. 따라서 counter.increment() 호출 시, Counter 구조체의 새로운 인스턴스가 생성되고, 그 인스턴스의 count 프로퍼티가 증가합니다. 그리고 작업이 끝나면 해당 인스턴스는 메모리에서 해제됩니다. 따라서 두 작업에서 생성된 Counter 인스턴스는 서로 다른 인스턴스이므로, 값이 공유되지 않습니다. 따라서 count 값이 변하지 않는 것입니다.

 

@optional

@optional은 Objective-C 프로토콜에서 메소드의 구현이 선택적(Optional)임을 나타내는 예약어입니다. 이 예약어를 사용하면 프로토콜에서 선언한 메소드가 구현되지 않더라도 컴파일 에러가 발생하지 않습니다. 따라서 구현해도 되고 구현하지 않아도 되는 메소드를 정의할 때 사용됩니다. @required는 반대로 해당 메소드가 반드시 구현되어야 함을 나타내는 예약어입니다.

- (void)cut:(nullable id)sender API_AVAILABLE(ios(3.0));
- (void)copy:(nullable id)sender API_AVAILABLE(ios(3.0));
- (void)paste:(nullable id)sender API_AVAILABLE(ios(3.0));
- (void)pasteAndMatchStyle:(nullable id)sender API_AVAILABLE(ios(15.0));
- (void)pasteAndGo:(nullable id)sender API_AVAILABLE(ios(15.0));
- (void)pasteAndSearch:(nullable id)sender API_AVAILABLE(ios(15.0));
- (void)select:(nullable id)sender API_AVAILABLE(ios(3.0));
- (void)selectAll:(nullable id)sender API_AVAILABLE(ios(3.0));
- (void)delete:(nullable id)sender API_AVAILABLE(ios(3.2));
- (void)makeTextWritingDirectionLeftToRight:(nullable id)sender API_AVAILABLE(ios(5.0));
- (void)makeTextWritingDirectionRightToLeft:(nullable id)sender API_AVAILABLE(ios(5.0));
- (void)toggleBoldface:(nullable id)sender API_AVAILABLE(ios(6.0));
- (void)toggleItalics:(nullable id)sender API_AVAILABLE(ios(6.0));
- (void)toggleUnderline:(nullable id)sender API_AVAILABLE(ios(6.0));

- (void)increaseSize:(nullable id)sender API_AVAILABLE(ios(7.0));
- (void)decreaseSize:(nullable id)sender API_AVAILABLE(ios(7.0));

- (void)find:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)findAndReplace:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)findNext:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)findPrevious:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)useSelectionForFind:(nullable id)sender API_AVAILABLE(ios(16.0));

- (void)updateTextAttributesWithConversionHandler:(NS_NOESCAPE UITextAttributesConversionHandler _Nonnull)conversionHandler API_AVAILABLE(ios(13.0));
- (void)print:(nullable id)sender NS_SWIFT_NAME(printContent(_:)) API_AVAILABLE(ios(15.0));

- (void)rename:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)duplicate:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)move:(nullable id)sender API_AVAILABLE(ios(16.0));
- (void)export:(nullable id)sender API_AVAILABLE(ios(16.0));

void 함수가 반환할 값이 없음을 나타내는 C언어의 예약어입니다. Objective-C에서도 함수의 반환 타입으로 사용됩니다. 따라서 위 코드에서 함수들이 값을 반환하지 않고 어떤 작업을 수행하는 것을 나타냅니다.

 

코드에 따라 받는 파라미터로 "sender"나 "conversionHandler" 라는 객체를 받을 있습니다.

"nullable" 해당 파라미터가 nil 값을 받을 있음을 의미합니다.

API_AVAILABLE 매크로를 사용하여 각 메소드가 iOS 3.0 ~ 16.0 이후부터 사용 가능함을 나타냅니다.

 

@end

@end Objective-C 프로그래밍 언어에서 사용되는 키워드로, 클래스나 프로토콜의 끝을 표시하는 역할을 합니다. @interface @implementation 짝을 이루어 해당 클래스나 프로토콜의 범위를 표시하며, @end 통해 범위가 끝나는 것을 나타냅니다. 키워드는 C 프로그래밍 언어의 중괄호({}) 같은 역할을 하며, Objective-C 코드에서는 필요한 요소 하나입니다.

 

728x90
반응형
LIST

'iOS' 카테고리의 다른 글

API 키 숨기기, xcconfig파일로  (0) 2023.04.20
Feature, ViewModel, UseCase  (0) 2023.04.20
iOS 터치-3  (0) 2023.04.16
iOS 터치-2  (0) 2023.04.16
iOS 터치-1  (0) 2023.04.16