Objective-C ARC : 강력 vs 유지 및 취약 대 할당


367

ARC가 도입 한 속성에 대한 두 가지 새로운 메모리 관리 속성이 있습니다. strong 하고 weak.

copy분명히 완전히 다른 무언가를 제외하고 strongvs retain와 차이점이 있습니까?weak vsassign 있습니까?

내 이해에서, 여기의 유일한 차이점 은 포인터에 weak할당 된다는 것 입니다. 그렇지 않지만, 포인터를 놓으면 포인터에 메시지를 보낼 때 프로그램이 중단됩니다. 그러나을 사용하면 메시지 보내기 가 아무것도하지 않기 때문에 이런 일이 발생 하지 않습니다.nilassignweaknil

나는 사이의 차이에 대해 알고하지 않습니다 strongretain.

내가 사용하는 이유 어떤 이유가 assignretain새로운 프로젝트에, 또는 사용되지의 친절은?


12
이 ARC에 의해 도입 된 속성에 대한 세 가지의 새로운 메모리 관리 속성은 strong, weak하고 unsafe_unretained.
NJones

5
@NJones이 있습니다 등록 정보 속성 ( weakstrong)과 4 개 변수 평생 예선 ( __strong, __weak, __unsafe_unretained, __autoreleasing). 아래의 ARC 참고 사항을 참조하십시오.
Snowcrash

1
@SnowCrash assignARC로 컴파일 할 때 오류가 발생한 Xcode 버전 (개발자 미리보기 일 수 있음)이 있었습니다. 이에 대한 많은 삭제 된 답변이 있습니다. 최종 릴리스 전에 변경된 것으로 보입니다. unsafe_unretained많은 얼리 어답터가 선호하는 속성입니다. unsafe_unretained유효한 속성 임을 증명 하려면 "일부 클래스에 안전하지 않은 참조를 사용하십시오"라는 제목 아래의 "데이터 캡슐화"섹션에서 Apple의 "Objective-C로 프로그래밍"을 참조하십시오. "속성의 경우 이는 unsafe_unretained 속성을 사용한다는 의미입니다."
NJones

답변:


230

로부터 ARC 릴리스로 전환 (등록 정보 속성 섹션의 예).

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

그래서 strong같은retain 속성 선언한다.

내가 사용하는 것이 ARC 프로젝트의 strong대신에 retain, 내가 사용하는 것이 assignC 원시 속성 및 weak목표 - C 객체에 약한 참조하십시오.


11
실제로 ARC에서는 assign객체 에 사용하는 컴파일 오류 입니다. 당신은 사용해야하거나 weak또는 unsafe_unretained(분명히 안전하다) 당신이 재산을 유지하지 않으려면.
cobbal

5
assign배포 대상 4.0이있는 ARC 프로젝트에서 나에게 잘 컴파일됩니다.
Pascal

8
@Pascal : 운영 체제가 5.0 이상이 아닌 배포 대상에서는 약한 참조가 허용되지 않습니다. 따라서 이전 프로젝트의 경우 여전히 assign을 사용할 수 있지만 최신 버전으로 이동하는 경우 약한 것으로 전환해야합니다.
Mattia

1
Xcode 4 (ARC 포함)는 vs를 사용하여 NSManagedObject 하위 클래스를 생성하는 것처럼 보입니다 . 나는 그것이 무해하다고 생각하지만 일관성 이 있어야한다고 생각합니다 ... 아마도 중요하지 않습니다. stackoverflow.com/questions/7796476/…retainstrongstrong
Joe D' Andrea

3
@JeremyP 예, 귀하의 답변이 정확합니다. @Mattia에 반응했습니다. 나는 그것이 assign어떤 경우에는 여전히 유효하다고 지적했다 .
Steven Oxley

606

변수 속성 속성을 확인하기 위해 많은 기사 Stackoverflow 게시물과 데모 응용 프로그램을 읽은 후 모든 속성 정보를 하나로 묶기로 결정했습니다.

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

아래는 위에서 언급 한 모든 속성을 찾을 수있는 자세한 기사 링크입니다. 최고의 답변을 주신 모든 분들께 감사드립니다 !!

iOS의 변수 속성 또는 수정 자

1. 강한 (iOS4 = 유지)

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

예:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2. 약함 -

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

예 :

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

@synthesize myButton;

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

우리의 물건이 개이고, 개가 도망 가기를 원한다고 상상해보십시오.

강한 포인터는 강아지의 가죽 끈과 같습니다. 개가 가죽 끈에 붙어있는 한 개는 도망 가지 않습니다. 5 명이 가죽 끈을 1 마리의 개 (한 물체에 5 개의 강한 포인터)에 부착하면 5 개의 가죽 끈이 모두 분리 될 때까지 개가 도망 가지 않습니다.

