1. UIViewandCALayerWhat is the relationship?
  • UIViewInherited fromUIResponderClass that can respond to events
  • CALayerDirectly inherited fromNSObjectClass that cannot respond to events
  • UIViewisCALayerthedelegate(CALayerDelegate)
  • UIViewPrimarily dealing with events,CALayerResponsible for the drawing
  • eachUIViewThere’s one on the insideCALayerProvide the content behind the drawing and display, andUIViewThe dimensions and styles are all made up of internalLayerProvided. Both have tree-like hierarchies,LayerinternalSubLayers.ViewinternalSubViews, butLayerthanViewMore than aAnchorPoint
  1. NSCacheandNSMutableDictionarySimilarities and differences

Similarities: NSCache and NSMutableDictionary functions are basically the same differences: NSCache is thread-safe, NSMutableDictionary threads are not, A class developed by Mutable is generally not thread-safe. NSCache automatically frees memory when it runs out of memory (so always check for empty data when fetching from the cache). NSCache can specify a cache limit, The NSCache Key is a Strong reference to the object, not a copy, so NSCopying is not required

  1. atomicThe implementation mechanism of the; Why can’t absolute thread-safety be guaranteed (preferably in context)
  • atomicIt’s going to be on the propertysetter/getterMethod to lock, which is only guaranteed during operationsetter/getterThe method is safe. The safety of other threads cannot be guaranteed
  • For example, thread 1 called the property ofsetterMethod and thread 2 calls it halfway throughgetterMethod, then the execution will finishsetterAfter the operation, run the command againgetterOperation, thread 2 gets thread 1setterAfter the full value; When several threads simultaneously invoke the same attributeSetter and getterMethod, a complete value is obtained, but the value obtained is not controllable
  1. Several methods of introspection in iOS

The ability of an object to get its type at run time is called introspection. Introspection there are several ways to implement introspection at OC runtime:

  • Determine the object type:
-(BOOL) isKindOfClass: // Check whether it is an instance of this class or a subclass of this class -(BOOL) isMemberOfClass: // Check whether it is an instance of this classCopy the code
  • Determines whether an object/class has this method
- (BOOL) respondsToSelector: / / instance such method + (BOOL) instancesRespondToSelector: / / judge whether there is the wayCopy the code
  1. objcWhat happens when you send a message to an object

Find the class of the object based on its ISA pointer, and go to objc’s corresponding class to find method 1. First, look for the invoked method in the list of cached methods in the object of the corresponding operation. If found, turn to the corresponding implementation and execute 2. If no, look for the called method in the method list of the corresponding operation object. If no, go to the corresponding implementation and perform 3. If not, go to the object pointed to by the parent pointer and execute 1,2. 4. And so on. An error is reported if the intercepting method was not overridden

  1. Have you ever been exposed to the reflex mechanism in OC? Talk a little bit about the concept and usage
  • classreflection
  • Instantiate an object as a string of class names
Class class = NSClassFromString(@"student"); 
Student *stu = [[class alloc] init];
Copy the code
  • Change the class name to a string
Class class = [Student class];
NSString *className = NSStringFromClass(class);
Copy the code
  • SELThe reflection of
  • Instantiate a method as a string
SEL selector = NSSelectorFromString(@"setName");
[stu performSelector:selector withObject:@"Mike"];
Copy the code
  • Turn the method into a stringNSStringFromSelector(@selector(setName:));
  1. What could go wrong with this notation@property (nonatomic, copy) NSMutableArray *arr;

When adding, deleting, or modifying elements in an array, the program will crash because it can’t find the corresponding method. Cause: Copy copies an immutable NSArray object. You cannot add or modify an NSArray object

  1. How do I make my classes usefulcopyThe modifier

If you want to copy your own objects, you need to implement the NSCopying protocol. NSCopying and NSMutableCopying protocols are implemented simultaneously if the custom object is of mutable and immutable versions. 1. Declare that the class complies with the NSCopying protocol. 2

  • NSCopyingProtocol method:
