
// h.file
@interface Car : NSObject
@property NSString *name;
@property Boolean isOn;
-(void)turnEngineOn;
// init - override
- (instancetype) initWithState : (Boolean) starState;
@end
@implementation Car
- (void)turnEngineOn {
_isOn = true;
}
- (instancetype) initWithState : (Boolean) starState {
self = [super init];
_isOn = starState;
return self;
}
@end
Car *jeep = [[Car alloc] init];
Car *corolla = [[Car alloc] initWithState: true];
@protocol sendingMessageProtocol <NSObject>
- (void) send: (NSString *)message;
@end
#import "Protocol.h"
@interface ViewController : UIViewController <sendingMessageProtocol>
@end
- (void) send: (NSString *)message {
receiveMessageLabel.text = message;
}
GreenViewController 인스턴스.delegate = self;
여기서는 GreenViewController → ViewController 로 데이터를 보내기 때문에, GreenViewController 가 위임받은 ViewController 입니다.
@property (nonatomic) id <sendingMessageProtocol> delegate;
// Swift
var delegate: sendingMessageDelegate
[self.delegate send: textToSend];
@interface NSString (Reverser)
-(NSString *)reverseIt;
@end
@implementation NSString (Reverser)
-(NSString *)reverseIt {
NSMutableString *result = [NSMutableString new];
NSInteger stringLength = [self length];
while (stringLength > 0) {
stringLength --;
NSRange substringRange = NSMakeRange(stringLength, 1);
NSString *prevChar = [self substringWithRange:substringRange];
[result appendString: prevChar];
}
return result;
}
@end
NSString* helloString = @"Hello World";
NSString *reverseString = [helloString reverseIt];
atomic과 nonatomic은 속성의 쓰레드 안전성에 관련된 키워드
동기화된 접근: atomic 속성은 기본적으로 쓰레드 안전성을 보장합니다.
즉, 여러 쓰레드에서 동시에 속성에 접근할 때 데이터의 일관성을 유지합니다.
기본 설정: 별도로 지정하지 않으면, 속성은 atomic으로 설정됩니다.
성능: atomic 속성은 동기화 오버헤드로 인해 nonatomic보다 느립니다.
특징: atomic 속성은 '모든 쓰레드에서 속성을 읽거나 쓸 때 완전히 완료된 접근'을 보장합니다.
이는 속성 접근 시 잠금(lock) 메커니즘을 사용하여 구현됩니다.
@property (atomic, strong) NSString *atomicString;
비동기화된 접근: nonatomic 속성은 쓰레드 안전성을 보장하지 않습니다.
즉, 여러 쓰레드에서 동시에 속성에 접근할 때 데이터의 일관성이 깨질 수 있습니다.
성능: nonatomic 속성은 동기화 오버헤드가 없기 때문에 atomic보다 빠릅니다.
특징: nonatomic 속성은 주로 성능이 중요한 상황에서 사용됩니다.
쓰레드 안전성을 개발자가 직접 관리해야 합니다.
@property (nonatomic, strong) NSString *nonatomicString;
readonly 키워드는 속성을 읽기 전용으로 만듭니다.
이 속성은 값이 설정된 후 변경할 수 없으며, 자동으로 setter 메서드가 생성되지 않습니다.
@property (nonatomic, readonly) NSString *readOnlyString;
readwrite는 속성을 읽기/쓰기 가능하게 만듭니다.
이는 기본값이므로 명시적으로 지정하지 않아도 됩니다. setter와 getter 메서드가 자동으로 생성됩니다.
@property (nonatomic, readwrite) NSString *readWriteString;
Objective-C 에는 Class Method 라는 것이 존재합니다. + 를 사용하여 메서드를 생성하는 것입니다.
기존에 - 를 사용하면 인스턴스 메서드라고 하는데, 이는 인스턴스에 접근하여 메서드를 사용합니다.
@interface MyClass: NSObject {
+(void)doSomething;
@end
@implementation MyClass
+(void)doSomething {
// 클래스 메서드 내부 구현
}
@end
+ (void)classMethod {
// 클래스 메소드 구현
}
- (void)instanceMethod {
// 인스턴스 메소드 구현
}
// 클래스 메소드 호출
[MyClass sayHello];
// 인스턴스 생성 및 인스턴스 메소드 호출
MyClass *myInstance = [[MyClass alloc] init];
[myInstance greetWithName:@"Objective-C"];
기본 참조 방식으로, 객체에 대한 강한 참조를 나타냅니다. 객체의 참조 카운트를 증가시키며, 이 객체에 대한 모든 강한 참조가 해제될 때까지 객체가 메모리에서 해제되지 않습니다.
@property (nonatomic, strong) MyClass *myObject;
객체에 대한 약한 참조를 나타냅니다. 객체의 참조 카운트를 증가시키지 않으며, 객체가 메모리에서 해제되면 참조가 자동으로 nil로 설정됩니다. 주로 강한 참조 순환을 방지하기 위해 사용됩니다.
@property (nonatomic, weak) MyClass *myObject;
Objective-C의 MRC(Manual Reference Counting) 시절의 속성으로, 객체의 참조 카운트를 증가시킵니다. ARC(Automatic Reference Counting)를 사용하는 경우 strong으로 대체되었습니다.
@property (nonatomic, retain) MyClass *myObject;
객체에 대한 단순한 참조를 나타내며, 참조 카운트를 증가시키지 않습니다. 주로 기본 데이터 타입(예: int, float)이나 weak를 사용할 수 없는 경우에 사용됩니다.
@property (nonatomic, assign) NSInteger myInteger;
객체의 복사본을 생성하여 소유합니다. 주로 NSString, NSArray와 같은 불변 객체에 사용됩니다. 객체의 상태가 변경될 위험이 있는 경우 안전하게 사용할 수 있습니다.
@property (nonatomic, copy) NSString *myString;
Obj-C 에서의 SEL 은 Swift에서 addTarget 의 @selector 랑 똑같음.
형태는 아래와 같음.
SEL btnSelector = @selector(testBtnClicked:);
SEL 는 어디에 사용이 될까??
방금 앞서 말했듯이, Swift 에서 addTarget 에 들어가는 @selector 과 동일하다고 했음.
그럼 먼저 함수를 만들어 보아야겠죠??
아래 함수는 반환 값이 없는 함수이며, sender 로 UIButton 을 입력받는 함수임.
그리고 NSStringFromSelector(_cmd) 는 현재 실행하고 있는 함수의 이름을 가져오는 것이고, _cmd 는 현재 실행되고 있는 셀렉터의 이름을 가져오는 것임.
- (void)onTestBtnClicked:(UIButton *) sender {
// NSStringFromSelector(_cmd) : 현재 실행하고 있는 함수 이름을 가져옴.
NSLog(@"name: %@ , btnTitle: %@", NSStringFromSelector(_cmd),
sender.titleLabel.text);
}
함수를 만들었으니, 함수를 버튼과 인식을 시켜봅시당
코드는 아래와 같음.
간략하게 설명을 드리면, 위에 만들어두었던 함수를 SEL로 만들기 위해서는 @selector(함수) 이런식으로 포장을 해주어야함.
SEL btnSelector = @selector(onTestBtnClicked:);
[_selectorTestButton addTarget:self action:btnSelector forControlEvents:UIControlEventTouchUpInside];
근데, 우리는 왜 위 코드처럼 귀찮게 SEL로 포장해서 사용을 해야할까??
그걸 이해하기 위해서는 addTarget 의 문장 구성을 이해해야함.
- (void)addTarget:(id)target
action:(SEL)action
forControlEvents:(UIControlEvents)controlEvents;
addTarget : (id)target 라고 되어 있는데, 여기에는 간단히 self 로 쓰면됨.
action : (SEL) action 으로 되어 있는게 보임? (SEL) 로 만들어줘야 정상적으로 빌드가 되기 때문에, 우리는 @selector 에 함수를 넣어서 SEL을 만들어줘야함.
forControlEvents:(UIControlEvents)controlEvents 는 Swift 에서와 마찬가지로 .touchupInside 와 똑같다고 생각하면됨.
Objc-C 에서의 id는 클래스 객체 인스턴스 메모리 주소 반환, 즉 포인터임.
코드는 아래와 같음.
// 여기 id 가 어떤 클래스의 인스턴스를 뜻함.
+ (id)getAFriend{
Friend *aFriend = [[Friend alloc] init];
[aFriend setNickname:@"호호호호호호호"];
// Friend 생성하여 메모리 반환.
return [[Friend alloc] init];
}
// 위 함수와 아래 함수는 동일함.
+ (Friend *)getMyFriend {
Friend *aFriend = [[Friend alloc] init];
[aFriend setNickname:@"내 친구임."];
return aFriend;
}
Friend * 는 Friend 메모리 주소 자체를 반환하는 것이기 때문에 id 를 반환하는 것과 동일함.
Objc-C 에도 getter / setter 라는 함수가 존재함.
getter / setter 는 함수이기 때문에 사용할 때 [] 를 써야함.
Objc-C 에서 getter 는 @property nickname 이라는 변수가 있다고 가정할 때, 그 값을 조회하는 것임.
[aNewFriend setNickname]; // getter
Objc-C 에서 setter 는 @property nickname 이라는 변수가 있다고 가정할 때, 그 값을 새로운 값을 삽입하는 것임.
그런데, getter 와는 달리 setter 는 nickname 이 아니라, setNickname 임.
이유는 setter 를 사용할 때는 변수 앞에 set변수명(변수명 맨 앞은 대문자)로 해줘야함.
[aNewFriend setNickname: @"호호호"]; // setter