@property Objective-C에서 비 원자 유지, 할당, 복사


214

Objective-C를 처음 접하는 사람이 @property 지시문을 따르는 보유, 할당, 복사 및 누락 된 다른 사람에 대한 개요를 알려줄 수 있습니까? 그들은 무엇을하고 있으며 왜 서로를 사용하고 싶습니까?


1
애플의 이름은 "속성"또는 "속성"입니다.
nevan king

답변:


273

MrMage가 링크 한 기사가 더 이상 작동하지 않습니다. 그래서 Objective-C에서 (매우) 단시간 코딩으로 배운 내용은 다음과 같습니다.

비 원자 대 원자- "원자"가 기본값입니다. 항상 "비 원자"를 사용하십시오. 나는 왜 그런지 모르겠지만 내가 읽은 책에는 "원자"를 사용하는 "드물게 이유"가 있다고 말했다. (BTW : 내가 읽은 책은 BNR "iOS Programming"책입니다.)

readwrite vs. readonly- "readwrite"가 기본값입니다. @synthesize하면 getter와 setter가 모두 생성됩니다. "읽기 전용"을 사용하면 setter가 생성되지 않습니다. 객체의 인스턴스화 후에 절대 변경하고 싶지 않은 값으로 사용하십시오.

유지 대 복사 대 할당

  • "할당"이 기본값입니다. @synthesize에 의해 생성 된 setter에서 값은 단순히 속성에 할당됩니다. 나는 포인터가 아닌 속성에 "할당"을 사용해야한다는 것을 이해하고 있습니다.
  • 속성이 객체에 대한 포인터 인 경우 "보존"이 필요합니다. @synthesize에 의해 생성 된 setter는 객체를 유지합니다 (일명 유지 횟수 추가). 작업이 끝나면 개체를 해제해야합니다.
  • 개체가 변경 가능한 경우 "복사"가 필요합니다. 이 시점에서 객체의 값이 필요하고 해당 값이 객체의 다른 소유자가 변경 한 내용을 반영하지 않게하려면이 옵션을 사용하십시오. 사본을 보유하고 있으므로 오브젝트를 완료하면 오브젝트를 해제해야합니다.

@Blamdarot-ARC와 함께 배포해야합니까
Dejell

10
@Odelya-아니요. ARC를 사용하는 동안 릴리스하면 컴파일러 오류가 발생합니다.
Blamdarot 2014

52
"항상 비 원자 사용"은 좋지 않은 조언입니다. 비원자를 사용할 때 무엇을 포기하고 있는지 알아야합니다.
Jesse Rusak

7
동의했다. 특히, 많은 사람들은 비 원자 값이 게터에 의해 자동 릴리스되지 않는다는 것을 알지 못하는 것 같습니다. 비 원자는 종종 적합하지만,화물 컬트 프로그래밍은 거의 없습니다.
Catfish_Man

9
기본값 atomic을 유지하도록 조언하는 것은 조언하는 것만 큼 좋지 않습니다 nonatomic. 둘 중 어느 것도 "올바른"선택이 아니므로 언어 ​​설계자들은 두 가지 솔루션 중 더 안전한 것을 선택했습니다. 실제로 nonatomic매우 비싼 스레드 잠금을 생략하므로 일반적으로 더 나은 선택입니다. 사용하는 유일한 이유 atomic는 속성이 여러 스레드에서 설정되어있는 경우 (이 경우 생략하면 초과 릴리스 또는 누수가 발생할 수 있음)입니다.
Adam Kaplan

295

@property의 속성에 대해 알기 전에 @property의 사용법을 알아야합니다.

  • @property 는 클래스가 캡슐화 할 정보를 정의하는 방법을 제공합니다. @property를 사용하여 객체 / 변수를 선언 하면 해당 객체 / 변수는 해당 클래스를 가져 오는 다른 클래스에서 액세스 할 수 있습니다.

  • 헤더 파일에서 @property 를 사용하여 객체를 선언 하면 구현 파일에서 @synthesize 를 사용하여 객체 를 합성해야 합니다. 이것은 객체 KVC를 준수 합니다. 기본적으로 컴파일러는 이 객체에 대한 접근 자 메서드 를 합성 합니다.

  • 접근 자 메소드는 setter 및 getter입니다.

예 : .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.미디엄

@implementation XYZClass
@synthesize name;
@end

이제 컴파일러는 name에 대한 접근 자 메서드를 합성 합니다.

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • @property 의 속성 목록

    원자, 비 원자, 유지, 복사, 읽기 전용, 읽기 / 쓰기, 할당, 강함, getter = method, setter = method, unsafe_unretained

  • 원자가 기본 동작입니다. 객체가 원자로 선언되면 스레드로부터 안전 해집니다. 스레드 안전은 한 번에 해당 클래스의 특정 인스턴스에서 하나의 스레드 만 해당 개체를 제어 할 수 있음을 의미합니다.