- (id)copyWithZone:(NSZone *)zone {
  MyObject *copy = [[[self class] allocWithZone: zone] init];
  copy.username = self.username;
  return copy;
}
Copy the code
  1. whyassignCannot be used to modify objects

First of all, we need to be clear that the memory of the object is usually allocated to the heap, and the memory of the basic and OC data types is usually allocated to the stack. If we assign the object, when the object is released, the address of the pointer still exists, which means that the pointer is not set to nil, thus creating a wild pointer. Because objects are allocated on the heap, memory on the heap is allocated and freed by the programmer. And because Pointers aren’t set to nil, if a subsequent allocation happens to be in this block, it’s going to crash and assign decorates the base data type or the OC data type, because the base data type is allocated on the stack, allocated and freed by the system, so it’s not going to cause wild Pointers

  1. Write the following code output
 int a[5] = {1, 2, 3, 4, 5};
 int *ptr = (int *)(&a + 1);
 printf("%d, %d", *(a + 1), *(ptr + 1));
Copy the code

Random value analysis: a represents the first address of an array with five elements, and the elements of a[5] are 1,2,3,4,5. Next, a + 1 means the beginning of the data plus 1, so it’s a[1], which corresponds to a value of 2, but it’s ampersand a + 1, because a is the entire array, and it’s 5 times sizeof(int), so ampersand a + 1 is a + 5. A is a constant pointer to the beginning of the current array, and the pointer +1 moves sizeof(int) by a number of bytes. So PTR is a pointer to int *, and PTR is a pointer to a + 5, so PTR +1 is also a + 6, so the last *(PTR +1) is a random value. And *(PTR – 1) is the same thing as a plus 4, which is equal to 5

  1. aviewIt’s already initialized,viewI added n to itbutton(may be created using a loop), exceptviewthetagWhat else can you do to find what you wantbuttonTo modify theButtonThe value of the

If a button is clicked, it will refresh its value, other need not modify, then do not reference any button, directly in the callback, has already received the response button to pass, directly through it can modify the second type: When a button is clicked, all buttons of the same type change their values, so you can create the button by storing it in an array and iterating through it as needed

  1. UIViewControllertheViewDidUnload, viewDidLoadandloadViewWhen are they called?UIViewthedrawRectandlayoutSubviewsWhat do they do

First question: viewDidUnload is called before the controller is destroyed, loadView is called when the controller doesn’t have any views and viewDidLoad is called when the view is finished loading. Second question: After we call setNeedsDisplay, we’ll call drawRect, and we can do that by getting the context and then setNeedsLayout, we’ll call layoutSubviews, We can tweak the UI in this way. Of course, there are many ways to cause layoutSubviews to be called, such as adding subviews, scrolling scrollViews, changing the view’s frame, etc

  1. Working principle of automatic release pool

An autorelease pool is an instance of the NSAutorelease class. When an autoRelease message is sent to an object, the object is automatically pooled, and when the pool is destroyed, a release message is sent to all objects in the pool. The release object [Pool Release], [pool drain] means that the pool itself is not destroyed, but that temporary objects in the pool are sent releases to destroy the object

  1. How does Apple do thatautoreleasepoolthe

Autoreleasepool is implemented by AutoreleasePoolPage as a bidirectional list through the following three functions:

  • byobjc_autoreleasePoolPushAs the first function to automatically release the pool scope
  • useobjc_autoreleaseAdds objects to the automatic release pool
  • byobjc_autoreleasePoolPopAs the last function to automatically release the pool scope
  1. autoreleaseWhen the object is released

