This article lists 9 common crash types. The original text is very good, and I will sort out and record them based on my own experience.
(a) KVO
A common scenario of KVO is that the View object listens to the View Model object to refresh the UI in real time. For example, if there is a table view, each cell listens to the corresponding cell Model, so that there is no need to reload the entire list when only one object’s property changes in the data source array.
A common crash with KVO is that the listener is not removed, so we need to execute the removeObserver method in the dealloc method. Facebook’s open source KVOController is recommended to make it easier to use KVO.
(2) Modify the set when traversing the variable set
We often encounter collection traversal crash, one thing to note that in the traversal variable set (NSMutableArray, NSMutableDictionary, NSMutableSet), will not be able to change the collection, such as adding or removing elements in the collection. This problem is best avoided from code specifications, such as interfaces that should not expose mutable collections, but readonly collections. Here’s a recommended way to write it:
People.h
#import <Foundation/Foundation.h>
@interface People : NSObject
@property (nonatomic, strong, readonly) NSArray *friends;
- (void)addFriend:(id)aFriend;
- (void)removeFriend:(id)aFriend;
@endCopy the code
People.m
#import "People.h"
@interface People ()
@property (nonatomic, strong) NSMutableArray *internalFriends;
@end
@implementation People
- (void)dealloc
{
//
}
- (instancetype)init
{
self = [super init];
if (self) {
_internalFriends = [NSMutableArray new];
}
return self;
}
- (void)addFriend:(id)aFriend
{
if (aFriend == nil) {
return;
}
@synchronized(self)
{
[_internalFriends addObject:aFriend];
}
}
- (void)removeFriend:(id)aFriend
{
if (aFriend == nil) {
return;
}
@synchronized(self)
{
[_internalFriends removeObject:aFriend];
}
}
//NSMutableArray copy -> NSArray
- (NSArray *)friends
{
return [_internalFriends copy];
}
@endCopy the code
Another point to note is that we should doubt the correctness of the set returned by the third-party interface. It is possible that the interface is written as immutable but actually returns a mutable set. If we directly use the set as immutable, crash may be triggered. Therefore, it is a good practice to copy the data returned by the third-party interface before traversing the collection.
(3) the NSNotification
NSNotification is a one-to-many listening mechanism. A common crash is that the listener is not removed after the object dealloc.
Remove the listening mode
We can remove it based on the specific notification name, for example
[[NSNotificationCenter defaultCenter] removeObserver:self name:kSomeNotificationName object:someObject];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kSomeOtherNotificationName object:someOtherObject];
etc...Copy the code
There is no problem with the above method, but it is not conducive to maintenance. For example, new notifications need to be added to realize them later, and corresponding codes need to be added to remove them. If we forget to remove them accidentally, crash will be triggered. A more recommended approach is to use [[NSNotificationCenter defaultCenter] removeObserver:self] in dealloc; To remove
Repeat listening
One problem to note when registering for listening notifications is that repeated registration results in callback methods entering multiple times. We often register listeners in viewDidLoad, but views can still reloaded, so viewDidLoad can still be unloaded many times leading to repeated registrations.
Register in init method, remove in dealloc method
For an object, its init method is executed only once, as is the dealloc method, so registering and removing in both methods ensures that registration and removal are balanced, making it easier to troubleshoot problems.
Avoid using addObserverForName
[NSNotificationCenter addObserverForName: object: queue: usingBlock:] provides the method of block to use notice, but we should avoid using this way, because it need we in the subsequent code to remove alone, This increases the possibility of errors, unlike the ones mentioned above that can be removed uniformly in Dealloc.
(4) Handling empty situations
We know that in Objective-C, it’s okay to send messages to nil, for example
[thing doStuff];
This is fine, but if the argument is nil, it depends on how the method is implemented, for example:
[self doStuff:thing];
In this case, it depends on what thing is used for. What if the method implementation has code like this
menuItem.title = thing;
MenuItem is NSMenuItem, so when thing is empty it causes crash.
One recommended approach is to use assertions to short arguments, as follows:
- (void)someMethod:(id)someParameter { NSParameterAssert(someParameter); ...doWhatever... }Copy the code
(5) Trespassing
Of course, there are other transgressions, such as NSrange. For these, it is recommended to do range check before using them, which is also a point to pay attention to.
(6) Non-main thread processing UI events
Handling UI events on a non-main thread can cause unexpected events, such as a crash or UI display exception. For example, if we perform a time-consuming calculation task on a child thread and then pass the calculation result to the UI to update the display, we need to
dispatch_async(dispatch_get_main_queue(), ^{
});Copy the code
In addition, the author also presents some of his programming practices, such as:
- When possible, queue tasks on the main thread to avoid most multithreading problems, except for tasks that have been detected to have performance bottlenecks that need to be placed on child threads, which also tend to have independent tasks placed on child threads
- Use dot syntax whenever possible (assigning _property = XXX does not trigger KVO), ARC, and weak attributes
- Establish a perfect crash collection mechanism, and record the bug tracking
- The code should look clear when written, but if it looks convoluted, it needs refactoring
Resources: inessential.com/hownottocra…
Finally do a promotion, welcome to pay attention to the public account MrPeakTech, I learn a lot from here, recommend to everyone, common progress ~