스레드가 getter 메소드를 수행중인 경우 다른 스레드가 해당 오브젝트에서 setter 메소드를 수행 할 수 없습니다. 느립니다.

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • 비원 자는 스레드 안전하지 않습니다. nonatomic 속성 속성을 사용하여 합성 된 접근자가 단순히 값을 직접 설정하거나 반환하도록 지정할 수 있습니다. 동일한 값이 다른 스레드에서 동시에 액세스 될 경우 어떤 일이 발생하는지에 대한 보장은 없습니다.

이러한 이유로 원자 이외의 특성에 액세스하는 것이 더 빠릅니다.

@property (nonatomic)NSString *name;   
  • 속성이 객체에 대한 포인터 인 경우 유지 가 필요합니다.

setter 메소드는 오브젝트의 보유 횟수를 증가시켜 자동 릴리스 풀에서 메모리를 차지합니다.

@property (retain)NSString *name;
  • copy copy 를 사용하면 retain을 사용할 수 없습니다. 클래스의 사본 인스턴스를 사용하면 자체 사본이 포함됩니다.

변경 가능한 문자열이 설정되고 이후에 변경 되더라도 인스턴스는 설정 당시의 값을 캡처합니다. setter 및 getter 메소드는 합성되지 않습니다.

@property (copy) NSString *name;

지금,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

이름 은 영향을받지 않습니다.

  • readonly setter 메서드를 통해 속성을 변경하지 않으려면 속성을 읽기 전용으로 선언 할 수 있습니다.

컴파일러는 getter를 생성하지만 setter는 생성하지 않습니다.

@property (readonly) NSString *name;
  • readwrite 가 기본 동작입니다. readwrite 속성을 명시 적으로 지정할 필요는 없습니다.

읽기 전용과 반대입니다.

@property (readwrite) NSString *name;
  • assign 은 값을 복사 또는 유지하지 않고 인스턴스 변수에 직접 할당하는 setter를 생성합니다. 이것은 NSInteger 및 CGFloat와 같은 기본 유형 또는 대리자와 같이 직접 소유하지 않은 객체에 가장 적합합니다.

가비지 수집이 활성화 된 경우 유지 및 할당은 기본적으로 호환됩니다.

@property (assign) NSInteger year;
  • strong 은 보유를 대체합니다.

ARC와 함께 제공됩니다.

@property (nonatomic, strong) AVPlayer *player; 
  • getter = method getter 메소드 에 다른 이름을 사용하려는 경우 속성에 속성을 추가하여 사용자 정의 이름을 지정할 수 있습니다.

부울 속성 (YES 또는 NO 값이있는 속성)의 경우 getter 메서드가 "is"라는 단어로 시작하는 것이 일반적입니다.

@property (getter=isFinished) BOOL finished;
  • setter = method setter 메소드 에 다른 이름을 사용하려는 경우 속성에 속성을 추가하여 사용자 정의 이름을 지정할 수 있습니다.

메소드는 콜론으로 끝나야합니다.

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Cocoa 및 Cocoa Touch에는 아직 약한 참조를 지원하지 않는 몇 가지 클래스가 있습니다. 즉, 약한 속성이나 약한 로컬 변수를 선언하여 추적 할 수 없습니다. 이러한 클래스에는 NSTextView, NSFont 및 NSColorSpace 등이 포함됩니다. 이러한 클래스 중 하나에 대한 약한 참조를 사용해야하는 경우 안전하지 않은 참조를 사용해야합니다.

안전하지 않은 참조는 관련 개체를 유지하지 않는다는 점에서 약한 참조와 비슷하지만 대상 개체의 할당이 해제되면 nil 로 설정되지 않습니다 .

@property (unsafe_unretained) NSObject *unsafeProperty;

여러 속성을 지정해야하는 경우 다음과 같이 속성을 쉼표로 구분 된 목록으로 포함하십시오.

@property (readonly, getter=isFinished) BOOL finished;

또한 weak는 개체에 대한 참조에 대한 참조 카운트가 없지만 전혀 참조되거나 전혀 참조되지 않음을 의미합니다. "네, 저를 참조한 것"과 "9 개의 저의 참조가 있습니다"와 같은 종류 (강한 것 같습니다).
Alex Zavatone

6
가비지 수집은 Mac OS X에서 더 이상 사용되지 않으며 Apple 설명서 에 따라 iOS에는 존재하지 않으므로 가비지 수집과 관련된 답변은 무시하십시오 .
Basil Bourque

4
"참고 : 속성 원자 성은 객체의 스레드 안전성과 동의어가 아닙니다." -에서 developer.apple.com/library/mac/documentation/Cocoa/Conceptual/...
jk7

1
" @property헤더 파일을 사용하여 오브젝트를 선언 하면 구현 파일을 사용하여 오브젝트 합성해야 @synthesize합니다." 항상 그런 것은 아닙니다. 예를 들어 "기본적으로 readwrite속성은 인스턴스 변수에 의해 지원되며 컴파일러에서 자동으로 다시 합성합니다." 에서 문서 .
Franklin Yu

4
@liza 이것은 훌륭한 답변입니다. 이것이 왜 받아 들여지지 않는가? 현재 허용되는 답변보다 훨씬 더 많은 지식을 제공합니다. 때때로 StackOverflow를 이해하지 못합니까?
찰스 로버트슨

149

많은 기사를 읽은 후 모든 속성 정보를 하나로 묶기로 결정했습니다.

  1. 원자 // 기본
  2. 비 원자
  3. strong = 보유 // 기본
  4. 약한 = unsafe_unretained
  5. 유지
  6. // 디폴트 할당
  7. unsafe_unretained
  8. 읽기 전용
  9. readwrite // 기본

다음은 이러한 속성을 찾을 수있는 자세한 기사에 대한 링크입니다.

최고의 답변을 주신 모든 분들께 감사드립니다 !!

iOS의 변수 속성 또는 수정 자

다음은 기사의 샘플 설명입니다.

  1. atomic -Atomic은 하나의 스레드 만 변수 (정적 유형)에 액세스 함을 의미합니다. 원자는 스레드 안전합니다. -하지만 성능이 느립니다-원자가 기본 동작입니다-가비지 수집 환경에서 (예 : 유지 / 릴리스 / 자동 릴리스를 사용하는 경우) 원자 접근자는 다른 스레드가 올바른 설정 / 가져 오기를 방해하지 않도록 잠금을 사용합니다. 가치의. -실제로는 키워드가 아닙니다.

예 :

@property (retain) NSString *name;

@synthesize name;
  1. nonatomic -Nonatomic은 다중 스레드가 변수 (동적 유형)에 액세스 함을 의미합니다. -Nonatomic은 안전하지 않습니다. -하지만 성능이 빠릅니다. -Nonatomic은 기본 동작이 아니므로 속성 속성에 비 원자 키워드를 추가해야합니다. -두 개의 다른 프로세스 (스레드)가 동일한 변수에 동시에 액세스 할 때 예기치 않은 동작이 발생할 수 있습니다.

예:

@property (nonatomic, retain) NSString *name;

@synthesize name;

설명:

"name"이라는 원자 문자열 특성이 있고 스레드 A에서 [self setName : @ "A"]를 호출하는 경우 스레드 B에서 [self setName : @ "B"]를 호출하고 다음에서 [self name]을 호출하십시오. 스레드 C의 경우 다른 스레드의 모든 작업이 순차적으로 수행되므로 한 스레드가 setter 또는 getter를 실행하면 다른 스레드가 대기합니다. 이로 인해 "name"속성이 읽기 / 쓰기에 안전하지만 다른 스레드 D가 [name release]을 (를) 동시에 호출하면 여기에 관련된 setter / getter 호출이 없기 때문에이 작업으로 인해 충돌이 발생할 수 있습니다. 이는 다른 스레드가 동시에 모든 유형의 메시지를 개체에 보낼 수 있으므로 개체가 읽기 / 쓰기 안전 (ATOMIC)이지만 스레드 안전하지 않음을 의미합니다. 개발자는 그러한 물체에 대해 스레드 안전을 보장해야합니다.

"name"속성이 원자가 아닌 경우 위의 예-A, B, C 및 D에있는 모든 스레드가 동시에 실행되어 예기치 않은 결과가 생성됩니다. 원자의 경우 A, B 또는 C 중 하나가 먼저 실행되지만 D는 여전히 병렬로 실행될 수 있습니다.

  1. strong (iOS4 = retain)- "더 이상 가리 키지 않을 때까지 힙에 보관하십시오"-다시 말해서 "소유자입니다. 유지와 동일하게 조준하기 전에이를 해제 할 수 없습니다"- 개체를 유지해야하는 경우에만 강력하게 사용하십시오. -기본적으로 모든 인스턴스 변수와 로컬 변수는 강력한 포인터입니다. -우리는 일반적으로 UIViewControllers (UI 항목의 부모)에 강력 함을 사용합니다 -strong은 ARC와 함께 사용되며 기본적으로 객체의 보유 수에 대해 걱정할 필요가 없으므로 도움이됩니다. ARC를 사용하면 ARC가 자동으로이를 해제합니다. strong 키워드를 사용하면 객체를 소유하고 있음을 의미합니다.

예:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. weak (iOS4 = unsafe_unretained)- "다른 사람이 강력하게 지적하는 한 이것을 유지하십시오"– 할당, 유지 또는 해제와 같은 것- "약한"참조는 유지하지 않는 참조입니다. -우리는 일반적으로 IBOutlets (UIViewController의 Childs)에 약한 것을 사용합니다. 이것은 자식 개체가 부모 개체가있는 한 존재해야하기 때문에 작동합니다. -약한 참조는 가비지 수집기에서 수집 된 개체로부터 참조 된 개체를 보호하지 않는 참조입니다. -약한 것은 기본적으로 유지되지 않은 속성입니다. 객체가 할당 해제 될 때를 제외하고 약한 포인터는 자동으로 nil로 설정됩니다.

예 :

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

BJ 호머 덕분에 강력하고 약한 설명 :

우리의 물건이 개이고, 개가 도망 치고 싶다고 상상해보십시오. 강한 포인터는 강아지의 가죽 끈과 같습니다. 가죽 끈이 개에 붙어있는 한 개는 도망 가지 않습니다. 5 명이 가죽 끈을 1 마리의 개 (한 물체에 5 개의 강한 포인터)에 부착하면 5 개의 가죽 끈이 모두 분리 될 때까지 개가 도망 가지 않습니다. 반면에, 약한 포인터는 어린 아이들이 개를 가리키며 "보라! 개"라고 말하는 것과 같습니다. 개가 여전히 가죽 끈에있는 한, 작은 아이들은 여전히 ​​개를 볼 수 있으며, 여전히 개를 가리킬 것입니다. 그러나 모든 가죽 끈이 분리 되 자마자, 작은 아이가 몇 개를 가리켜도 개는 도망칩니다. 마지막 강한 포인터 (끈)가 더 이상 객체를 가리 키지 않으면 객체가 할당 해제되고 모든 약한 포인터는 0이됩니다. 우리가 약한 것을 사용할 때? 당신이 약한 것을 사용하고 싶은 유일한 시간은 당신이 유지주기를 피하고 싶을 때입니다.

  1. retain = strong-이 유지되고 이전 값이 해제되고 할당됩니다 -retain 새 값을 보내도록 지정합니다.-지정시 유지하고 이전 값을 보냅니다. -release -retain은 strong과 같습니다. -apple은 작성하면 작성하면 자동으로 변환 / 강하게 작동합니다. "alloc"과 같은 방법에는 암시 적 "보유"가 포함됩니다.

예:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign -assign이 기본값이며 단순히 변수 할당을 수행합니다. -assign은 컴파일러에게 속성의 setter 구현을 합성하는 방법을 알려주는 속성 특성입니다.-C 프리미티브 속성에 assign을 사용하고 Objective-C 객체에 대한 약한 참조에는 약합니다.

예:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. unsafe_unretained

    -unsafe_unretained는 보유 / 릴리스 호출을 삽입하는 방법을 ARC에 알려주는 소유권 한정자입니다. -unsafe_unretained는 assign의 ARC 버전입니다.

예:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. 객체가 변경 가능한 경우 -copy가 필요합니다. -copy는 할당시 새 값을 보내도록 지정하고 이전 값을 보내면 해제됩니다. -copy is retain은 비가 비지 수집 환경에서 명시 적으로 해제 (예 : 할당 해제)해야하는 객체를 반환합니다. -복사를 사용하는 경우 여전히 할당을 해제해야합니다. -현재 객체의 값이 필요하고 객체의 다른 소유자가 변경 한 값을 반영하지 않으려면이 값을 사용하십시오. 사본을 보유하고 있으므로 오브젝트를 완료하면 오브젝트를 해제해야합니다.

예:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;

2
나는 아크 후에는 더 이상 사용되지 않는다고 생각합니다.
mert

1
전체 목록에는 두 가지 옵션 항목 인 setter 및 getter가 누락되어 있으며이 옵션에는 인수가 필요한 유일한 옵션이기도합니다.
Scott Chu

개체 유형의 경우 기본값은 strong 또는 retain입니다. 기본 유형에는 사용할 수 없습니다.
Saleh Enam Shohag

9

한 번에 하나의 스레드 만 원자 속성에 액세스 할 수 있습니다. 그것은는 스레드 안전합니다 . 기본값은 atomic입니다. 키워드 atomic 이 없습니다.

비원 자란 다중 스레드가 항목에 액세스 할 수 있음을 의미합니다. 스레드 안전하지 않은

따라서 atomic을 사용하는 동안 매우 조심해야합니다.


3
"참고 : 속성 원자 성은 객체의 스레드 안전성과 동의어가 아닙니다." 에서 developer.apple.com/library/mac/documentation/Cocoa/Conceptual/...
jk7

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.