RunLoop goes to the auto-free pool at the end of each event loop to reduce the reference count of all auto-free objects by one. If the reference count becomes zero, the object is actually destroyed and memory is reclaimed. Without manually adding an Autorelease Pool, the Autorelease Pool will reduce the reference count of all autoreleased objects by one at the end of each event loop. If the reference count becomes zero, the object will be freed and memory will be reclaimed. Therefore, if you want torelease an AutoRelease object earlier, you can add an automatic release pool to the object. For example, when looping through data, temporary variables should be released quickly:

// Add @autoreleasepool directly to objects created by alloc. Autorelease is not required for objects created by class methods. The reason is that the system automatically adds autoReleases to objects created by class methodsfor (int i = 0; i < 1000000; i++) {
 @autoreleasepool {
   NSString *str = @"Abc";
   str = [str lowercaseString];
   str = [str stringByAppendingString:@"xyz"];
   NSLog(@"% @", str); } // From here, the automatic release pool will be traversed.Copy the code
  1. This section describes basic principles of memory management

OC memory management follows the mechanics of who creates, who frees, who references, and who manages. When you use alloc, copy, or retian an object, you’re obligated to send a release or autoRelease message to it torelease the object. You don’t need to manage memory. When the object reference count reaches zero, the system will release the object. This is the OC’s manual management mechanism (MRC) that sends an AutoRelease message to an object. It releases the object by sending a release message to every object in the pool, not because the object is destroyed, but when the object’s reference count reaches zero, the system calls the dealloc method to release the object and its own instances

  1. sizeofThe keyword

Sizeof is processed at compile time and cannot be compiled to machine code. The result of sizeof is equal to the number of bytes of memory occupied by the object or type. Sizeof returns a value of type size_t variable: int a; Sizeof (a) is 4; Pointer: int *p; Sizeof (p) is 4; Array: int b[10]; Sizeof (b) is the sizeof the array 4*10; int c[0]; Sizeof c is equal to 0, sizeof void is equal to 1, sizeof void star is equal to 4

  1. What is off-screen rendering? Under what circumstances can it be triggered? Off-screen rendering is a performance drain

Off-screen rendering is to create a new buffer outside the current screen buffer for operation. Off-screen rendering triggers the following scenes:

  • Rounded corners (set at the same timeLayer. masksToBounds = YES, layer.cornerRadiusGreater than zero)
  • Layer mask
  • The shadow,layer.shadowXXXIf setlayer.shadowPathThere will be no off-screen rendering
  • Mask,layer.mask
  • Rasterizer,layer.shouldRasterize = YES

The reason why off-screen rendering consumes performance is that it needs to create a new buffer. In the whole process of off-screen rendering, it needs to switch the context environment several times. First, it needs to switch from the current Screen to the off-screen and display the rendering result of the off-screen buffer On the Screen after the off-screen rendering is finished. You also need to switch the context from off-screen to the current screen

  1. In ARC, what are the default keys when you do not explicitly specify any property keys

The default keywords for basic data types are: atomic, readwrite, assign The default keywords for ordinary Objective-C objects are: atomic, readwrite, strong

  1. What are the essential differences and connections between class methods and instance methods in OC

Methods:

  • Class methods belong to class objects
  • Class methods can only be called from class objects
  • Self in the class method is the class object
  • Class methods can call other class methods
  • A member variable cannot be accessed in a class method
  • Object methods cannot be called directly from a class method

Instance methods:

  • Instance methods belong to instance objects
  • Instance methods can only be called from instance objects
  • Self in the instance method is the instance object
  • Member variables can be accessed in instance methods
  • Instance methods are called directly from instance methods
  • Class methods can also be called from instance methods (by class name)
  1. Can I add instance variables to the compiled class? Can I add instance variables to classes created at run time? Why is that?
  • You cannot add instance variables to compiled classes
  • Ability to add instance variables to classes created at run time
  • Because the compiled classes are already registered inruntimeIn the class structureobjc_ivar_listThe linked list sum of instance variablesinstance_sizeThe memory size of the instance variable has been determined whileruntimeWill be calledclass_setIvarLayoutorclass_setWeakIvarLayoutTo deal withstrong weakReference, so you can’t add instance variables to existing classes. Runtime classes created can be called to add instance variablesclass_addIvarFunction. But it has to be calledobjc_allocateClassPairAfter that,objc_registerClassPairBefore, for the same reason
  1. runtimeHow to useselectorFind the correspondingIMPAddress (consider instance method and class method respectively)Selector, Method, and IMPWhat are the differences and connections between

