티스토리 뷰
GCD is the associated technology and provides an abstraction to threading, based on so-called dispatch queues. Blocks can be enqueued on these queues, and GCD handles all scheduling for you. It creates, reuses, and destroys background threads as it sees fit, based on system resources, to process each queue. Moreover, GCD provides easy-to-use solutions to common programming tasks, such as thread-safe single-code execution and running the tasks in parallel, based on available system resources.
Item 37: Understand Blocks
int additional = 5;
int (^addBlock)(int a, int b) = ^(int a, int b){
return a + b + additional;
};
int add = addBlock(2, 5); //< add = 12
By default, any variable captured by a block cannot be modified by the block. In the example, if the variable called additional were changed within the block, the compiler would issue an error.
void (^block)();
if ( /* some condition */ ) {
block = ^{
NSLog(@"Block A");
};
} else {
block = ^{
NSLog(@"Block B");
};
}
block();
The two blocks that are defined within the if and else statements are allocated within stack memory. When it allocates stack memory for each block, the compiler is free to overwrite this memory at the end of the scope in which that memory was allocated. So each block is guaranteed to be valid only within its respective if-statement section. The code would compile without error but at runtime may or may not function correctly. If it didn’t decide to produce code that overwrote the chosen block, the code would run without error, but if it did, a crash would certainly occur.
To solve this problem, blocks can be copied by sending the block the copy message. In doing so, the block is copied from the stack to the heap.
void (^block)();
if ( /* some condition */ ) {
block = [^{
NSLog(@"Block A");
} copy];
} else {
block = [^{
NSLog(@"Block B");
} copy];
}
block();
This code is now safe.
Item 38: Create typedefs for Common Block Types
typedef int(^EOCSomeBlock)(BOOL flag, int value);
Just as the variable name of a block is in the middle prefixed by a caret, so too is the new type name.
EOCSomeBlock block = ^(BOOL flag, int value){
// Implementation
};
typedef void(^ACAccountStoreSaveCompletionHandler)
(BOOL success, NSError *error);
typedef void(^ACAccountStoreRequestAccessCompletionHandler)
(BOOL granted, NSError *error);
These block type definitions have the same signature but are used in distinct places. The name of the type and the name of the parameters in the signature make it easy for the developer to understand how the type is to be used. The developer could have defined a single type definition, perhaps called ACAccountStoreBooleanCompletionHandler, used in place of both of these. However, that would lose the clarity of how the block and parameters are used.
Item 39: Use Handler Blocks to Reduce Code Separation
EOCNetworkFetcher *fetcher =
[[EOCNetworkFetcher alloc] initWithURL:url];
[fetcher startWithCompletionHander:
^(NSData *data, NSError *error){
if (error) {
// Handle failure
} else {
// Handle success
}
}];
This approach requires the error variable to be checked and puts all the logic in one place. The downside is that because all the logic is in one place, the block can become long and complicated. However, the upside of the single-block approach is that it is much more flexible. It’s possible to pass an error, as well as data, for example. Consider that perhaps the network was able to download half the data and then an error occurred. Maybe in that case, you would pass back the data and the associated error. The completion handler can then determine the problem, handle it as appropriate, and may be able to do something useful with the part of the data that was successfully downloaded
Item 40: Avoid Retain Cycles Introduced by Blocks Referencing the Object Owning Them
call back block = completion handler
Item 41: Prefer Dispatch Queues to Locks for Synchronization
Item 42: Prefer GCD to performSelector and Friends
- (id)performSelector:(SEL)selector
This is equivalent to calling the selector directly. So the following two lines of code are equivalent:
[object performSelector:@selector(selectorName)];
[object selectorName];
It might seem as though this is redundant. It would be if this were the only way the method could be used. However, its real power comes from the fact that the selector can be decided at runtime. Like:
SEL selector;
if ( /* some condition */ ) {
selector = @selector(foo);
} else if ( /* some other condition */ ) {
selector = @selector(bar);
} else {
selector = @selector(baz);
}
[object performSelector:selector];
However, the result might be a memory leak.
For example, to perform a task after a delay, you should prefer the latter to the former:
// Using performSelector:withObject:afterDelay:
[self performSelector:@selector(doSomething)
withObject:nil
afterDelay:5.0];
// Using dispatch_after
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^(void){
[self doSomething];
});

The performSelector family of methods is potentially dangerous with respect to memory management. If it has no way of determining what selector is going to be performed, the ARC compiler cannot insert the appropriate memory-management calls.
The family of methods is very limited with respect to the return type and the number of parameters that can be sent to the method.
The methods that allow performing a selector on a different thread are better replaced with certain Grand Central Dispatch (GCD) calls using blocks.
Item 43: Know When to Use GCD and When to Use Operation Queues
- Cancelling operations
- Operation dependencies
- Key-Value Observing of operation properties
- Operation priorities
- Reuse of operations
Item 44: Use Dispatch Groups to Take Advantage of Platform Scaling
Item 45: Use dispatch_once for Thread-Safe Single-Time Code Excution
Item 46: Avoid dispatch_get_current_queue
cf. UI work in both Mac OS X and iOS needs to be performed on the main thread, which equates to the main queue in GCD.
The dispatch_get_current_queue function does not in general perform how you would expect. It has been deprecated and should now be used only for debugging.
https://www.oreilly.com/library/view/effective-objective-c-20/9780133386950/
Effective Objective-C 2.0: 52 Specific Ways to Improve Your iOS and OS X Programs
Write Truly Great iOS and OS X Code with Objective-C 2.0! Effective Objective-C 2.0 will help you harness all of Objective-C’s expressive power to write OS X or iOS code … - Selection from Effective Objective-C 2.0: 52 Specific Ways to Improve Your iOS
www.oreilly.com
이 책으로 공부 중이고, 기억하면 좋을 것 같은 부분을 발췌 + 공부 + 정리합니다.
'Objective-C 2.0' 카테고리의 다른 글
7. The System Frameworks (0) | 2023.01.03 |
---|---|
5. Memory Management (0) | 2022.05.10 |
4. Protocols and Categories (0) | 2022.03.04 |
3. Interface and API Design (0) | 2022.01.25 |
2. Objects, Messaging, and the Runtime (0) | 2022.01.19 |
- Total
- Today
- Yesterday
- 전화걸기연결
- 액션바
- 인플레이터
- allcases
- 스낵바설정
- prepareforreuse
- Objective-C
- 제스처디텍터
- 터치리스너
- 뷰페이저
- 상태드로어블
- 데이터
- 프래그먼트
- 부가데이터
- 어댑터
- 카카오톡열기
- CaseIterable
- objc
- 다이얼연결
- 전화연결하기
- 비트맵버튼
- 알림대화상자
- 쉐이프드로어블
- ios
- subscript
- swift
- 표현패턴
- 프래그먼트매니저
- 안드로이드
- 페이저타이틀스트립
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |