내 코드는 다음과 같습니다 :
- (void)viewDidLoad {
[super viewDidLoad];
[self testGCD];
}
- (void)testGCD {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"1");
return;
});
NSLog(@"2");
}
콘솔 1및2를 인쇄했습니다.
원하는 것은 처음 1 만 인쇄하는 것입니다. 아마도
return
생각
메소드에서 반환되지 않고 대신 블록에서 반환됩니다.
이 GCD 블록의 현재 메소드에서 리턴 할 수있는 방법이 있습니까?
- 답변 # 1
- 답변 # 2
블록을 사용하여 문제를 해결하십시오.
- (void)testGCD { __block void(^codeBlock)(void) = ^{ NSLog(@"2"); }; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ codeBlock = ^{ NSLog(@"1"); }; }); codeBlock(); }
- 답변 # 3
- (void)testGCD { static dispatch_once_t onceToken; __block NSString *text = @"2"; dispatch_once(&onceToken, ^{ text = @"1"; }); NSLog(@"%@", text); }
- 답변 # 4
와이즈 비즈 statement는 현재 엔 클로징 범위에서 반환하며, 귀하의 경우에는 블록입니다. 외부 둘러싸는 범위에서 돌아올 수 없습니다.
간단한 부울 플래그를 사용하여 코드가 스레드 실행에 안전한지 확인하기 위해 직렬 디스패치 큐와 함께 코드가 처음으로 실행되었는지 여부를 확인할 수 있습니다.
같은 것 :
return
직렬 디스패치 큐를 사용하면
- (void)testGCD { static dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL); static bool firstRun = YES; dispatch_sync(queue, ^{ if (firstRun) { NSLog(@"1); firstRun = NO; } else { NSLog(@"2"); } }); }
를 동시에 업데이트 할 수 없습니다. - 답변 # 5
블록은 완전히 분리 된 방법과 같습니다. 와이즈 비즈 블록에서만 반환됩니다. 효과적으로 필요한 것 :
firstRun
귀하의 경우 간단한 자물쇠를 사용하려고 시도 할 수 있지만이 경우 얼마나 안전한지 확실하지 않습니다.
return
그러나 여전히 멀티 스레딩시 결과가 불안정 할 수 있습니다. 결과가 정확하려면 이것을 원자 적으로 실행해야 할 수도 있습니다. 잠재적 인 문제는 다음과 같습니다.
나사 A와 스레드 B가 동일한 방법을 실행하기 시작합니다.
스레드 A가 토큰을 수집하고
- (void)testGCD { static BOOL didTrigger = NO; if(didTrigger) { NSLog(@"2"); } else { didTrigger = YES; NSLog(@"1"); } }
를 잠금 해제합니다나사 B는 블록을 건너 뛰고
- (void)testGCD { static dispatch_once_t onceToken; static BOOL didInvokeOnceBlock = NO; static BOOL didPassSkippedBlock = NO; dispatch_once(&onceToken, ^{ NSLog(@"1"); didInvokeOnceBlock = YES; }); if(didInvokeOnceBlock && didPassSkippedBlock) { NSLog(@"2"); } didPassSkippedBlock = YES; }
를 잠금 해제합니다 그러나didInvokeOnceBlock
를 건너 뜁니다스레드 A가
didPassSkippedBlock
를 불러옵니다NSLog(@"2");
관련 자료
- perl - 정렬 블록에서 반환하면 "정렬에서 초기화되지 않은 값 사용"경고가 표시되지만 명시 적 반환 만 있음
- java - getClass () 메서드의 반환 값을 Class 를 확장합니까?
- wordpress - 현재 제품 속성을 기반으로 제품 목록 반환
- java - 이 메서드 내에 void 메서드가있는 경우 반환 값으로 메서드를 모의하는 방법
- java - 수정 후 메소드에서 arraylist를 반환 유형으로 지정해야합니까?
- javascript - 배열이 비어 있고 그 반대의 경우 노드에서 거짓 값 약속 메서드를 반환하는 방법
- javascript - GET 메서드에서 JSON을 반환하는 방법은 무엇입니까?
- import - os 모듈을 사용하여 Python의 현재 작업 디렉토리 바로 위에있는 디렉토리 이름을 반환합니다
- python - Dict 목록에는 반환 방법이 필요합니다
- python - index () 메서드가 None 대신 정수를 반환하도록 만드는 방법은 무엇입니까?
- list - Java의 메소드에서 다른 데이터 유형을 리턴하십시오
- rx java - 안드로이드의 Retrofit 메소드에서 Callable 반환
- android - 저 음질 오디오에서 MediaPlayer getDuration () 메소드가 -1을 반환하는 이유는 무엇입니까?
- getYesterdayDate_yyyy_MM_dd ()이 메소드는 리턴 형 javasqldate를 사용합니다
- laravel - 'dispatch'메소드가 스케줄링없이 PendingDispatch의 인스턴스화 및 리턴 만하는 이유는 무엇입니까?
- ios - Int의 글꼴을 반환하는 확장 메서드를 제공하고 싶습니다 맞습니까?
- python - try 블록의 함수에서 반환하면 모든 단점
- Java의 2D 배열 방법에서 점수 평균을 반환하는 방법은 무엇입니까?
- php - loginformauthenticator - : getuser () "메서드는 userinterface를 반환해야합니다
- Javascript의 메서드 내에서 'return'을 사용하는 경우
- ios : 컨테이너보기에 추가 할 때 ViewDidLoad가 호출되지 않음
- ios - 단일 UILabel에서 굵은 글씨체 및 굵은 글씨체가 아닌 텍스트?
- ios - loadItemForTypeIdentifier를 사용하여 이미지를로드하는 방법
- ios - UIView를 푸시 할 때 UITabBar 숨기기
- ios - 로그인을 위해 부모 UIView (50 % 투명)를 어둡게하는 방법은 무엇입니까?
- ios - Objective-C 및 Swift에서 기다리는 방법
- ios - NSUserDefaults에 이미지를 저장 하시겠습니까?
- ios - 두 가지 색상의 텍스트가있는 UILabel
- ios : libPods.a 오류
- ios - 텍스트 길이를 기준으로 UILabel 너비를 계산하는 방법은 무엇입니까?
dispatch_once
정의를 보면 그런 다음 그들이DISPATCH_EXPECT
를 사용하고 있음을 알 수 있습니다.onceToken
를 비교하기 위해 .if (onceToken != -1)
를 사용할 수도 있습니다 그러나DISPATCH_EXPECT
컴파일러에게onceToken == -1
의 확률을 알려 코드를 최적화합니다 훨씬 더 높습니다. 이를지점 예측