반면에, 약한 포인터는 어린 아이들이 개를 가리키며 "보라! 개"라고 말하는 것과 같습니다. 개가 여전히 가죽 끈에있는 한, 작은 아이들은 여전히 ​​개를 볼 수 있으며, 여전히 개를 가리킬 것입니다. 그러나 모든 가죽 끈이 분리 되 자마자, 작은 아이가 몇 개를 가리켜도 개는 도망칩니다.

마지막 강한 포인터 (끈)가 더 이상 객체를 가리 키지 않으면 객체가 할당 해제되고 모든 약한 포인터는 0이됩니다.

우리가 약한 것을 사용할 때?

당신이 약한 것을 사용하고 싶은 유일한 시간은 당신이 유지주기를 피하고 싶을 때입니다.

3. 보유 = 강함

  • 보유, 이전 값이 릴리스되고 보유가 지정되어 새 값을 보내도록 지정합니다.
  • 할당 유지 및 이전 값 전송-해제
  • 유지하는 것은 강한 것과 같습니다.
  • apple은 당신이 작성하면 자동 변환 / 강력한 것처럼 작동한다고 말합니다.
  • "alloc"과 같은 메소드에는 암시 적 "보유"가 포함됩니다.

예:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4. 할당

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

예:

@property (nonatomic, assign) NSString *address;

@synthesize address;

5
2. "약한 참조는 가비지 수집기에 의한 수집으로부터 참조 된 개체를 보호하지 않는 참조"-목표 c에는 가비지 수집기와 같은 것이 없습니다.
bucherland

1
이 계층은 iOS에서 자동으로 관리됩니다. MVC 개념에 대해 읽어보십시오. ViewContorller가 제공 될 때 iOS 가로 드되면 화면에 뷰 계층 구조가 표시됩니다 (손실 된 뷰 생성). 다른 ViewController가 표시되면이 첫 번째 뷰 계층 구조가 할당 해제됩니다. 그러나 ViewController에 'strong'이 있으면 화면이 꺼져있을 때이보기를 할당 해제 할 수 없습니다. 기기 메모리에 심각한 영향을 미치고 앱 속도 저하의 원인이 될 수 있습니다. (물론 장치는 많은 메모리를 가지고 있으며 5-10 화면 앱에서는 괜찮을 것이지만 거대한 앱에서는 문제가 생길 것입니다)
bucherland

1
우리가 약한 것을 사용할 때? ) 상기 언급 한 바와 같이 UI를 들면 1. 2. 위임 3. 블록 개체 (weakSelf은 (피 대신 메모리 사이클 자체의 표기
bucherland

1
이 위대한 대답에는 한 가지 실수가 있습니다-강력합니다- "ARC는 당신이 그것을 할 때 자동으로 그것을 풀어줍니다", 이것은 옳지 않습니다. ARC는 포인터가 없으면 약한 오브젝트를 자동으로 해제합니다. 강력 함-유지한다는 동의어이므로 개체가 유지되며 개체를 nil로 만드는 것은 우리의 책임입니다
Ashwin G

1
@RDC, 무슨 default뜻입니까? 내가 사용 @property (nonatomic) NSString *string하면 strong? 아니면 assign? 둘 다 기본값이기 때문입니다.
Iulian Onofrei

40

비 원자 / 원자

  • 비원자는 원자보다 훨씬 빠릅니다.
  • 원자에 대해 매우 구체적인 요구 사항이없는 한 항상 원자가 아닌 것을 사용하십시오.

강한 / 약한 / 할당

  • 강하게 사용하다 개체를 유지하기 위해 - 키워드가 동의어 유지하지만, 강한 대신 사용하는 것이 가장 좋습니다
  • 약하게 사용하다객체를 유지하지 않고 포인터를 원할 경우 하십시오-유지주기 (예 : 델리게이트)를 피하는 데 유용합니다.
  • 프리미티브에 할당 을 사용하십시오 -풀 때 객체를 없애지 않는 것을 제외하고는 약한 것과 같습니다 (기본적으로 설정 됨)

(선택 과목)

  • 객체의 얕은 복사본을 만드는 데 사용하십시오.
  • 변경 불가능한 속성을 항상 복사하도록 설정하는 모범 사례-변경 가능한 버전은 변경 불가능한 속성으로 전달 될 수 있으므로 복사는 항상 변경 불가능한 객체를 처리하도록합니다.
  • 불변의 객체가 건네 받았을 경우, 그 객체는 유지됩니다.

읽기 전용

  • 속성 설정을 비활성화하려면 사용하십시오 (위반이있는 경우 코드가 컴파일되지 않도록 함)
  • 인스턴스 변수를 통해 변수를 직접 변경하거나 getter 메소드 자체에서 변수를 변경하여 getter가 전달하는 내용을 변경할 수 있습니다.

@Sakthimuthiah가 맞습니다. 답을 수정해야합니다.
Adela Toderici

@Sakthimuthiah가 잘못되었습니다 (그리고 그것을 말하는 다른 사람). 원자는 스레드로 인해 안전하지 않지만 동작으로 인해 쉽게 착각 할 수 있습니다. 읽어보십시오 : stackoverflow.com/questions/12347236/…
Chris J

39

지금까지 내가 아는 한, strong그리고 retain그들이 할 수 있도록, 동의어 정확히 같은.

그런 다음 weak은 거의 같지만 assign객체가 가리키는 할당이 해제되면 자동으로 nil로 설정됩니다.

즉, 간단히 교체 할 수 있습니다.

그러나 , 내가 겪어야 할 특별한 경우 assignweak있습니다. 이제 우리는 두 가지 속성이 있다고 가정 해 봅시다 delegateAssigndelegateWeak. 둘 다 우리의 대리인이 저장되어 있습니다. 델리게이트가 할당 해제 중이므로 -dealloc메소드도 호출됩니다.

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething];
    [delegateAssign doSomething];
}

