NSObject에 구현되어 있으므로 모든 객체에서 사용 가능

 

Person *p1 = [[Person alloc] init];
Pereson *p2 = [p1 copy];

copy 메소드 실행하면

NSCopying protocol에 있는

- (instancetype)copyWithZone:(NSZone *)zone method 실행 (zone: 시스템에서 지정한 메모리 공간)

 

아래 메소드를 구현해줘야 함 (NSCopying protocol을 따르게 해야함)

- (instancetype)copyWithZone:(NSZone *)zone {
	Person *newPerson = [[Person allocWithZone:zone] init];
    // 초기화할 멤버가 있다면 여기서 해줍니다.
    return newPerson;
}

 

직렬화(Serialization): OOP언어에서 특정 클래스 오브젝트를 파일로 저장하거나 파일에서 읽어들일 때 특수하게 가공하는 것을 의미. Objective-c나 Swift에서는 이부분은 Encode, Decode 용어를 사용

 

Encode: 직렬화(Serialize) 한다

Decode: 직렬화된 데이터를 오브젝트로 풀어내는 것(deserialization)을 의미

직렬화에서도 KVC(Key-Value Coding) 개념 사용됨 - property와 key 연결

NSCoder

  • byte stream을 추상화한 것
  • 데이터를 Coder로 쓰거나 Coder에서 데이터를 읽어 올 수 있음.
    (Coder - NSData 클래스에서 생성한 객체)
  • NSKeyedUnarchiver, NSKeyedArchiver를 사용하여 데이터 기록
    (NSCoder는 추상 클래스)

NSCoding protocol

- (id)initWithCoder:(NSCoder *)coder;               // 직렬화된 데이터에서 Object를 만들어 낼 때 호출

- (void)encodeWithCoder:(NSCoder *)coder;    // 직렬화할 때 자동 호출

 

NSKeyArchiver

// Swift
let data = NSKeyedArchiver.archivedDataWithRootObject(object)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: "object-key")

// Objective-c
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"object-key"];

 

NSKeyedUnarchiver

// Swift
if let data: NSData = NSUserDefaults.standardUserDefaults().objectForKey("object-key") as? NSData {
    let object: SomePersonClass = NSKeyedUnarchiver.unarchiveObjectWithData(data) as SomePersonClass
}

// Objective-C
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"object-key"];
SomePersonClass *object = [NSKeyedUnarchiver.unarchiveObjectWithData:data];

 

NSUserDefaults

  • 파일 시스템에 초기 기본 설정과의 차이점을 User default database에 저장함
  • 프리미티브 타입이 아닌 객체를 저장하고 싶으면 위의 NSCoding protocol을 적용하여 저장함.

+ (NSUserDefaults *)standardUserDefaults    // 공유된 기본설정 객체
- (void)registerDefaults:(NSDictionary *)dictionary    // 초기 기본설정 등록

// 설정을 바꾸는 메소드
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName 
- (void)setFloat:(float)value forKey:(NSString *)defaultName 
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName 
- (void)setObject:(id)value forKey:(NSString *)defaultName

- (BOOL)boolForKey:(NSString *)defaultName
- (float)floatForKey:(NSString *)defaultName
- (NSInteger)intgerForKey:(NSString *)defaultName
 - (id)objectForKey:(NSString *)defaultName

- (void)removeObjectForKey:(NSString *)defaultName

 

 

 

 

Ref. http://seorenn.blogspot.com/2014/11/swiftobjective-c-serialization.html

Key-value coding

  • 변수 이름으로 변수의 값을 선정하거나 가져오는 방식 (key-value mapping)

  • 변수 이름: key, string
    문자열을 이용해 property에 접근
    - 접근자(Accessor Methods) 통하지 않고 property 이름인 문자열로 접근하므로, 객체간 의존성을 낮추고 결합도가 낮은 소프트웨어 개발을 있음.

  • 관련 함수는 NSKeyValueCoding 프로토콜에 의해 정의됨.
    NSObject가 이 protocol을 confirm하므로 모든 자료형 가능

    - setValue:forKey:

    - valueForKey:

 

// set value
Student *s = [[Student alloc] init];
[s setValue:@“Larry” forKey:@“firstName”];

// get value
NSString *x = [s valueForKey:@“firstName”];

 

 

Key paths

  • 객체들을 특정 경로로 정렬.

  • 이름을 가져오는데 키 경로(Key Path)를 이용
    NSString *mn = [selectedPerson valueForKeyPath:@“spouse.scotter.modelName”];

  • 키 경로 연산자: @avg, @count, @max, @min, @sum
    NSNumber *theAvg = [employees valueForKeyPath:@“@avg.expctedRaise”];

 