For instance methods, each instance’s ISA pointer points to the corresponding class object, and each class object has a list of object methods. For class methods, the ISA pointer to each class object points to the corresponding metaclass object, and each metaclass object has a list of class methods. Method list records the name of the Method, Method implementation, and parameter type, in fact, the selector is essentially the name of the Method, through this Method name can be found in the Method list corresponding Method implementation selector, Method and IMP can be described like this: You distribute messages at run time, and each entity in the Method list is a Method and it’s called SEL and it corresponds to a Method implementation IMP

  1. Objc_msgSend, _objc_msgForwardWhat do they do? What is the message invocation flow in OC
  • objc_msgSendIt’s used to send messages. inOCIn, all calls to methods are converted to internal message sending execution
  • _objc_msgForwardisIMPThe type (function pointer) is used for message forwarding: when a message is sent to an object and it is not implemented,_objc_msgForwardWill attempt to do message forwarding
  • During the message invocation,objc_msgSendThe action is more clear: first inClassCache lookup inIMPIf no cache is found, the parent class is initializedClassLookup. If the root class is still not implemented, use_objc_msgForwardFunction pointer substitutionIMP. Finally, execute thisIMP. When you call aNSObjectWhen an object does not have a method, it does not throw an exception immediately. Instead, it calls the object’s method through multiple layers of forwarding- resolveInstanceMethod:, - forwardingTargetForSelector:, - methodSignatureForSelector:, - forwardInvocation:Methods. Where the last-forwardInvocation:There will be oneNSInvocationObject, this oneNSInvocationThe object holds all information about this method call, includingSelector name, parameter, and return value typeYou can start with thisNSInvocationGets the values of all the arguments to the call
  1. classMethods andobjc_getClassWhat’s the difference

Object_getClass (obj) returns a pointer to isa in obj. When obj is an instance object, the class in [obj class] is the instance method, which returns the ISA pointer in obj object. The other is that when obj is a class object (including metaclass, root class and root metaclass), the class method is called and the result is itself returned

  1. OC to onenilWhat happens when the object sends a message

Sending messages to nil in OC is perfectly valid, it just doesn’t do anything at run time; When you send a message to a nil object, the first thing that comes back when you look for the isa pointer to the object is the zero address, so you don’t get any errors, you don’t crash

  1. _objc_msgForwardWhat does a function do? What happens when you call it directly

_objc_msgForward is a function pointer (of the same type as IMP) for message forwarding; When a message is sent to an object and it is not implemented, _objc_msgForward will try to forward the message. Objc_msgSend is used for message passing. The action of objc_msgSend is clear during message passing: first look for the IMP in the cache of the Class (initialize the cache if there is no cache). If not, look for the parent Class. If _objc_msgForward is called, the IMP will skip the IMP lookup process and directly trigger the message forward. If _objc_msgForward is called, the IMP will skip the IMP lookup process and directly trigger the message forward. Even if the object does implement this method, you can tell objc_msgSend that I didn’t find an implementation of this method in this object, and that it will Crash if used badly

  1. When will it be reportedunrecognized selectorThe abnormal
  • When a method is called on an object that has no implementation of the method. Can be achieved byforwardSee the following figure for the process
  • OCWhen sending a message to an object,runtimeLibraries are based on objectsisaThe pointer finds the class that the object actually belongs to, and then looks for the method to run in the list of methods in that class and the list of methods in its parent class. If the corresponding method is still not found in the topmost parent class, the program hangs at runtime and throws an exceptionunrecognized selector sent to XXX But before that, the OC runtime gives three chances to save the program from crashing
  • Method Resolution (dynamic message resolution)OCRun time call+resolveInstanceMethod:or+resolveClassMethod:, gives you the opportunity to provide a function implementation. If you add a function, the runtime restarts the process of sending a message; otherwise, the runtime moves to the next step, message forwarding (Message Forwarding)
