1、nil 、 NSNull

Nil: For objects, empty objects do not take up space, equivalent to a “whitewash”, back to the original state.

When we assign an object, we say object = nil, which means I want to get rid of this object; Or the object, for whatever reason, has been released multiple times, so the object reference counter is zero, and the system frees up this memory, and at that point this object is nil, so I call it a null object. (Note: I emphasize “empty object” here, I will compare it to “null object” below!!) So for an empty object, all operations on retain, such as adding keys to dictionaries or new elements to arrays, will crash

NSNull: for Pointers, both object Pointers and non-object Pointers are valid. Null takes no space.

The difference between NSNull and nil is that nil is an empty object that has completely disappeared from memory, and if we want to express the idea that we need to have a container that has nothing in it, we use NSNull, which I call a null-valued object. If you look at the development documentation, you’ll see that NSNull is a class that inherits NSObject, and it just has a “+ (NSNull *) null;” Class methods. This means that the NSNull object has a valid memory address, so any reference to it in the program will not crash the program.

2. The sandbox contains three directories: Documents, Library and Temp

(1) Documents: This directory is used to store user data. This path can be configured to share files in iTunes. ITunes or iCloud will back it up.

(2) Library: This directory has two subdirectories:

Preferences: Contains the Preferences file for the application. ITunes or iCloud will back it up.

Caches: Stores cached data that can be redownloaded or generated without affecting offline use. Cached data may be deleted when the device has low storage space. It won’t be backed up by iTunes or iCloud.

(3) TMP: This directory is used to store temporary files that are not needed during the application startup process. The system will delete files from the file periodically. Files in this path will not be backed up by iTunes.

3. Event delivery chain

