Advantages and disadvantages of bridge and adapter patterns
- A Bridge, “Bridge,” is used for
Decouple abstraction from implementation
,They can vary independently
. This type of design patternIt belongs to the structural pattern
It throughProvide abstraction
andTo achieve the
Between theThe bridge structure
To achieveDecoupling of the two
. - Adapter patterns are used as
Two incompatible
theThe interface between
thebridge
. Of this typeDesign patterns are structural patterns
It combinesTwo separate interfaces
The function. - Thing in common:
The bridge
andThe adapter
It’s all about two things working together - Difference:
- The adapter:
Change the two existing interfaces
.Make them compatible
. - Bridge mode:
Dissociative abstraction
andimplementation
, so that the interface between the two can be different, the purpose is to separate.
- The adapter:
The implementation process of POD Install
- 1.
Analyzing the dependency
Compare the versions in the local Pod and podfile.lock files
If theInconsistency may indicate a risk
.
- 2.
Contrast podfile
Whether or nothappen
thechange
.The add/remove pod
- If present, two lists are generated, one for pods that need to be added and one for pods that need to be removed.
- 3. If
There is the remove
The,Delete the remove
thepods
(Removes version dependencies from podfile.lock) - 4.
Add the pods dependencies you need
. At this point, if theta isRegular CocoaPods libraries (Based on Git)
, will go first:- 1.
Find the corresponding Pods folder under Spec
- 2.
Find the corresponding tag
- 3.
Locate the podSpec file under the corresponding tag
- 4.
Git clone the code and copy it to the Pod directory
- 1.
- 5.
Run the pre - install hooks
- 6.
Generate the Pod Project
- 7.
Add the POD file to the project
- 8.
Add corresponding framework,. A libraries, and bundles
- 9.
Link header file to generate Target
- 10.
Run the post - install hooks
- 11.
Generate podfile. Lock
, then make a copy of the file mainfest.lock and place it in the Pod folder. If The sandbox is not sync with The podfile.lock error occurs, manifest.lock and podfile.lock files are inconsistent - 12.
Configure the original project file (Add Build Phase)
- 13.
Added Embed Pods Frameworks
- 14.
Added Copy Pod Resources
- Among them,
pre-install hook
andpost-install hook
You can view it as a callback functionFor install in the podfile
The logic that can be executed before or after (build project but not yet written to disk) is as follows:
Pre_install do | installer | # do some prior to installation of hook end post_install do | installer | # do some hook end after installationCopy the code
- Among them,
Note:
Pod Install preferentially follows the version information specified in the PodfileSecondly,
Follow the version information specified in podfile. lockTo install the corresponding dependency libraries.
Pod Install vs. Pod Update
- Pod Install: It just
Just install the Podfile file
In theSpecifies the version of the library
And nothing more. andThe latest version will not be checked and updated
. - Pod Update: It does as much as possible
Update the latest tripartite library
. The premise is toConforms to the version limit of the library corresponding to Podfile
. If pod ‘myPod’ is not added, ‘~>1.2’ is version-restricted. The latest version is updated.
Realization of OC reflection mechanism
The System Foundation framework provides apis for method reflection that allow us to perform operations such as converting strings to SEL. Due to the dynamic nature of the OC language, these operations occur at runtime, as follows:
FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector); FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector); FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName); FOUNDATION_EXPORT NSString *NSStringFromClass(Class aClass); FOUNDATION_EXPORT Class __nullable NSClassFromString(NSString *aClassName); FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0); FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0); FOUNDATION_EXPORT Protocol * __nullable NSProtocolFromString(NSString *namestr) NS_AVAILABLE(10_5, 2_0);Copy the code
With these methods, we can choose which instance to create at run time and dynamically choose which method to invoke. These operations can even be controlled by the parameters returned by the server. We can instantiate the class and method names returned by the server as our objects.
Common judgment methods
The NSObject class gives us some basic methods for making judgments that happen dynamically at runtime, as follows:
// whether the current object is an instance of this Class or its subclasses - (BOOL)isKindOfClass:(Class)aClass; // whether the current object is an instance of this Class - (BOOL)isMemberOfClass:(Class)aClass; // whether the current object complies with the Protocol - (BOOL)conformsToProtocol:(Protocol *)aProtocol; // whether the current object implements this method - (BOOL)respondsToSelector:(SEL)aSelector;Copy the code
Pros and cons of reflection
- Advantages:
decoupling
To eliminate dependencies between classes
- Disadvantages:
Code readability degraded
, will the original logiccomplicated
Is not conducive to maintenancePoor performance
. (using theThe reflection match string indirectly hits memory
thanDirect hit memory
The way ofslower
. Of course, the degree depends on the usage scenario, and the performance impact can be negligible if only as a part of the program that is rarely covered. However, if inperformance
veryThe key
theApplication of the core
Performance issues are especially important when reflection is used in logic.)
Differences between TCP and UDP
TCP connection-oriented, reliable data transfer service; UDP is a connectionless, best-effort data transfer service that does not guarantee the reliability of data transfer
TCP byte stream oriented and UDP packet oriented
TCP has congestion control, but UDP does not
Therefore, network congestion does not reduce the transmission rate of the source host (effective for real-time applications, such as live broadcasting, real-time video conferencing, etc.).TCP can only be one-to-one communication
The endpoint of a TCP connection is a socket.UDP supports one-to-one, one-to-many, many-to-one, and many-to-many communication
The TCP header is expensive
.It has 20 bytes, longer than the 8-byte header of UDP
The implementation principle of code Coverage tool
Santizer Coverage is simply a code coverage tool built into Clang. It implements global AOP’s killer by inserting a series of function calls prefixes __sanitizer_cov_trace_pc_ into user-defined functions. Its extensive coverage, including Swift/Objective-C/C/C++ and other languages, Method/Function/Block full support.
Opening method
To enable Santizer coverage, add -fsanitize-coverage=func, trace-PC-guard to “Other C Flags” in build Settings. If Swift code is included, you also need to add -sanitize-coverage=func and -sanitize=undefined in “Other Swift Flags”. All binaries linked to the App need santizer Coverage turned on to fully cover all calls
NSTimer doesn’t work
- 1.
NSTimer is added in mainRunLoop
,Pattern is NSDefaultRunLoopMode
.The mainRunLoop is responsible for all main thread events
For example, UI operations,Complex operation
, so it willThe timer is blocked
- 2.
Mode switching
, when createdWhen timer is added to NSDefaultRunLoopMode
At this time,If there is a sliding UIScrollView
.The runLoop mode is switched to TrackingRunLoopMode
, this isThe timer stops the callback
The solution
- 1. In
Create a timer in the child thread
In theThe main thread performs scheduled task operations
- In 2.
Create a timer in the child thread
In theA scheduled task is performed on a child thread
, you need toSwitch back to the main thread during UI operation
- 3. GCD implements the timer
The associated object implements the weak attribute
Weak: Modifies OBJC objects. It does not hold the pointer modifiers, and the reference count for the same object is not increased. When the pointer is released, the weak object is set to nil. Because heap memory is dynamic, when an object at an address is released, all Pointers to it should be null. Weak is used to avoid circular references and can be left empty when the object is released. Assign is used to modify the stack memory of numeric objects. Using assign to an OBJC object may result in wild Pointers. The reason was just mentioned above.
To attribute a Category, you need to use the runtime association to implement the set and GET methods. However, the Runtime only provides the following modifier implementations and does not have weak.
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
Copy the code
The idea is that, although the Runtime does not have an open solution for weak, OBJC objects can implement weak, so let the object that needs to be decorated hold a strong object, and then when the decorated object is freed, the holding object will also be freed, and then we can capture the freed event. Then use OBJC_ASSOCIATION_ASSIGN to implement weak references, and then release them in the release event to achieve weak function.
// Define an object and call the destructor back and forth with block. typedef void (^DeallocBlock)(); @interface OriginalObject : NSObject @property (nonatomic, copy) DeallocBlock block; - (instancetype)initWithBlock:(DeallocBlock)block; @end @implementation OriginalObject - (instancetype)initWithBlock:(DeallocBlock)block { self = [super init]; if (self) { self.block = block; } return self; } - (void)dealloc { self.block ? self.block() : nil; } @endCopy the code
Category Add attribute
// Category // NSObject+property.h @interface NSObject (property) @property (nonatomic, weak) id objc_weak_id; @end // NSObject+property.m @implementation NSObject (property) - (id)objc_weak_id { return objc_getAssociatedObject(self, _cmd); } - (void)setObjc_weak_id:(id)objc_weak_id { OriginalObject *ob = [[OriginalObject alloc] initWithBlock:^{ objc_setAssociatedObject(self, @selector(objc_weak_id), nil, OBJC_ASSOCIATION_ASSIGN); }]; // The key must be unique. If you use _cmd, the previous object associations will be invalid if you associate the same object multiple times. objc_setAssociatedObject(objc_weak_id, (__bridge const void *)(ob.block), ob, OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(self, @selector(objc_weak_id), objc_weak_id, OBJC_ASSOCIATION_ASSIGN); }Copy the code
Specific experience difference between Weak and Assgin:
@property (nonatomic,weak) id weakPoint; @property (nonatomic,assign) id assignPoint; @property (nonatomic,strong) id strongPoint; self.strongPoint = [NSDate date]; self.weakPoint = self.strongPoint; self.assignPoint = self.strongPoint; self.strongPoint = nil; NSLog(@"%p", self.weakPoint); // print 0x0 pointer is null. NSLog(@"%p", self.assignPoint); // crash because the object to which self.assignPoint points has been released.Copy the code
Test whether weak is correct:
self.strongPoint = [NSDate date]; self.objc_weak_id = self.strongPoint; self.weakPoint = self.strongPoint; NSLog(@"%p", self.weakPoint); // print pointer. NSLog(@"%p", self.objc_weak_id); // print the same pointer. self.strongPoint = nil; NSLog(@"%p", self.weakPoint); // print 0x0 pointer is null. NSLog(@"%p", self.objc_weak_id); // print 0x0 pointer is null.Copy the code
Adding a property to a Category is relatively rare, and adding a weak property is very rare, but by doing this, you can see what weak is and what assign is, rather than just using weak in the delegate, NSInteger with assign.
How does the Runtime implement the weak attribute
- 1. Initialization:
runtime
willCall the objc_initWeak function
.Initialize the
aThe new weak pointer points to the address of the object
- 2. Add a reference:
objc_initWeak
Function willCall the objc_storeWeak() function
Objc_storeWeak () is used to update Pointers to other objectsUnbind the weak pointer from the old object
Will,Weak_unregister_no_lock)
If theThe new object to which the pointer points is not null
,Create the corresponding
theA weak reference table
That will beWeak pointer
withThe new object is bound
Will,Call to weak_register_no_lock
. In the process, in order toPreventing multithreading
In theThe competition conflicts
, there will be some locking operations - 3. Release:
Call the clearDeallocating function
.ClearDeallocating function
First of all,Gets an array of all weak pointer addresses based on the object address
And thenWalk through the array
Among them theData is set to nil
And finally put thisDescription Entry was deleted from the weak table
And the lastClears records of objects
IOS wild pointer
What is a wild pointer?
A stray pointer is called a wild pointer when the object it points to is released or reclaimed, but no changes are made to the pointer so that it still points to the reclaimed memory address.
An ordinary pointer can become a wild pointer only if the object it points to is released or retracted, or if no changes have been made to it.
It should be noted that accessing the wild pointer itself is fine and does not cause an exception; Exception only occurs when wild Pointers are used (such as when an OC sends a message to an object), indicating a flash back.
Wild pointer anomaly
Compared with NSException, wild pointer exception can be called half of crash field. Compared with NSException, wild pointer has two characteristics:
1. Randomness is strong
The resulting wild pointer is diverse: first, the memory freed does not mean that the memory will be overwritten or the data will be corrupted immediately, and accessing the memory at this time does not necessarily cause errors. Second, multithreading creates a complex application environment in which unprotected data can be fatal. In addition, the design of the code is not strict is also one of the important reasons for the exception of wild pointer
2. Difficult to locate
NSException is encapsulation at a high level of abstraction, which means that it provides more error information to refer to. The wild pointer is almost from the C language level, often we can get only the system stack information, it is difficult to locate the error code location, let alone to reproduce the repair
positioning
The biggest difficulty to solve the wild pointer lies in location. Usually when a crash occurs online and needs to be fixed, the most important step for developers is to recreate the crash. The two characteristics of the wild pointer mentioned above will prevent us from locating the problem. For these two characteristics, some corresponding processing can be done to reduce their interference:
Take auxiliary information
Auxiliary information, including device information, user information and other information, can often be used to reproduce the problem. For example, user behaviors can form user usage paths to reproduce user usage scenarios. When a crash occurs, the current page information can be collected and the user can use the path to quickly locate the approximate location of the problem. After verification, the auxiliary information can effectively reduce the interference of the system stack to the problem recurrence
Improved wild pointer crash rate
Since wild Pointers do not necessarily crash this feature, even if we passThe stack information
andAuxiliary information
Just because we’ve got a ballpark doesn’t mean we’re gonna make itcrash
. An excellent wild pointer crash can be causedOne day development, three days debug
If the collapse of the wild pointer were not random, the problem would be much simpler Xcode
providesMalloc Scribble
rightMemory has been released for data filling
So as to ensureWild pointer access
isInevitably collapse
. In addition,Bugly
Take this principle and modify itFree function
forFreed object for illegal data populating
It is also effectiveImproved wild pointer
theCollapse rate
Zombie Objects
Zombie Objects is a completely different wild pointer debugging mechanism, which marks the released object as a Zombie object and sends a message to the Zombie object again, crashing and printing the relevant call information. This mechanism simultaneously locates the crash class object and has a relatively clear call stack
The solution
Sorting through the above, you can see that there are two main ways to cope: auxiliary information + object memory padding and Zombie Objects. In the case of the former, populating the memory of freed objects is risky, as Xcode9’s Malloc Scribble starts without populating the memory address of the object. Second, filling memory requires hooking lower-level apis, which means higher code capabilities. Therefore, it is a feasible solution to locate the wild pointer anomaly using the implementation idea of Zombie Objects
forwarding
Forwarding is an interesting mechanism that works by inserting an intermediate layer between the two sides of the communication. Instead of coupling the receiver, the sender simply sends the data to the middle tier, which then sends it to the specific receiver. There are a lot of interesting things you can do based on the idea of forwarding:
forward
iOS
The messaging mechanism allows us toSends an unregistered message to the object
, usually this causesunrecognized selector
The exception. But before you throw an exception, there is oneforward
Mechanism that allows us to respecify the recipient of a message to process the message. This mechanism has been implementedunrecognized selector crash
The feasible of
Break the reference ring
Circular reference isARC
One of the most common memory problems in the environment is when references between multiple objects form a reference ring, which is likely to cause the objects in the ring to be unable to be freed. referenceProxy
Can be achieved to destroy the role of the reference ring. insertWeakProxy
Layer the way to achieve the defensecrash
Routing forwarding
Componentization is an architectural solution that must be considered when the project volume reaches a certain level
That will beThe project breaks down the underlying components
andThe business component
To joinThe middle layer decouples components
The effect. Due to theBusiness components do not depend on each other
Therefore, appropriate solutions are neededImplement component communication
.routing
Design is a kind ofCommon means of communication
. Implementation of each modulecanOpenURL:
Interface to determine whether to process the corresponding jump logic, the module splices the parameter information inurl
Passed in:
The implementation principle of notification, whether synchronous or asynchronous
Synchronization cause: Event occurs, notification center broadcast, there may be multiple listeners, design to use synchronous mode, can ensure that all listeners respond to the notification! No omissions