+ (BOOL)resolveInstanceMethod:(SEL) SEL {// If run is implemented, IMP is dynamically resolvedif (sel == NSSelectorFromString(@"run:"// IMP: method implementation => function => function entry => function name //typeVoid void v, id @, SEL: class_addMethod(self, SEL, (IMP)runMethod,"v@:@");
        return YES;
    }
    return[super resolveInstanceMethod:sel]; } // The new run function void runMethod(id self, SEL _cmd, NSNumber *meter) {NSLog(@)"Ran % @", meter);
}
Copy the code
  • Fast forwarding if the target object is implemented-forwardingTargetForSelector:.RuntimeThis method is called, giving you the opportunity to forward the message to other objects. As long as this method returns nonilandselfThe whole process of sending the message will be restarted, and of course the object you sent will become the object you returned. Otherwise, it will continueNormal Fowarding. This is calledFast, just to distinguish the forwarding mechanism for the next step. Because this step does not create any new objects, the next step forward will create oneNSInvocationObject, so it’s relatively faster
/ / message recipient redirect - (id) forwardingTargetForSelector aSelector: (SEL) {if (aSelector == @selector(run:)) {
        return[[Person alloc] init]; Return the Person object to receive the message}return [super forwardingTargetForSelector:aSelector];
}
Copy the code
  • Normal forwarding this step isRuntimeOne last chance to save the day. First it sends-methodSignatureForSelector:The message gets the parameter and return value types of the function. if-methodSignatureForSelector:returnnil.RuntimeWill be issued-doesNotRecognizeSelector:Message, and the program hangs. If a function signature is returned,RuntimeI’m going to create oneNSInvocationObject and send-forwardInvocation:Message to the target object
/ / get function parameters and return values of type, return the signature - (NSMethodSignature *) methodSignatureForSelector aSelector: (SEL) {if ([NSStringFromSelector(aSelector) isEqualToString:@"run:"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return[super methodSignatureForSelector:aSelector]; } // message redirection - (void)forwardInvocation:(NSInvocation *)anInvocation {// get message SEL from anInvocation SEL = anInvocation.selector;if (sel == NSSelectorFromString(@"run:"// Invocation of the current method as IMP // anInvocation. Selector = @selector(readBook:); // [anInvocation invoke]; IMP Person *p = [[Person alloc] init]; // Determine if the Person object method can respond to selif([p respondsToSelector:sel]) {// If the invocation is responsive, the message is forwarded to another object [anInvocation invokeWithTarget:p]; }else{/ / if still can't response, then an error: can't find the response method [self doesNotRecognizeSelector: sel]; }}else{
        [super forwardInvocation:anInvocation];
    }
}

- (void)doesNotRecognizeSelector:(SEL)aSelector {
    [super doesNotRecognizeSelector:aSelector];
}
Copy the code