First determine if the point is inside the View, and then iterate through the subViews

    – (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; 

Check if the point is inside the View

    – (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; 

       // default returns YES if point is in bounds

A: process

Alpha >0.01 2. UserInteractionEnabled == YES 3. Hidden = NO

2: Check whether the change point is inside the view.

3: If the child view is iterated then continue to return responsive views until there are none.

B: Common problems

The parent view is not clickable. Can the child view be clickable

No, the hit test ends when it reaches the parent view

Setting the child view to be unclickable does not affect the parent view

Overwriting the parent view does not affect clicking

The effect of gestures on the responder method

C: Practical usage

Click a circular control, how to achieve only click circular area effective

Overloading pointInside. In this case, the external points can also be judged as internal points, and vice versa

4. Processes and threads

(1) Threads move under the process (simple carriages cannot run)

(2) A process can contain more than one thread (a train can have more than one car)

(3) It is difficult to share data between different processes (passengers on one train can hardly change to another train, such as station transfer)

(4) It is easy to share data between different threads in the same process (it is easy to change from carriage A to carriage B)

(5) Processes consume more computer resources than threads (multiple trains consume more resources than multiple carriages)

(6) Processes do not affect each other, the failure of one thread will result in the failure of the entire process (one train will not affect another train, but if the middle car on one train catches fire, it will affect all trains)

(7) The process can be extended to multiple machines, and the process is suitable for multi-core at most (different trains can run on multiple tracks, and the carriages of the same train cannot run on different tracks).

(8) The memory address used by a process can be locked, that is, when a thread uses some shared memory, other threads must wait for it to end before they can use it. (train bathroom) -” Mutex”

(9) The memory address used by the process can be limited to the amount of memory used (e.g. the restaurant on the train, how many people are allowed to enter, if it is full, you have to wait at the door until someone comes out before entering) – “semaphore”

GCD queues are divided into two main types:

1. Concurrent queues

Multiple tasks can be executed concurrently (automatically enable multiple threads to execute tasks simultaneously)

Concurrency only works with asynchronous functions

Serial queue

Execution of one task after another (when one task is completed, the next task is executed)

Synchronous, asynchronous, concurrent, serial

Synchronization and asynchrony affect whether new threads can be started

Synchronization: Executes tasks in the current thread without the ability to start the thread

Asynchrony: Performs tasks in a new thread, with the ability to start a new thread

Concurrency and serialization affect: how tasks are executed

Concurrency: Multiple tasks are executed simultaneously

Serial: After one task is executed, the next task is executed

Objc_getClass and object_getClass

(1) Class objc_getClass(const char *aClassName)

1> Pass in the string class name

2> Return the corresponding class object

(2) Class object_getClass(id obj)

1> The obj passed may be an instance object, a class object, or a meta-class object

2 > the return value

(a) If it is instance, return the class object

If it is a class object, return a meta-class object

(c) If it is a meta-class object, return the meta-class object of NSObject

(3) – (Class) Class + (Class) Class

1> Returns the class object

                – (Class) {



                     return self->isa;



                 }

               + (Class) {



                      return self;



                 }

6, reflection

Reflection can be understood as a mechanism by which class names, method names, attribute names, and so on are converted to each other at run time

Essence – sends a message to Runtime, which then matches the actual method address based on the string name of the Class and the string name of the method, and executes. Again reflection uses strings to dynamically detect and convert at run time.

Advantages:

Decoupled, eliminating dependencies between classes

Disadvantages:

The code becomes less readable and complicates the original logic, which is not conducive to maintenance

Poor performance. Indirect memory hits using the reflection match string are slower than direct memory hits. 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 reflection is used in the core application logic where performance is critical, the performance issue becomes especially important.)

7. CADisplayLink and NSTimer

    CADisplayLink

Normally it is called at the end of each refresh, with a high degree of accuracy

The use of relatively specific, suitable for constantly redraw UI

    NSTimer

For example, when NSTimer triggers, if runloop is blocked, the trigger time will be delayed until the next runloop cycle

The range of use is much wider, all kinds of tasks that require single or cyclic timing processing can be used

8. IOS ——— Message forwarding mechanism

The mechanism of message forwarding is essentially three internal remediation opportunities

(1) Dynamic parsing uses runtime to dynamically add implementation code

                resolveInstanceMethod:



                resolveClassMethod:

(2) Fast forwarding is redirecting the recipient to find another class to forward the message to the object that can respond to the message for processing

                – (id)forwardingTargetForSelector:(SEL)aSelector {



                            return nil;



                    }

(3) Complete forward specified selector IMP pointing to the implementation code

                forwardInvocation

What does the _objc_msgForward function do? What happens when you call directly?

This function is called for method forwarding when the object does not implement a method. (A method corresponding to the IMP is not found, will return the IMP of this function to execute)

1. Call the resolveInstanceMethod: method to allow the user to dynamically add an implementation to the Class at this point. If there is an implementation, it is called and returned. If not, proceed with the following action.

2. Call forwardingTargetForSelector: method, trying to find a can respond to the message object. If it gets it, it forwards it directly. If nil is returned, proceed with the following action.

3. Call methodSignatureForSelector: method, trying to get a method signature. If not, call doesNotRecognizeSelector directly to throw an exception.

4. Call the forwardInvocation method, which wraps the method signature from step 3 into the Invocation Invocation.

If you call this method directly, even if the method you want to call is implemented, it will not be called and will go directly to the message forward step.

UI refresh is in the main thread

UIKit is not a thread-safe class. UI operations involve rendering access to properties of various View objects, which can cause read and write problems if done asynchronously, and locking it can be costly and slow.

UIApplication is initialized on the main thread, where all user events are delivered (click, drag), so a view can only respond to events on the main thread.

In terms of rendering, since image rendering requires simultaneous on-screen updates at a refresh rate of 60 frames, it is not certain that this process can achieve synchronous updates in the case of non-main-thread asynchronization. If you want to update the UI in a child thread, you must wait until the child thread finishes before submitting the update to the rendering service.

NSObject and ID

Id is a pointer.

NSObject * is a pointer to type NSObject.

Not all classes in Objective-C inherit from NSObject, there’s also the NSProxy class, so the scope of NSObject * is less than ID.

11, lock

Spin lock, mutex comparison –

Code execution is high, CPU is plentiful, mutex is available,

Low frequencies and complex code require mutex.

Spin-lock – The process waiting for the lock is in busy-wait state, occupying CPU resources all the time. The process is not secure, and priority reversal may occur

Spin locks are good for short wait times

Critical section code is often invoked, but contention rarely occurs

The CPU is not nervous

Multicore processor

Mutex – The thread waiting for the lock will sleep

The thread wait time is expected to be long

Single-core processor

Critical area IO operation

The critical section is more code, complex, or large loop

Critical sections are very competitive

Recursive locking – The same thread can be locked N times without causing a deadlock

Mutex: pthread_mutex_t mutex. Threads waiting for the lock will sleep.

NSLock: Encapsulates a mutex lock.

NSRecursiveLock: Encapsulates the mutex recursive lock, which can repeatedly lock the same thread.

NSCondition: Encapsulation of mutex and COND. The advantage is that dependencies can be formed between threads. The disadvantage is that there are no explicit conditions.

NSConditionLock: Further encapsulation of NSCondition

NSConditionLock can be used to resolve the problem if A depends on the completion of B and B depends on the completion of C

Dispatch_queue: special lock, directly using serial queue of GCD, can also achieve thread synchronization. A serial queue is a queue in which the tasks of a thread are executed in order to achieve the purpose of locking.

Dispatch_semaphore: controls the number of concurrent threads. The value of “dispatch_semaphore” is set to “1” and is used as a synchronous lock.

@synchronized: The object obj is locked. When using this lock, the underlying value calculated by the object is used as the key to generate a lock. Different resources can use different OBJ as the lock object.

Atmoic: Atomic operation. Adding the Atmoic modifier to a property ensures that both setters and getters of the property are atomic operations. This ensures that the interior of the setter and getter is thread synchronized. High atomic reads can cause threads to queue up, wasting CPU time

Read/write lock: pthread_rwlock(c encapsulated read/write lock)/asynchronous fence call dispatch_barrier_async

Sort performance from highest to lowest

                os_unfair_lock

                OSSpinLock

                dispatch_semaphore

                pthread_mutex

                dispatch_queue(DISPATCH_QUEUE_SERIAL)

                NSLock

                NSCondition

                pthread_mutex(recursive)

                NSRecursiveLock

                NSConditionLock

                @synchronized

It is recommended to use NSLock and semaphore. The simplest is @synchronized, which is used without declaration and initialization.

conclusion

A normal thread lock is essentially synchronous execution

Atomic operations limit only setter and getter methods, not member variables

Read and write lock performance can be pthread_rwlock_t and dispatch_barrier_async

Four necessary conditions for deadlocks

Mutually exclusive: Only one process can access a resource at a time. That is, once the resource is allocated to a process, other processes cannot access the resource until the process finishes accessing it.

Hold and wait: a process has a resource (one or more) and is waiting for other processes to release the resource.

3, do not preempt: others have occupied a resource, you can not because you also need the resource, to take over the resources of others.

Circular waiting: there is a chain of processes so that each process has at least one resource required by the next process.

12, optimization

CPU

Try to use lightweight objects, such as CALayer instead of UIView, for places that don’t handle events

Don’t make frequent calls to UIView properties such as frame, bounds, Transform, etc., and minimize unnecessary changes

Try to calculate the layout in advance, adjust the corresponding attributes at one time if necessary, do not modify the attributes more than once

Autolayout consumes more CPU resources than setting the frame directly

The image size should be exactly the same as the UIImageView size

Control the maximum number of concurrent threads

Try to put time-consuming operations into child threads

Text processing (size calculation, drawing)

Image processing (decoding, rendering)

GPU

Try to avoid the display of a large number of pictures in a short period of time, as far as possible to display a composite of multiple pictures

The maximum texture size that GPU can process is 4096×4096. Once the texture size exceeds this size, IT will occupy CPU resources for processing, so the texture size should not exceed this size

Minimize the number of views and levels

Reduce transparent views (alpha<1) and set Opaque to YES for opaque views

Try to avoid off-screen rendering

It makes sense to choose imageNamed and image with content file

ImageNamed caches images and is good for using an image multiple times

ImageWithContentsOfFile loads image files from the bundle, does not cache, and is suitable for loading a large image that is used only once, such as a bootstrap image

13, [self class] [super class]

1. The first two methods send messages to self with the names class and superclass, which obviously result in viewing your own type and the type of the parent class

2. The last two methods also send messages to self, but query the class and superclass methods from the parent class, both of which are present in NSObject

The receiver of the message is also self, and the method called is the same, so the result is its own type and the parent type

14. Basic functions of RunLoop

1. Keep the program running continuously

2. Handle various events in the app (such as touch events, timer events, selector events)

3, save CPU resources, improve program performance, have things to do things, have no things to rest

Mode function – Specifies the priority of the event in the running Loop. Threads need different modes to run, to respond to different events, to handle different situational patterns. (For example, when you can optimize the TableView, you can set UITrackingRunLoopMode not to perform some operations)

Dealloc consists of the following steps

C++ destructor (c++ destructor is used to clean up objects before they are deleted)

2. Associated objects (such as using Runtime to associate variables in a classification) are removed and stored in a hash table

Weak pointer set to nil; weak pointer set to nil; weak pointer set to nil; weak pointer set to nil

Note that the -dealloc method is invoked on the thread where the object reference count is zero, so it is not necessarily executed on the main thread

16、SideTables 、 SideTable

In the Runtime memory space, SideTables is an 8-element hash array of length 64 that stores the SideTable. The hash key of SideTables is the address of an object obj. An OBJ corresponds to a SideTable. But one SideTable is going to have multiple OBJs. Since there are only 64 sidetables, many OBJs share the same SideTable

In a SideTable, the members:

spinlock_t slock ; // Spin lock, used to lock/unlock SideTable. RefcountMap refcnts; // Object reference count related map (hash map, where key is obj’s address, and value, Weak_table_t Weak_table; weak_table; weak_table; weak_table; weak_table; // Hash table containing the address of a weakly referenced pointer to obj as key and the address of a weakly referenced pointer to obj as value

The Runtime maintains a weak table that stores all the weak Pointers to an object. The weak table is a hash table where Key is the address of the pointer to the weak object and Value is an array of addresses of the pointer to the weak object.

1. Initialization: The Runtime calls the objc_initWeak function and initializes a new weak pointer to the address of the object.

2. When adding a reference: the objc_initWeak function will call objc_storeWeak(), which updates the pointer pointer and creates the corresponding weak reference table.

3. When releasing, call the clearDeallocating function. The clearDeallocating function first fetches an array of weak pointer addresses based on the object’s address, then iterates through the array to set it to nil, deletes the entry from the Weak table, and clears the object’s record.

Load and Initialize

        +load

The +load method is called when the Runtime loads the class or class

2. The +load of each class and category is called only once during the running of the program

3. Call order

(1) Call class +load first

Call in compile order (compile first, call first)

(2) the +load of the subclass will be called before the +load of the parent class

(3) Call the +load of the classification again

Call in compile order (compile first, call first)

+ the initialize

The + Initialize method is called the first time the class receives a message

2. Call order

Call +initialize from parent class and +initialize from subclass

(First initialize the parent class, then initialize the child class, each class is initialized only once)

The difference between:

+initialize is called via objc_msgSend, so it has the following characteristics:

If the subclass does not implement +initialize, +initialize of the parent class will be called (so +initialize may be called multiple times).

If the class implements +initialize, override the class’s own +initialize call

18, the Category,

Realize the principle of

1. After Category compilation, the underlying structure is struct category_t, which stores classified object methods, class methods, attributes, and protocol information

2. When the program runs, the Runtime merges the Category data into the class information (class object, metaclass object).

The difference between Category and Class Extension

1. When Class Extension is compiled, its data is already included in the Class information

2. Category data is merged into the class information at runtime

19. Do you want to add instance variables to compiled classes? Can I add instance variables to classes created at run time?

1. You cannot add instance variables to compiled classes

2. Can add instance variables to classes created at run time

Explanation:

1. The compiled class has been registered with the Runtime. The linked list of objc_iVAR_list instance variables and the memory size of instance_size instance variables in the class structure have been determined. The Runtime calls class_setVARLayout or class_setWeaklvarLayout to handle strong weak references. You cannot add instance variables to existing classes

2. Create classes at runtime that can add instance variables and call class_addIvar. But after calling objc_allocateClassPair, before objc_registerClassPair, for the same reason.

20. Page loading rate

The time it takes the viewController to get from the first line of ViewDidLoad to the last line of viewDidAppear

21, AutoreleasePool AutoreleasePage

An AutoreleasePoolPage belongs to a thread. A thread can have multiple AutoReleasepoolPages

AutoreleasePoolPage has the following underlying structure:

AutoreleasePoolPage is a bidirectional linked list composed of stacks. Following the fifo rule, the automatic release pool consists of a series of AutoreleasepoolPages that are connected in a bidirectional linked list.

Auto-release pools correspond one to one with threads;

Each AutoreleasePoolPage object takes up 4096 bytes of memory, 56 bytes for its internal member variables, and the remaining space (4040 bytes) for the address of the AutoRelease object. Note that there are only 504 objects on the first page, because a POOL_SENTINEL is inserted at the next location when the page is created.

POOL_BOUNDARY is the sentry object that is inserted on the stack and released on the stack

Each page stores a next pointer to the location of the next autoreleased object.

Each page contains a parent node and a child node, pointing to the previous and next pages respectively. The parent node of the first page is nil, and the child node of the last page is nil.

Each page is marked with a depth value of 0 on the first page and incremented by 1 on subsequent pages.

Each page also contains the current thread and the maximum number of pushes.

AutoreleasePool has the following memory structure:

(1) Automatic release pool is a stack structure, which is a bidirectional linked list with AutoreleasePoolPage as nodes. Pages can be dynamically added or deleted as required.

(2) The size of each AutoreleasePoolPage is 4096 bytes, and the address stores Pointers to page members, sentinels, and objects in ascending order. Where, its member occupies 56 bytes, and there will only be one sentinel in the release pool as the boundary of the object pointer, so:

Page 1, internal storage: page members + 1 sentinel + 504 object Pointers.

Other pages, internal storage: page members + 505 object Pointers.

(3) Full pages are marked as full page, and the current page is marked as hot Page.

(4) AutoreleasePoolPage inherits from AutoreleasePoolPageData, and its internal members are as follows:

Magic: Verifies the integrity of the AutoreleasePoolPage structure.

Next: The location of the next newly added Autoreleased object, initialized to point to begin().

Thread: indicates the current thread, indicating that the automatic release pool is associated with the thread.

Parent: refers to the parent node, i.e. the previous page, and the parent value of the first page is nil.

Child: Points to the child node, the next page, and the last page has a child value of nil.

Depth: indicates the page depth. The value starts from 0 and increases by 1.

Hiwat: high water mark, indicating the maximum number of stacks

POOL_BOUNDARY:

It’s just an alias for nil. In previous lives, POOL_SENTINEL is called a sentinel object or a boundary object;

POOL_BOUNDARY is used to distinguish between different auto-release pools to solve the problem of auto-release pool nesting

Whenever an autofree pool is created, the push() method is called to push a POOL_BOUNDARY onto the stack and return its memory address;

When an autorelease object is added to the autorelease pool, the memory address of the autorelease object is pushed, preceded by at least one POOL_BOUNDARY;

When an autofree pool is destroyed, the pop() method is called and a POOL_BOUNDARY is passed, starting with the last object in the autofree pool, and release messages are sent to each of them until the POOL_BOUNDARY is encountered

22, the ARC

When it is about to go out of scope, the compiler calls a release for all variables identified by __strong

Weak is also called weak reference. Weak reference means that no object is held. When the referenced object is destroyed, this variable is automatically set to nil

Even using alloc/new/copy/mutableCopy created object, also does not hold, the result is this object no one wants, so comes out is destroyed

Note – objects created by other than these four methods are not destroyed because an __weak flag has been created, but are not destroyed until the autoReleasepool is exceeded.

SizeThatFits, sizeToFit

SizeThatFits: will calculate the optimal size, but will not change its size;

SizeToFit: calculates the optimal size and changes its size.

There is also a difference when the Label text is too long to be displayed on a single line

24, SEL IMP

SEL – selectors, which represent method/function names and have the same underlying structure as char *

This can be obtained via @selector() and sel_registerName()

You can convert it to a string by sel_getName() and NSStringFromSelector()

Method names with the same name in different classes correspond to the same method selector

IMP – the concrete implementation of the function

25, the installation package thin

Ipa is mainly composed of executable files and resources

1. Resources (pictures, audio, video, etc.)

Take lossless compression

Remove unused resources: github.com/tinymind/LS…

2. Thin executable files

Compiler optimization

Strip Linked Product, Make Strings read-only, Symbols Hidden by Default set to YES

Remove exception support

Enable C++ Exceptions, Enable Objective-c Exceptions set to NO, Other C Flags add -fno-exceptions

Use AppCode (www.jetbrains.com/objc/) to detect unused… -> Code -> Inspect Code

Write the LLVM plug-in to detect duplicate code, uncalled code

Original: www.jianshu.com/p/351b5d583…