대리인이 이미 할당 해제 프로세스에 있지만 아직 완전히 할당 해제되지 않았습니다. 문제는 weak그에 대한 언급이 이미 무효화 되었다는 것입니다 ! 속성 delegateWeak에 nil이 포함되어 있지만 delegateAssign유효한 객체가 포함되어 있습니다 (모든 속성이 이미 해제되어 무효화되었지만 여전히 유효 함).

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething]; // Does nothing, already nil.
    [delegateAssign doSomething]; // Successful call.
}

그것은 특별한 경우이지만, weak변수가 어떻게 작동하고 언제 무효화 되는지를 보여줍니다 .



20

Objective-C ARC (Automatic Reference Counting) 에 대한 Clang의 문서 는 소유권 한정자와 수정자를 명확하게 설명합니다.

소유권 한정자는 네 가지입니다.

  • __ autoreleasing
  • __ 강하다
  • __ * unsafe_unretained *
  • __

__ autoreleasing , __ strong 또는 __ weak 로 정규화 된 유형은 사소한 소유권이 없습니다 .

그런 다음 선언 된 속성에 대한 6 개의 소유권 수정자가 있습니다.

  • assign은 __ * unsafe_unretained * 소유권을 의미합니다.
  • 복사 __ 의미 강력한 소유권뿐만 아니라 세터에 복사 의미의 일반적인 동작을.
  • 유지는 __ 강력한 소유권을 의미합니다 .
  • strong은 __ 강력한 소유권을 의미합니다 .
  • * unsafe_unretained *는 __ * unsafe_unretained * 소유권을 의미합니다.
  • weak는 __ 약한 소유권을 의미합니다 .

weak를 제외 하고 이러한 수정자는 비 ARC 모드에서 사용할 수 있습니다.

의미 적으로 현명하게도 소유권 한정자는 읽기, 할당, 초기화, 파괴 및 이동 의 5 가지 관리 작업 에서 서로 다른 의미를 갖습니다. 대부분의 경우 할당 작업의 차이에만 관심이 있습니다.

할당 은 할당 연산자를 평가할 때 발생합니다. 시맨틱은 자격에 따라 다릅니다.

  • __ 강한 개체의 경우 새 포인트가 먼저 유지됩니다. 둘째로, lvalue에는 원시 시맨틱이로드됩니다. 셋째, 새로운 포인트는 프리미티브 시맨틱으로 lvalue에 저장됩니다. 마지막으로 오래된 포인트가 해제됩니다. 이것은 원자 적으로 수행되지 않습니다. 동시로드 및 저장시이를 안전하게하려면 외부 동기화를 사용해야합니다.
  • __ 약한 객체의 경우 새 포인트가 현재 할당 해제중인 객체가 아닌 경우 lvalue가 새 포인트를 가리 키도록 lvalue가 업데이트됩니다.이 경우 lvalue가 null 포인터로 업데이트됩니다. 이는 객체에 대한 다른 할당, 객체에서 읽기 및 새 포인트의 최종 릴리스와 관련하여 원자 적으로 실행해야합니다.
  • __ * unsafe_unretained * 객체의 경우 새 포인트는 기본 시맨틱을 사용하여 lvalue에 저장됩니다.
  • __ 들어 autoreleasing 목적, 새로운 pointee는 유지 오토 릴리즈 원시적 의미를 사용하여 좌변에 저장된다.