Since – forwardingTargetForSelector: and – forwardInvocation: all messages can be forwarded to other objects, then where is the difference between the two? The difference is that – forwardingTargetForSelector: only forward the message to an object. The -forwardInvocation: the message can be stored, forwarded when you see fit, or not processed. Modify message target, selector, parameters, etc. Forwarding messages to multiple objects

  1. iOS layoutSubviewsWhen will it be called
  • initMethod does not calllayoutSubviewsBut withinitWithFrameInitialization is performed whenrectThe value of theCGRectZeroIs triggered
  • addSubviewWill triggerlayoutSubviewsmethods
  • setFrameOnly when setframeThe parameters of thesizeWith the originalsizeIt is triggered by differenceviewthelayoutSubviewsmethods
  • slidingUIScrollViewWill be calledscrollviewandscrollviewOn theviewthelayoutSubviewsmethods
  • The rotating device will only be calledVCtheviewthelayoutSubviewsmethods
  • Direct call[self setNeedsLayout];(This is explained in the Apple documentation above)-layoutSubviewsMethod: This method does nothing by default and needs to be overridden by subclasses-setNeedsLayoutMethod: mark for need of relayout and call asynchronouslylayoutIfNeededRefresh layout, not immediately, butlayoutSubviewsIt’s bound to be called-layoutIfNeededMethod: Call immediately if there is a tag that needs to be refreshedlayoutSubviewsLayout (not called if there is no taglayoutSubviewsIf you want to refresh immediately, call first[view setNeedsLayout], set the tag to need layout, and call it immediately[view layoutIfNeeded]Before the view is first displayed, the markup is alwaysNeed to refreshCan be called directly[view layoutIfNeeded]
  1. What happens to the following code
@property (nonatomic, strong) NSString *str;

dispatch_queue_t queue = dispatch_queue_create("parallel", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 1000000 ; i++) {
    dispatch_async(queue, ^{
        self.str = [NSString stringWithFormat:@"changzifuchaung:%d",i];
    });
}
Copy the code

Will crash. Because an asynchronous dispatch_async assignment to the STR attribute in the parallel queue DISPATCH_QUEUE_CONCURRENT results in STR already being released and also being released. This is what happens when a message is sent to an object that has freed memory: the STR attribute strong modifier is assigned, as in MRC

- (void)setStr:(NSString *)str{
    if (str == _str) return; id pre = _str; [str retain]; //1. Keep the new value _str = STR; //2. Assign [pre release]; //3. Release old value}Copy the code

So if thread A in the concurrent queue executes to step 1 and thread B executes to step 3 before it reaches step 2, then when thread A executes to step 3, the old value will be overfreed, causing A crash by sending messages to the freed object

  • Follow-up: How to modify this code to not crash

Atomic atomic: setters are thread-safe, and setters are threadsafe. Setters are threadsafe, and setters are threadsafe. Setters are threadsafe, and setters are threadsafe. 3. Setters that use the weak keyword weak do not retain operations on new values, so they do not cause repeated releases. If you want to use an “weak” lock, you can use an “weak” lock. If you want to use an “weak” lock, you can use an “weak” lock. @synchronized (self) {self. STR = [NSString stringWithFormat:@”changzifuchaung:%d”, I]; Tagged Pointer is a memory technology introduced by Apple on 64-bit systems. For NSString or NSNumber, 64-bit Pointers are 8 bytes long. You can use this space to directly represent values. This will actually convert NSString and NSNumber objects from a pointer to a value type. Setters and getters for value types are atomic, making them thread-safe

  • Divergent: The following code doescrash?
@property (nonatomic, strong) NSString *str;

dispatch_queue_t queue = dispatch_queue_create("parallel", DISPATCH_QUEUE_CONCURRENT);
for(int i = 0; i < 1000000 ; I++) {dispatch_async(queue, ^{self. STR = [NSString stringWithFormat:@"%d",i];
        NSLog(@"%d, %s, %p", i, object_getClassName(self.str), self.str);
    });
}
Copy the code

Won’t crash. And it turns out that STR is a string of type NSTaggedPointerString. TaggedPointer is an interesting technique that can improve performance and save memory. TaggedPointer is for storing small objects, For example, the Tagged Pointer to NSNumber and NSDate(which can later store small strings) is no longer an address, but a real value. So, it’s not really an object anymore, it’s just a normal variable in an object wrapper that doesn’t have memory stored in the heap, doesn’t need malloc and free, so it’s incredibly fast to read and create

Attached: my blog address