[objective-c] “__block”키워드는 무엇을 의미합니까?

__blockObjective-C 의 키워드는 정확히 무엇을 의미합니까? 블록 내에서 변수를 수정할 수 있다는 것을 알고 있지만 알고 싶습니다 …

  1. 컴파일러에게 정확히 무엇을 알려줍니까?
  2. 다른 일이 있습니까?
  3. 그게 다라면 왜 처음에 필요한가요?
  4. 어디서나 문서에 있습니까? (찾을 수 없습니다).


답변

컴파일러는 해당 변수로 표시된 변수가 블록 내부에서 사용될 때 특별한 방식으로 처리되어야한다고 알려줍니다. 일반적으로 블록에도 사용되는 변수 및 해당 내용은 복사되므로 이러한 변수에 대한 수정 내용은 블록 외부에 표시되지 않습니다. 로 표시되면 __block블록 내부에서 수행 한 수정 내용도 외부에서 볼 수 있습니다.

예제와 추가 정보 는 Apple 블록 프로그래밍 주제__block 스토리지 유형 을 참조하십시오 .

중요한 예는 다음과 같습니다.

extern NSInteger CounterGlobal;
static NSInteger CounterStatic;

{
    NSInteger localCounter = 42;
    __block char localCharacter;

    void (^aBlock)(void) = ^(void) {
        ++CounterGlobal;
        ++CounterStatic;
        CounterGlobal = localCounter; // localCounter fixed at block creation
        localCharacter = 'a'; // sets localCharacter in enclosing scope
    };

    ++localCounter; // unseen by the block
    localCharacter = 'b';

    aBlock(); // execute the block
    // localCharacter now 'a'
}

이 예에서, 양 localCounterlocalCharacter블록이 호출되기 전에 수정된다. 그러나 블록 내부 localCharacter에서는 __block키워드 덕분에 수정 사항 만 표시 됩니다. 반대로, 블록은 수정할 수 있으며이 localCharacter수정은 블록 외부에서 볼 수 있습니다.


답변

@bbum은 블로그 게시물 에서 깊이있는 블록을 다루고 __block 스토리지 유형을 다룹니다 .

__block은 고유 한 저장소 유형입니다.

정적, 자동 및 휘발성과 마찬가지로 __block은 스토리지 유형입니다. 변수의 스토리지를 다르게 관리하도록 컴파일러에 지시합니다.

그러나 __block 변수의 경우 블록이 유지되지 않습니다. 필요에 따라 유지 및 해제는 사용자의 책임입니다.

유스 케이스의 경우 __block인수를 유지하지 않기 때문에 유지주기를 피하기 위해 때때로 사용됩니다. 일반적인 예는 self를 사용하는 것입니다.

//Now using myself inside a block will not 
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;


답변

일반적으로 __block을 사용하지 않으면 블록은 변수를 복사 (유지)하므로 변수를 수정하더라도 블록은 이전 객체에 액세스 할 수 있습니다.

NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints @"hello"

이 두 가지 경우 __block이 필요합니다.

1. 블록 내부의 변수를 수정하고 외부에서 볼 수있게하려면 :

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    str = @"how are you";
};
theBlock();
NSLog(@"%@", str); //prints "how are you"

2. 블록을 선언 한 후 변수를 수정하고 블록에서 변경 사항을 볼 것으로 예상하는 경우 :

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints "how are you"


답변

__block 은 두 가지 방법으로 사용할 수있는 스토리지 한정자입니다.

  1. 변수가 원래 변수의 어휘 범위와 해당 범위 내에 선언 된 블록간에 공유되는 스토리지에 있음을 표시합니다. 그리고 clang은이 변수를 나타내는 구조체를 생성하고이 구조체를 값이 아닌 참조로 사용합니다.

  2. MRC에서 __block 을 사용하면 블록이 캡처하는 객체 변수를 유지하지 않아도 됩니다. 이것이 ARC에서 작동하지 않도록주의하십시오. ARC에서는 __weak을 대신 사용해야 합니다.

당신은 참조 할 수 있습니다 사과 문서 자세한 정보는.


답변

__block스코프 변수를 변경 가능하게 만드는 데 사용되는 스토리지 유형입니다.이 지정자로 변수를 선언하면 참조가 읽기 전용 사본이 아닌 블록으로 전달됩니다. 자세한 내용은 iOS의 블록 프로그래밍을 참조하십시오


답변

이것이 당신을 도울 수 있기를 바랍니다

다음과 같은 코드가 있다고 가정 해 봅시다.

{
     int stackVariable = 1;

     blockName = ^()
     {
      stackVariable++;
     }
}

블록 내의 스택 변수는 기본적으로 불변이므로 “변수를 지정할 수 없습니다”와 같은 오류가 발생합니다.

선언 앞에 __block (storage modifier)을 추가하면 블록 내부에서 변경할 수 있습니다. __block int stackVariable=1;


답변

로부터 블록 언어 사양 :

새로운 블록 유형 외에도 로컬 변수에 대한 새로운 스토리지 한정자 __block이 도입되었습니다. [testme : 블록 리터럴 내 __block 선언] __block 저장소 한정자는 기존 로컬 저장소 한정자 auto, register 및 static과 상호 배타적입니다. [testme] __block으로 한정된 변수는 할당 된 저장소에있는 것처럼 작동하며이 저장소는 상기 변수를 마지막으로 사용한 후에 자동적으로 회복된다. 구현은 스토리지가 초기에 자동이며 참조 블록의 Block_copy에 따라 할당 된 (힙) 스토리지로만 “이동”하는 최적화를 선택할 수 있습니다. 이러한 변수는 정상 변수처럼 변이 될 수 있습니다.

__block 변수가 블록 인 경우 __block 변수가 할당 된 저장소에 상주한다고 가정해야하며, 따라서 할당 된 저장소에도있는 블록을 참조한다고 가정합니다 (Block_copy 작업의 결과 임). 그럼에도 불구하고 구현에서 블록에 대한 초기 자동 스토리지를 제공하는 경우 Block_copy 또는 Block_release를 수행 할 준비가 없습니다. 이는 공유 변수를 업데이트하려는 잠재적으로 여러 스레드의 고유 경쟁 조건 및 이전 값을 폐기하고 새 값을 복사하는 것과 동기화해야하기 때문입니다. 이러한 동기화는이 언어 사양의 범위를 벗어납니다.

__block 변수가 무엇을 컴파일해야하는지에 대한 자세한 내용은 2.3 블록 구현 사양 섹션을 참조하십시오 .