읽기, 초기화, 파기 및 이동의 다른 차이점 은 문서의 4.2 의미 를 참조하십시오 .


6

Strong 및 Weak 참조를 이해하기 위해 아래 예제를 고려하여 displayLocalVariable이라는 이름의 메소드가 있다고 가정하십시오.

 -(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
  }

위의 myName 변수의 메소드 범위는 displayLocalVariable 메소드로 제한됩니다. 일단 메소드가 완료되면 문자열 "ABC"를 보유하고있는 myName 변수가 메모리에서 할당 해제됩니다.

뷰 컨트롤러 수명주기 내내 myName 변수 값을 유지하려면 어떻게해야합니까? 이를 위해 아래와 같이 myName 변수에 대한 강력한 참조를 갖는 username이라는 이름의 속성을 만들 수 있습니다 ( self.username = myName;아래 코드 참조 ).

@interface LoginViewController ()

@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;

- (void)displayLocalVariable;

@end

@implementation LoginViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

}

-(void)viewWillAppear:(BOOL)animated
{
     [self displayLocalVariable];
}

- (void)displayLocalVariable
{
   NSString myName = @"ABC";
   NSLog(@"My name is = %@", myName);
   self.username = myName;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


@end

이제 위의 코드에서 myName이 self.username에 할당되었고 self.username이 myName에 대한 강력한 참조 (@property를 사용하여 인터페이스에서 선언 한대로)를 가지고 있음을 볼 수 있습니다 (간접적으로 "ABC"문자열에 대한 강력한 참조를 가짐). 따라서 문자열 myName은 self.username이 활성화 될 때까지 메모리에서 할당 해제되지 않습니다.

  • 약한 참조

이제 약한 참조 인 dummyName에 myName을 할당하십시오. self.dummyName = myName; Strong reference와 달리 Weak은 myName에 대한 강한 참조가있을 때까지만 myName을 유지합니다. 약한 참조를 이해하려면 아래 코드를 참조하십시오.

-(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
     self.dummyName = myName;
  }

위의 코드에는 myName에 대한 약한 참조가 있습니다 (즉, self.dummyName에 myName에 대한 약한 참조가 있음). myName에 대한 강한 참조가 없으므로 self.dummyName은 myName 값을 보유 할 수 없습니다.

이제 다시 아래 코드를 고려하십시오.

-(void)displayLocalVariable
      {
         NSString myName = @"ABC";
         NSLog(@"My name is = %@", myName);
         self.username = myName;
         self.dummyName = myName;
      } 

위의 코드에서 self.username에는 myName에 대한 강력한 참조가 있으므로, myName에 연관된 참조가 있으므로 self.dummyName은 메소드가 종료 된 후에도 myName의 값을 갖습니다.

변수에 대한 강력한 참조를 만들 때마다 유지 횟수가 1 씩 증가하고 할당 해제 유지 횟수가 0에 도달하지 않습니다.

도움이 되었기를 바랍니다.


2

강한:

  • 속성은 삭제되지 않지만 속성을 nil로 설정 한 후에 만 ​​객체가 삭제됩니다
  • 기본적으로 모든 인스턴스 변수와 로컬 변수는 강력한 포인터입니다.
  • 개체를 유지해야하는 경우에만 강력하게 사용하십시오.
  • 우리는 일반적으로 UIViewControllers (UI 항목의 부모)를 강력하게 사용합니다.
  • IOS 4 (비 ARC) KeyWord 유지
  • 강력한 키워드를 사용할 수있는 IOS 5 (ARC)

예 : @property (강하고 비 원자) ViewController * viewController;

@synthesize viewController;

약한

기본적으로 자동으로 가져오고 nil로 설정

  • 우리는 일반적으로 IBOutlets (UIViewController 's Childs)와 델리게이트에 약한 것을 사용합니다.
  • 할당과 동일, 유지 또는 해제

예 : @property (약한 비 원자) IBOutlet UIButton * myButton;

@synthesize myButton;


1

강력 함과 유지함의 차이점 :

  • iOS4에서 Strong은 유지하는 것과 같습니다.
  • 즉, 객체를 소유하고 더 이상 가리킬 때까지 힙에 보관해야합니다.
  • 당신이 유지를 작성하면 자동으로 강한처럼 작동합니다

약한 할당과 할당의 차이점 :

  • "약한"참조는 보유하지 않은 참조이며 다른 사람이 강력하게 가리키는 한 유지합니다.
  • 객체가 "할당 해제"되면 약한 포인터가 자동으로 nil로 설정됩니다.
  • "할당"속성 속성은 컴파일러에게 속성의 setter 구현을 합성하는 방법을 알려줍니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.