Analysis of hash table structure
We saw earlier in @Synchronization that you can have this many tables
class StripedMap {
#ifTARGET_OS_IPHONE && ! TARGET_OS_SIMULATOR
enum { StripeCount = 8 };
#else
enum { StripeCount = 64 };
#endif
// ...
}
Copy the code
So what is a hash table? We find the structure of the SideTable, and we find a weak reference table and a reference counting table
struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;
/ /...
};
Copy the code
A weak reference table
So before we do that, let’s take a quiz. What’s the print out below
NSObject *objc = [[NSObject alloc]init];
NSLog(@"%ld -%@", (long)CFGetRetainCount(objc), objc);
__weak typeof(id) weakObjc = objc;
NSLog(@"%ld -%@", (long)CFGetRetainCount(objc), objc);
NSLog(@"%ld -%@", (long)CFGetRetainCount(weakObjc), weakObjc);
Copy the code
Why is the third one two? Just follow the conventional thinking and break points, anddebug
Open the assembly
LibObjc: objc_initWeak -> storeWeak…. This structure is similar to the associative object
- Find the hash table first
- Find the weak reference table of weakTable in the hash table
- To create a
weak_entry_t
- the
referent
To join theweak_table
An array ofinline_referrers
>= TABLE_SIZE(entry) * 3/4
Weak_table capacity- the
new_entry
To join theweak_table
In the
Then continue tostep over
I’m going to go to this methodFind the libobJC source codeObjc_loadWeakRetained this method
Step by step debuggingNotice that at line 563 the reference count is still 1, but at line 566 the reference count is 2. We can guess from this that weak references are inrootTryRetain
Weak references can be +1, so I’ll print it again. Is count 3? So let’s verify thatWeak reference when the current object is copied to a reference count table, weakObjc operates reference count from its own weak reference table. Weak reference tables and ARC strong references are independent of each other,
Timer
The strong holds
What’s wrong with the following operation?
self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(fireHome) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
Copy the code
We destroy the timer in the dealloc method, but when the page pop returns the page is not released, so the timer keeps going. This creates a circular reference. Let’s try the weak modifier self
pop
It still wasn’t destroyed when it came back, so why?command + shift + O
Find the official documentation
What is stated here is that it is strongly held until the Timer is destroyed, so even if we use weakSelf modification, circular reference is still created here.
Solution 1: Use the following method, which does not hold self strongly
scheduledTimerWithTimeInterval:repeats:block:
Copy the code
Solution 2: The mediator mode Target does not use self FBKVO thinking
RunLoop -> Timer -> self -> Timer RunLoop -> Timer -> TimerProxy has no operation on self, so self can destroy the Timer on dealloc, and the Timer automatically disconnects from TimerProxy.
public class WeakTimerProxy: NSObject {
weak var target: NSObjectProtocol?
var sel: Selector?
/// required, the timer must be assigned to the proxy after the timer is instantiated, otherwise the timer itself will continue to run even if target is freed
public weak var timer: Timer?
public required init(target: NSObjectProtocol? .sel: Selector?). {
self.target = target
self.sel = sel
super.init(a)// Strengthen security protection
guard target?.responds(to: sel) = = true else {
return
}
// Replace target's selector with redirectionMethod, which reprocesses the event
let method = class_getInstanceMethod(self.classForCoder, #selector(WeakTimerProxy.redirectionMethod))!
class_replaceMethod(self.classForCoder, sel!, method_getImplementation(method), method_getTypeEncoding(method))
}
@objc func redirectionMethod(a) {
// If target is not released, the target method is called, otherwise the timer is released
if self.target ! = nil {
self.target!.perform(self.sel)
} else {
self.timer?.invalidate()
FCLog("Timer destroyed.")}}}Copy the code