Advantages and disadvantages of bridge and adapter patterns

  • A Bridge, “Bridge,” is used forDecouple abstraction from implementation,They can vary independently. This type of design patternIt belongs to the structural patternIt throughProvide abstractionandTo achieve theBetween theThe bridge structureTo achieveDecoupling of the two.
  • Adapter patterns are used asTwo incompatibletheThe interface betweenthebridge. Of this typeDesign patterns are structural patternsIt combinesTwo separate interfacesThe function.
  • Thing in common:The bridgeandThe adapterIt’s all about two things working together
  • Difference:
    • The adapter:Change the two existing interfaces.Make them compatible.
    • Bridge mode:Dissociative abstractionandimplementation, so that the interface between the two can be different, the purpose is to separate.

The implementation process of POD Install

  • 1.Analyzing the dependency
    • Compare the versions in the local Pod and podfile.lock filesIf theInconsistency may indicate a risk.
  • 2.Contrast podfileWhether or nothappenthechange.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. IfThere is the removeThe,Delete the removethepods(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
  • 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 hookandpost-install hookYou can view it as a callback functionFor install in the podfileThe 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

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 justJust install the Podfile fileIn theSpecifies the version of the libraryAnd nothing more. andThe latest version will not be checked and updated.
  • Pod Update: It does as much as possibleUpdate 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:
    • decouplingTo eliminate dependencies between classes
  • Disadvantages:
    • Code readability degraded, will the original logiccomplicatedIs not conducive to maintenance
    • Poor performance. (using theThe reflection match string indirectly hits memorythanDirect hit memoryThe 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 inperformanceveryThe keytheApplication of the corePerformance 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 notTherefore, 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 communicationThe 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 eventsFor example, UI operations,Complex operation, so it willThe timer is blocked
  • 2.Mode switching, when createdWhen timer is added to NSDefaultRunLoopModeAt this time,If there is a sliding UIScrollView.The runLoop mode is switched to TrackingRunLoopMode, this isThe timer stops the callback

The solution

  • 1. InCreate a timer in the child threadIn theThe main thread performs scheduled task operations
  • In 2.Create a timer in the child threadIn 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 theaThe new weak pointer points to the address of the object
  • 2. Add a reference:objc_initWeakFunction willCall the objc_storeWeak() functionObjc_storeWeak () is used to update Pointers to other objectsUnbind the weak pointer from the old objectWill,Weak_unregister_no_lock)If theThe new object to which the pointer points is not null,Create the correspondingtheA weak reference tableThat will beWeak pointerwithThe new object is boundWill,Call to weak_register_no_lock. In the process, in order toPreventing multithreadingIn theThe competition conflicts, there will be some locking operations
  • 3. Release:Call the clearDeallocating function.ClearDeallocating functionFirst of all,Gets an array of all weak pointer addresses based on the object addressAnd thenWalk through the arrayAmong them theData is set to nilAnd finally put thisDescription Entry was deleted from the weak tableAnd 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 informationandAuxiliary informationJust 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 debugIf the collapse of the wild pointer were not random, the problem would be much simpler XcodeprovidesMalloc ScribblerightMemory has been released for data fillingSo as to ensureWild pointer accessisInevitably collapse. In addition,BuglyTake this principle and modify itFree functionforFreed object for illegal data populatingIt is also effectiveImproved wild pointertheCollapse 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

iOSThe messaging mechanism allows us toSends an unregistered message to the object, usually this causesunrecognized selectorThe exception. But before you throw an exception, there is oneforwardMechanism that allows us to respecify the recipient of a message to process the message. This mechanism has been implementedunrecognized selector crashThe feasible of

Break the reference ring

Circular reference isARCOne 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. referenceProxyCan be achieved to destroy the role of the reference ring. insertWeakProxyLayer the way to achieve the defensecrash

Routing forwarding

Componentization is an architectural solution that must be considered when the project volume reaches a certain levelThat will beThe project breaks down the underlying componentsandThe business componentTo joinThe middle layer decouples componentsThe effect. Due to theBusiness components do not depend on each otherTherefore, appropriate solutions are neededImplement component communication.routingDesign 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 inurlPassed 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