Key-value Observing

  • 객체의 property 변경되는 것을 알고 싶을  사용하는 기능.
    (keypath 통해 property 변경을 감지하고 알려줌)

- (void)addObserver:(NSObject *)anObserver

               forKeyPath:(NSString *)keyPath

                    options:(NSKeyValueObservingOptions)options

                   context:(void *)context

      • keyPath 지정된 property 감시할 것을 등록.
      • Observer 객체는 anObserver, 
      • options property 변경될  보내지는 notification message이며, 
        종류는 NSKeyValueObservingOptionNew, NSKeyValueObservingOptionOld, OR 연산으로 두가지 같이   있음.

- (void)observeValueForKeyPath:(NSString *)keyPath

                                      ofObject:(id)object

                                        change:(NSDictionary *)change

                                        context:(void *)context

// NSObject에 정의  -> fido의 값이 변경되면 나에게 메시지를 줘!
[theAppDelegate addObserver:self
                 forKeyPath:@“fido”
                    options:NSKeyValueChangeOldKey
                     context:somePointer];

/* keypath : @“fido”
object: AppDelegate
context: observer로 등록할 때 인수로 사용한 context 주소 공간을 가리키는 포인터
change: fido 이전값, 새로운 값 
*/
- (void)observeValueForKeyPath:(NSString *)keyPath
				   	  ofObject:(id)object
					    change:(NSDictionary *)change
					   context:(void *)context {
                       //...
}

Cocoa Framework

  • 목적에 맞게 확장해야 할 기존 객체가 많음

  • ex) TableView의 subclass를 만드는 대신에, 간단하게 TableView에 helper object를 주면 됨.

Delegate

  • delegate outlet이 helper object를 가리키도록 설정

UITableView

  • dataSource라는 helper object가 있음 
    - UITableDataSource의 informal protocol을 준수해야함.

 

Delegate 동작 방식

객체가 delegate 메서드를 구현하면 Cocoa framework가 그 메서드 호출

NSObject에 아래 함수 가지고 있음
- (BOOL)respondsToSelector:(SEL)aSelector; // aSelector 메서드 존재 시 YES return

// delegate가 메서드를 구현했는지 확인
if([delegate respondsToSelector:@selector(tableView:shouldSelectRow:)]) {
    // 메서드 실행
    ok = [delegate tableView:self shouldSelectRow:rowIndex];
}

 

Protocol

java에서의 interface (약속!!!!)

 

- protocol: method 정의

- implement: class에서 사용

AppKit Framework

  • UIControl

  • UIButton, UISlider, UITextView ... - UIControl subclass

 

UIControl

  • target, action 존재

  • target: 다른 객체를 가리키는 포인터

  • action: target에 보내는 메시지 => selector
    - action method: parameter - sender, 어느 컨트롤이 메시지를 보내는지 알림.

UIControl

-(void)setAction:(SEL)aSelector

 

Selector

: Objective-c 컴파일러의 @selector지시자가 컴파일러에 셀렉터를 찾으라고 알려줌.

SEL mySelector = @selector(drawMickey:);    // 컴파일시, drawMickey: 셀렉터 로 교체

[myButton setAction:mySelector];

 

 

 

 

TODO: Responder chain and Touch Event

https://baked-corn.tistory.com/129

nil / Nil / NULL / NSNULL 대한 차이점과, Objective-C에서의 nil과 Swift에서의 nil에 대해 알아보자

 

 

1. nil / NULL / Nil

사용할 수 없는 번지를 가리키는 포인터(pointer), 즉 아무 객체도 가리키지 않는다

 

nil

Objective-c object의 부재를 나타내는 null Instance pointer

NSString * strObject = nil;

 

Nil

- Objective-c class의 부재를 나타낼 때는 null class pointer
- Objective-c class: 자신이 속한 클래스의 정보를 가진 구조체.

Class myClass = Nil

 

NULL

- traditional C null pointer

- c-pointer의 부재(주소가 0) 및 C나 C++의 변수 및 객체에 사용

int *intPtr = NULL;

 

 

2. NSNull

- NSObject를 상속받는 객체

- collection item을 null로 설정할 필요가 있을때 사용

myArray addObject:[NSNull null]];
 
if ([myArray objectAtIndex:0] == [NSNull null])

 

 

 

