Effective objective-c Chapter 5,6,7
Chapter 5 Memory Management
- Understand reference counting
- Reference counting is the foundation of Objective-C memory management, including ARC. Understanding the reference counting mechanism will help you better use ARC
- The basic principle of reference counting is that each object has a count of how many objects it currently wants to live, and when that count reaches zero, the object is released
- The method of checking reference counts is called
retainCount
But it is not actually recommended to debug code using this method - If object A needs object B to survive, then A needs to call B’s
retain
Method, if object A no longer needs object B to live, then object B’srelease
Methods orautorelease
methods - call
release
The object is not freed, depending on whether the reference count is 0 - All objects are eventually referenced indirectly or directly by a root object, as macOS applications are
NSApplication
Object, iOS isUIApplication
Object, both of which are singletons created when the application is started - The object’s
alloc
Method returns an object held by the caller -
autorelease
The object reference count is not reduced immediately, but rather at the next Event Loop to delay the release of the object -
autorelease
Usually used when a function returns an object to ensure that the object crosses the boundary of the function call
-
Tips 30 simplifies reference counting with ARC
- ARC simply automatically adds memory-management-related code to the code
- Under ARC, the call is not allowed
retain
.release
.autorelease
.dealloc
- When ARC calls these methods, it calls the underlying C language version directly, not through the messaging mechanism, to improve performance
-
alloc
.new
.copy
.mutableCopy
Name a method at the beginning that returns an object owned by the caller - ARC automatically optimizes memory management code to reduce unnecessary memory management operations
- ARC automatically solves most of our memory management problems, so there are no special requirements, we recommend using ARC
- Variable memory management semantic modifier
-
__strong
: Default, strong reference, which indicates that the value needs to be kept -
__weak
: weak reference, which means that the value is not retained and will be retrieved when the system retrieves the value of the variable if the object is reclaimednil
-
__unsafe_unretained
: unsafe reference, does not retain this value, the system does not clear the value of the variable when the object is reclaimed -
__autoreleasing
: used when passing an object “by reference” to a method, meaning that the value is automatically released when the method returns
-
- Does ARC do it by inserting the corresponding memory management code into our code at compile time and only using Objective-C code, objects created by CoreFoundation, or does it require manual memory management
-
Tips 31 releases only references in the dealloc method and unlistens
- Objects are executed when they are reclaimed by the system
dealloc
methods -
dealloc
Things to do in the method:- Releases the reference that the object owns, holds the object
- Clear observer
- Clean up the notice
- If you are not using ARC, you need to call
[super dealloc]
methods
-
dealloc
Things not to do in a method:- Free expensive or scarce resources within the system (file descriptors, sockets, large amounts of memory, etc.) because
dealloc
Method is not called at a specific time, and objects that use such resources generally need to be provided with similar namesopen
和close
To handle the actions of requesting and releasing resources - Executing asynchronous Tasks
- Free expensive or scarce resources within the system (file descriptors, sockets, large amounts of memory, etc.) because
- Objects are executed when they are reclaimed by the system
-
Tips 32 Be aware of memory management issues when using exceptions
- C++ and Objective-C exceptions are mutually compatible and can be thrown and caught
- In cases where ARC is not used, exceptions can be used to handle errors
- In the case of ARC, exceptions cannot be used to handle errors by default
- through
-fobjc-arc-exceptions
Flags can open ARC exception handling code, but can affect runtime performance and increase application size - In general, exceptions should be thrown only if the application must terminate directly
-
Tips 33 Use weak references to avoid circular references
- Circular references occur in the simplest case where two objects hold each other, and in the more complex case where the reference relationship between objects is closed
- Circular references can cause memory leaks
- Use in non-ARC situations
assign
orunsafe_unretained
To modify the weak reference property - ARC in case of use
weak
To modify the properties of weak references becauseweak
Property is automatically set to nil after the object is freed
-
Tips 34 Use the @AutoRelease code block to reduce memory spikes
- Automatically created threads (the main thread or threads in the GCD) have auto-release pools by default, each time the “event loop” is executed, so in general there is no need to worry about auto-release pool creation, and pages do not need to create one themselves
@autorelease
块 - Reasonable use
autorelease
You can reduce your application’s memory spikes, for example when creating a large number of objects in a loop
- Automatically created threads (the main thread or threads in the GCD) have auto-release pools by default, each time the “event loop” is executed, so in general there is no need to worry about auto-release pool creation, and pages do not need to create one themselves
-
Tips 35 Debug memory management issues using Xcode’s “Zombie Object”
- Zombie objects can respond to all messages by winning a message that contains the message content and the recipient, and then terminating the application
- Zombie objects are used to debug whether code will use an object that has been destroyed
-
Tips 36 Do not use retainCount
-
retainCount
There is no help in reflecting how many object references the caller has, or in debugging memory management -
retainCount
An error will compile in the ARC environment
-
Chapter 6 Block & GCD
Blocks and CDS are at the heart of Apple’s multithreaded programming. Blocks are “lexical closures” that can be used in C, C++, and Objective-C code. With blocks, developers can pass code around like objects and run it in different contexts. And the block can access all the variables in its scope.
The GCD abstracts threads into a “dispatch queue,” where developers put blocks into a queue and the GCD handles all scheduling.
- Understand “Blocks”
- Block by
^
To define the - A defined block can be used like a function or passed like a variable
- A block can capture all variables in its declared scope
- Block capture variables must pass increment
__block
Modifier can be modified - The block holds the captured object type variable
- Blocks defined in class instance methods can also be used
self
Variable, the ability to modify instance variables without adding them at declaration time_block
, modify instance variables and use them directly within the blockself
To access a variable is equivalent, but if you need to access an instance variable through a property, specifyself
To use properties - Block the use of
self
This can lead to circular references - Blocks can be allocated on the stack or heap, or they can be global, and blocks allocated on the stack can be copied to the heap, so that they have reference counting just like normal Objective-C objects
- Block by
- Tips 38 is created for commonly used block types
typedef
- use
typedef
Define block types for easy use - Multiple type aliases can be defined for the same block signature, and only the type to be changed needs to be refactored during refactoring
- use
- Tips 39 Use a Handle block to reduce code fragmentation
- When objects are created, handle blocks are used to declare related business logic together to reduce code fragmentation
- Tips 40 Using a block to refer to its owning object is to avoid circular references
- Circular references need to be considered when using blocks
- When designing the API, you need to find a mechanism to break the circular reference, not let the client code handle it
- Use MORE GCDS and less synchronous locks
- use
@synchronized
orNSLock
Inefficient and cumbersome to handle in the face of deadlocks - Using the Serial synchronization queue ensures that the code executes sequentially, but not synchronously
- Barrier blocks are used to ensure data synchronization
- Using GCD is more efficient than synchronizing locks
- use
- Use GCD more, use it less
performSelector
Series method-
performSelector
The methods pass in parameters and return value types are limited, and in some cases ARC cannot automatically add memory free operations, resulting in memory leaks and warnings at compile time-Warc-performSelector-leaks
- The best way to do this is to encapsulate tasks in blocks and then execute them using GCD
-
- Decide when to Use GCD and when to Use IT
NSOperationQueue
- When you need to use the Objective-C API purely
- When a task needs to be cancelled
- When there are dependencies between operations
- When you need to use KVO to observe performance
- An operation priority needs to be specified
- When you need to reuse
- Tips 44 Perform tasks based on system resource status through the Dispatch Group mechanism
- A series of tasks can be grouped into a Dispatch group, and developers are notified when the set of tasks is complete
- GCD schedules tasks in a Dispatch group based on system resources
- Tips to use 45
diapatch_once
To execute thread-safe code that only needs to be run once- Tags should be declared in the static or global scope
- Singletons can be implemented
- Do not use Tips 46
dispatch_get_current_queue
- This can cause a deadlock
- Function behavior is unpredictable
Chapter 7 System Framework
- Be familiar with the system framework
- At the heart of the system framework are Foundation and CoreFoundation
- Audio and video, database and network can all be handled by the system framework
- C is a great language for good Objective-C developers
- Tip 48 uses block enumerations more than for loops
- Using “block enumeration” itself allows concurrent traversal operations to be performed via GCD
- If you know what objects are in the collection, should you change the block signature to indicate the object type
- Tips 49 Using Toll-free-bridging for Collections with custom memory management semantics
- Seamlessly bridge back and forth between Objective-C objects in Foundation and C structures in CoreFoundation
-
__bridge
Tell ARC how to handle objective-C objects involved in the transformation - When you create a collection at the CoreFoundation level, you can specify a number of callback functions that indicate how the collection should handle its elements, and then you can use seamless bridging techniques, Convert it to an Objective-C collection with special memory management semantics
- Tips 50 used when building caches
NSCache
Rather thanNSDictionary
-
NSCache
Provides auto-delete functionality, does not copy keys, and is thread-safe - collocation
NSPurgeableData
Use, can realize automatic data clear function
-
- 51 streamline Tips
initialize
与load
Implementation code of-
load
Method has no override mechanism - Each class
load
Method call timing is uncertain, so inload
It is not safe to use other classes in a method - Before a class is used for the first time, the system sends
initialize
The message,initialize
Message memory override mechanism, so determine which class needs to be initialized at the moment -
load
和initialize
Both should be streamlined to improve the responsiveness of the application and reduce the probability of circular references - Global constants that cannot be set at compile time can be placed in
initialize
Method
-
- Tips 52
NSTimer
Will hold its target object-
NSTimer
The target object is held until the timer itself expires - With timers that execute tasks repeatedly, it’s easy to create circular dependencies
- You can extend the
NSTimer
Use blocks to solve the problem of loop dependencies
-