반응형
[iOS Study] Objective-C |
출처 : 아론 힐리가스의 iOS 프로그래밍
-
iOS 앱은 코코아 터치(Cocoa Touch) 프레임워크를 사용하여 Objective-C 언어로 작성된다.
Objective-C 는 C 언어의 확장이며 코코아 터치 프레임워크는 Objective-C 클래스의 모음이다.
-
일반적으로 Objective-C 에서는 인스턴스 변수명을 밑줄(_) 로 시작한다.
-
객체를 만들기 위해서는 클래스에 alloc 메세지를 보낸다.
이에 클래스는 메모리(힙)에 객체를 만들고 변수에 저장된 그 객체의 주소를 준다.
-
Party* partyInstance = [Party alloc];
[partyInstance init];
인스턴스를 만들기 위해 클래스에 alloc 메시지를 보내더라도 그 인스턴스는 초기화되기 전까지 유효하지 않다.
-
[[Party alloc] init];
위와 같은 문법을 중첩 메세지 보내기(nested message send) 라고 한다.
-
메시지는 항상 대괄호 안에 포함된다.
대괄호 안에 메시지는 세 부분으로 나뉜다.
리시버(receiver) : 메시지를 실행할 객체의 포인터
셀렉터(selector) : 실행한 메소드의 이름 ( 모든 라벨을 합친 것 )
인자(arguments) : 실행할 메소드에 매개변수로 전달되는 값들
라벨과 인자가 쌍을 이루는 것은 Objective-C 의 중요한 특징이다.
-
위와 같은 문법을 중첩 메세지 보내기(nested message send) 라고 한다.
-
메시지는 항상 대괄호 안에 포함된다.
대괄호 안에 메시지는 세 부분으로 나뉜다.
리시버(receiver) : 메시지를 실행할 객체의 포인터
셀렉터(selector) : 실행한 메소드의 이름 ( 모든 라벨을 합친 것 )
인자(arguments) : 실행할 메소드에 매개변수로 전달되는 값들
라벨과 인자가 쌍을 이루는 것은 Objective-C 의 중요한 특징이다.
-
메소드는 시랭 가능한 코드의 모음이고, 메시지는 클래스나 객체에게 메소드를 실행하도록 요청하는 행위이다.
-
객체를 제거하려면 객체를 가리키는 변수를 nil 로 설정한다.
nil 변수는 제로 포인터(zero pointer) 이다.
-
포인터가 nil 인지 확인하기 위한 단축형은..
if ( !venue )
-
만약 nil 인 변수에 메시지를 보내면 아무 일도 벌어지지 않는다.
-
만약 프로그램이 무언가 해야 하는 시점에 아무런 동작도 하지 않는다면 예상하지 못한 nil 포인터가 종종 원인일 수 있다.
-
포인터가 nil 인지 확인하기 위한 단축형은..
if ( !venue )
-
만약 nil 인 변수에 메시지를 보내면 아무 일도 벌어지지 않는다.
-
만약 프로그램이 무언가 해야 하는 시점에 아무런 동작도 하지 않는다면 예상하지 못한 nil 포인터가 종종 원인일 수 있다.
-
모든 클래스는 NSObject 에 정의된 메소드와 인스턴스 변수를 상속한다.
-
%@ 는 어떤 객체 포인터와도 일치하는 포맷팅 문자이다.
그 인자는 description 메세지에 보내진다.
description 메소드는 토큰을 대신하는 NSString 인스턴스를 반환한다.
%@ 토큰에 상응하는 인자는 메시지로 보내지기 때문에 반드시 객체여야 한다.
-
.h 헤더 파일은 새 클래스 이름, 상위 클래스, 인스턴스 변수, 구현할 메소드 등을 선언한다.
.m 파일은 구현 파일로 구현하는 메소드의 실제 코드를 갖는다.
-
%@ 는 어떤 객체 포인터와도 일치하는 포맷팅 문자이다.
그 인자는 description 메세지에 보내진다.
description 메소드는 토큰을 대신하는 NSString 인스턴스를 반환한다.
%@ 토큰에 상응하는 인자는 메시지로 보내지기 때문에 반드시 객체여야 한다.
-
.h 헤더 파일은 새 클래스 이름, 상위 클래스, 인스턴스 변수, 구현할 메소드 등을 선언한다.
.m 파일은 구현 파일로 구현하는 메소드의 실제 코드를 갖는다.
헤더 파일을 클래스 인스턴스의 사용 설명서로 생각할 수 있고,
구현 파일은 실제 동작하는 법을 정의한 세부 기술로 생각할 수 있다.
-
클래스를 선언하려면 @interface 키워드를 클래스 이름 앞에 사용한다.
콜론(:) 다음에 상위 클래스 이름이 온다.
Objective-C 는 단일 상속만을 허용한다.
-
클래스를 선언하려면 @interface 키워드를 클래스 이름 앞에 사용한다.
콜론(:) 다음에 상위 클래스 이름이 온다.
Objective-C 는 단일 상속만을 허용한다.
@end 지시자는 클래스 선언의 끝을 가리킨다.
-
클래스의 인스턴스 변수는 클래스 선언 다음의 중괄호 {} 사이에 선언한다.
그것들은 기본으로 protected 의 성격을 갖는다.
-
Objective-C 에서 세터 메소드의 이름은 그저 인스턴스 변수이름 그대로이다.
-
-
클래스의 인스턴스 변수는 클래스 선언 다음의 중괄호 {} 사이에 선언한다.
그것들은 기본으로 protected 의 성격을 갖는다.
-
Objective-C 에서 세터 메소드의 이름은 그저 인스턴스 변수이름 그대로이다.
-
구현 파일의 맨 위에는 항상 그 클래스의 헤더 파일을 임포트(import) 한다.
임포트는 해당 파일을 한 번만 포함하는 것을 보장한다.
-
import 문 다음은 @implementation 키워드와 구현할 클래스 이름으로 시작하는 구현 블록이다.
구현 파일에서 모든 메소드 정의는 이 구현 블록 안에 있다.
메소드들의 정의는 @end 키워드가 나타나 블록이 닫힐 떄까지 계속된다.
-
리시버 뒤에 .(점)이 따라오고 그 뒤에 밑줄 없는 인스턴스 변수명이 온다.
이는 접근자 메소드를 호출하는 것과 동일하다.
최근 Objective-C 프로그래머들은 접근자를 호출하기 위해 점 표기법을 사용하는 경향이 있다.
코드를 읽기 쉽게 만들어주고, 중첩된 메시지 호출을 해야 할 때 읽기 쉬워 좋다.
애플의 코드와 일관성도 유지된다.
-
NSObject 인스턴스에 description 메시지를 보내면
해당 객체 클래스 이름과 메모리 주소를 반환한다.
-
클래스 내부에 있는 인스턴스 변수라도 접근자 메소드를 사용하는 것이 좋다.
-
각 초기화 메소드는 init 이라는 단어로 시작한다.
초기화 메소드 명명법이 다른 인스턴스 메소드와 어떠한 차이를 만들어내는 것은 아니다.
단지 이름을 나타내는 방식이다.
-
지정 초기화 메소드는 객체의 모든 인스턴스 변수를 유효하게 만든다.
유효하다는 것은 객체 초기화 후에 메시지를 보낼 때 결과를 예측할 수 있고 아무런 문제가 없음을 뜻한다.
-
instancetype ( 이전에는 id ) 키워드는 반환 타입으로만 사용할 수 있고, 그 반환 타입은 메시지의 리시버와 일치한다.
init 메소드는 항상 instancetype 을 반환하도록 선언된다.
왜 반환 타입이 포인터가 아닐까?
그 이유는 해당 클래스가 하위 클래스를 가진 경우 문제가 될 수 있기 때문이다.
-
Objective-C 에서는 같은 셀렉터와 다른 반환 타입(또는 인자)을 가진 형태의 메소드를 여러 개 가질 수 없다.
( overloading 을 지원하지 않는다. )
-
Objective-C 에 instancetype 키워드가 생기기 전에는 초기화 메수드가 id 를 반환했다.
id 는 임의의 객체에 대한 포인터로 정의되어 있다.
id 는 객체의 타입이 불확실한 경우 id 타입의 변수나 메소드 인자를 선언할 수 있다.
id 는 임의의 객체에 대한 포인터로 정의돼 있기 때문에 id 타입의 변수나 메소드 인자를 선언할 때 *를 포함하면 안 된다.
-
메소드 구현부의 지정 초기화 메소드에서 항상 맨 먼저 하는 것은 super 를 사용해 상위 클래스의 지정 초기화 메소드를 호출하는 것이다.
마지막으로 하는 것은 self 를 사용해 초기화에 성공한 객체 포인터를 반환하는 것이다.
-
self 는 암시적 지역 변수이다.
init 메소드의 마지막 줄에서 항상 새로 초기화한 객체를 반환한다.
일반적으로 self 는 객체가 그 자신에게 메시지를 보내기 위해 사용된다.
-
상위 클래스의 초기화 메소드를 호출한 다음에는 그 반환값을 확인해야 한다
만약 초기화 메세지가 실패하면 nil 을 반환할 것이다.
-
인스턴스 변수에 직접 접근하지 말고 접근자 메소드를 이용하라고 언급했었다.
하지만 초기화 메소드를 작성할 때는 그 규칙을 깨는 것이 좋다.
-
상위 클래스의 초기화 메소드를 호출한 다음에는 그 반환값을 확인해야 한다
만약 초기화 메세지가 실패하면 nil 을 반환할 것이다.
-
인스턴스 변수에 직접 접근하지 말고 접근자 메소드를 이용하라고 언급했었다.
하지만 초기화 메소드를 작성할 때는 그 규칙을 깨는 것이 좋다.
-
초기화 메소드 체인을 사용하면 오류의 가능성이 줄고 코드를 관리하기 쉽다.
클래스를 만든 프로그래머들은 어느 초기화 메소드가 지정 초기화 메소드인지 명확히 한다.
지정 초기화 메소드에서 초기화 코드를 하 번만 작성하면 다른 초기화 메소드에서는 단순히 기본값으로 지정 초기화 메소드를 호출하기만 하면 된다.
-
초기화 메소드의 규칙은 다음과 같다.
* 클래스는 상위 클래스로부터 모든 초기화 메소드를 상속받고 원하는 만큼 추가할 수 있다.
* 각 클래스는 하나의 초기화 메소드를 지정 초기화 메소드로 선택한다.
* 지정 초기화 메소드는 제일 먼저 상위 클래스의 지정 초기화 메소드를 호출한다.
* 다른 초기화 메소드는 클래스의 지정 초기화 메소드를 호출한다.
* 클래스가 상위 클래스와 다른 지정 초기화 메소드를 선언하면 새 지정 초기화 메소드를 호출하도록 상위 클래스의 지정 초기화 메소드를 반드시 재정의해야 한다.
-
클래스 메소드는 인스턴스에서 동작하지 않고, 어떤 인스턴스 변수에도 접근하지 않는다.
클래스 메소드는 + 기호를 사용한다.
-
인스턴스 변수가 맨 처음 오고 다음에 클래스 메소드가, 그리고 초기화 메소드와 다른 인스턴스 메소드가 그 뒤를 따라온다.
가독성이 좋은 convention 이다.
-
array 를 literal 로 정의할 때는 대괄호 앞에 @ 를 붙인다.
이는 Immutable array 를 생성한다.
-
클래스 메소드는 + 기호를 사용한다.
-
인스턴스 변수가 맨 처음 오고 다음에 클래스 메소드가, 그리고 초기화 메소드와 다른 인스턴스 메소드가 그 뒤를 따라온다.
가독성이 좋은 convention 이다.
-
array 를 literal 로 정의할 때는 대괄호 앞에 @ 를 붙인다.
이는 Immutable array 를 생성한다.
-
arc4random() 함수는 자체적으로 seed 를 하며, return 값의 범위가 rand() 보다 넓어서 사용하기 훨씬 좋은 녀석이다.
-
Objective-C 배열은 여러 타입의 객체를 포함할 수 있다.
Objective-C 객체에 대한 참조만을 저장할 수 있다.
기본형과 C 구조체는 Objective-C 배열에 추가할 수 없다.
만약 기본형이라 C 구조체를 저장하려면 NSNumber, NSValue, NSData 와 같은 Objective-C 객체로 해당 데이터를 감사 사용할 수 있다.
또한 배열에 nil 을 추가할 수 없다.
만약 배열에 nil 을 추가하고자 한다면 반드시 NSNull 을 사용해야 한다. ( [NSNull null] 로 생성 )
-
Objective-C 배열은 여러 타입의 객체를 포함할 수 있다.
Objective-C 객체에 대한 참조만을 저장할 수 있다.
기본형과 C 구조체는 Objective-C 배열에 추가할 수 없다.
만약 기본형이라 C 구조체를 저장하려면 NSNumber, NSValue, NSData 와 같은 Objective-C 객체로 해당 데이터를 감사 사용할 수 있다.
또한 배열에 nil 을 추가할 수 없다.
만약 배열에 nil 을 추가하고자 한다면 반드시 NSNull 을 사용해야 한다. ( [NSNull null] 로 생성 )
-
자신의 타입의 객체를 반환하는 클래스 메소드를 컨비니언스 메소드(convenience method) 라고 한다.
컨비니언스 메소드에서 self 를 이용해서 객체를 생성해야 한다.
그래야 하위 클래스에서 사용할 때 문제가 없다.
-
[index] 를 사용한 배열 접근은
objectAtIndex: 메시지를 보낸 것과 동일하다.
-
모든 객체는 isa 라는 인스턴스 변수를 가진다.
객체가 만들어지면 객체를 만든 클래스는 반환된 객체의 isa 변수를 다시 자신을 가리키도록 설정한다.
-
어떤 이유로든 응답하지 않는 객체에 메세지를 보내면 프로그램은 예외가 발생할 것이다.
-
프로그램이 중단되거나 크래시가 발생하면 항상 콘솔을 확인하자.
-
Objective-C 에는 네임스페이스라는 개념이 없다.
대신에 클래스 이름을 구분하기 위해 두서너 자의 접두사를 사용한다.
자신의 이름, 회사 이름, 포함될 라이브러리 등과 관련된 것을 접두사로 사용한다.
-
세 글자의 접두사를 사용하는 것이 좋다.
애플에서 많은 두 글자 접두사를 프레임워크 클래스용으로 사용하고 있기 떄문이다.
-
-
[index] 를 사용한 배열 접근은
objectAtIndex: 메시지를 보낸 것과 동일하다.
-
모든 객체는 isa 라는 인스턴스 변수를 가진다.
객체가 만들어지면 객체를 만든 클래스는 반환된 객체의 isa 변수를 다시 자신을 가리키도록 설정한다.
-
어떤 이유로든 응답하지 않는 객체에 메세지를 보내면 프로그램은 예외가 발생할 것이다.
-
프로그램이 중단되거나 크래시가 발생하면 항상 콘솔을 확인하자.
-
Objective-C 에는 네임스페이스라는 개념이 없다.
대신에 클래스 이름을 구분하기 위해 두서너 자의 접두사를 사용한다.
자신의 이름, 회사 이름, 포함될 라이브러리 등과 관련된 것을 접두사로 사용한다.
-
세 글자의 접두사를 사용하는 것이 좋다.
애플에서 많은 두 글자 접두사를 프레임워크 클래스용으로 사용하고 있기 떄문이다.
-
예전에는 프레임워크를 위한 마스터 헤더 파일을 #import 했다.
이 마스터 헤더 파일은 프레임워크 안의 모든 헤더를 #import 한다.
이러한 접근 방법은 10여 년간 잘 동작했다.
그러나 더 많은 클래스들이 프레임워크에 추가되고 각 프로젝트에는 더 많은 프레임워크가 포함됐다.
결국 컴파일러는 동일한 표준 헤더를 계속해서 파싱하고 처리하는 데 대부분의 시간을 소비하게 됐다.
-
미리 컴파일된 헤더 파일(precompiled header file)이 모든 프로젝트에 추가됐다.
처음으로 프로젝트를 컴파일하면 그 파일에 나열된 헤더들은 한 번만 컴파일되고 그 결과는 캐시된다.
미리 컴파일된 헤더 파일(precompiled header file)이 모든 프로젝트에 추가됐다.
처음으로 프로젝트를 컴파일하면 그 파일에 나열된 헤더들은 한 번만 컴파일되고 그 결과는 캐시된다.
미리 헤더의 요약 정보를 가져 다른 모든 파일들을 더 많이 더 빨리 컴파일할 수 있게 된다.
.pch 파일이 precompiled-header file 이다.
-
-
이는 지난 10여 년 동안 잘 사용됐지만, 최근 애플은 개발자들이 .pch 파일을 효과적으로 관리하지 못한다는 사실을 깨달았다.
그래서 이를 효율적으로 사용하기 위해서 @import 가 도입되었다. ( @import Foundation; )
컴파일러에게 알아서 import 하라고 이야기 하는 것과 같다.
그래서 이를 효율적으로 사용하기 위해서 @import 가 도입되었다. ( @import Foundation; )
컴파일러에게 알아서 import 하라고 이야기 하는 것과 같다.
컴파일러는 헤더 파일의 전처리(preprocessing)와 캐싱(caching) 과정을 최적화하는 여러 선택사항을 가지고 있다.
현재는 오직 애플만이 @import 지시자를 사용해 모듈을 만들 수 있다.
현재는 오직 애플만이 @import 지시자를 사용해 모듈을 만들 수 있다.
자신이 만든 클래스나 프레임워크에서는 여전히 #import 지시자를 사용해야 한다.
반응형
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[iOS Study] 뷰와 뷰 계층구조 (0) | 2016.02.16 |
---|---|
[iOS Study] ARC 를 통한 메모리 관리 (0) | 2016.02.15 |
[iOS Study] 간단한 iOS 앱 만들기 (0) | 2016.02.12 |
[ios] How to link xib file to the view controller? ( xib 파일을 view controller 에 연결하는 방법 ) (0) | 2015.07.04 |
iOS Simulator Home 버튼이 보이지 않아요. (0) | 2015.06.30 |
댓글