3. Objective-c에서의 nil 과 Swift에서의 nil 차이점

차이점

Objective-C에서의 nil은 존재하지 않는 객체에 대한 포인터(pointer)이고

Swift에서의 nil는 포인터가 아니다 => 단지, 특정 타입에 대한 값의 부재를 나타내는 것

 

즉, Swift에서의 nil은 객체가 아니더라도 어떤 타입이든 Optional로 nil을 가질 수 있다.
(Objective-C에서는 객체만 nil을 가질 수 있고, primitive type은 가질 수 없음 ex. int, ...)

 

 

 

 

 

 

 

 

Ref.

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

https://inboony.tistory.com/10

 

 

Property

@property (readWrite, assign) int fido;    // 접근 메서드 fido, setFido: 선언과 동일
@synthesize fido;                          // 접근 메서드 구현과 동일

 

@property

: property의 attribute에 의해서 accessor method(getter/setter)가 자동으로 선언됨.

 

[Property Attribute]

  • atomic: multi-thread에서 충돌 방지(mutax 설정하여 변수보호)
    nonatomic: multi-thread
  • readwrite(기본값), readonly: 변경x
  • assign(기본값): 단순 대입. 스칼라형
  • strong: 강한 참조. ARC
  • weak: 약한 참조. assign과 비슷, 객체가 메모리에 할당되면 해당 객체를 가리키던 property  nil로 설정됨. ARC
  • copy: 새로운 값을 복사하고 변수에 복사한 값을 대입. (NSCopying protocol 구현되있어야 함)

@sythesize

accessor method가 자동 구현됨. 변수명을 바꿀 수 있다.

@dynamic

accessor method가 자신의 클래스가 아닌 다른 곳에 구현되어 있음을 알려주는 지시어.

 

iOS 메모리 관리

  • Retain Count
    - 객체의 참조수를 관리하여 alloc시 참조수 1 증가, 0이 되면 객체 메모리 해제
    - retain, release 메시지 사용

  • Mac OS X 10.5 : Garbage collector
    - 프로그램 실행 중 동적으로 감시하고, 해당 영역에 있는 변수에서 접근 할 수 없는 객체 찾고 자동으로 메모리 해제
    - 실행 타임에서 메모리 관리
    - 문제점: 쓰레기 객체 탐색을 위해 CPU 소비 필요

  • Mac OS 10.7 : ARC
    - 코드를 컴파일 할 때 참조수를 컴파일러가 증가, 감소 관리

Strong Reference Cycle

    • 인스턴스가 서로 강한(strong) 참조 하여 메모리에서 사라지지 않는 경우
    • ARC Reference Cycle 자동적으로 대응 불가
    • ‘weak’ 이용하여 방지
    • custom delegate weak attribute 하는 이유

Retain Count

  • 참조 종류
    - Strong Reference:  객체가 다른 객체를 retain 하는 것. 기본 설정
    - Weak Reference
    : retain하지 않는 것. 단순 포인터 대입 (참조 순환 피하기 위해)
    : Zeroing Weak Reference: ARC에서 약한 참조의 객체가 메모리 해제할 때 nil로 설정하여 메모리 crush 예방
  • dealloc
    - 참조 수가 1인 객체에 release 보내면 호출됨
    - 마지막에 [super dealloc];
  • NSAutoreleasePool
    - 객체에 autorelease 메시지 -> Autorelase pool에 객체 추가 (가비지 컬렉터를 사용하지 않을 때)
    - Cocoa application: 모든 이벤트를 제어하기 전에 생성, 제어 후 해제
    - 오토릴리즈 객체를 리턴하는 클래스 메서드들이 있음. 
       ex) [NSString stringWithFormat: ….]
    - Release 시점: 보통 현재 이벤트 루프가 끝날 때
  • Retain
    - alloc, new, copy가 포함된 이름을 가진 메서드 (copy, mutableCopy ...)
      => 참조수 + 1 (atorelease pool x)
    - release 해야할 의무가 있음
  • Release
    - 소유를 원하지 않을 경우 release or autorelease
    - 0일 때 dealloc
  • 접근자 메서드
    - 다른 객체들이 인스턴스 변수를 접근하기 위해 사용
    - getter, setter
- (void)setFoo:(NSDate *) x {
    [x retain];
    [foo release];
    foo = x;
}

- (NSDate *)foo {
    return foo;
}

 

 

Swift version Strong reference cycle 볼 필요 있음

https://rhammer.tistory.com/139

+ Recent posts