The first part

IOS based

Retain, copy, mutablecopy, weak, assign, strong

1). Getter =getterName, setterName =setterName, setterName =setterName 2). Retain, setters release the old value and retain the new value. Setters release the old value and retain the new value. Copy, setter method copy, same as retain process, old value release, copy new object, retainCount is 1. This is a mechanism introduced to reduce dependency on context. 6). Nonatomic access, no synchronization, multi-threaded concurrent access will improve performance. Note that without this attribute, both access methods are atomic transaction access by default. The lock is added to the instance level of the owning object.

  • One is the representation of atomicity

Atomic only guarantees thread-safe access to getter and setter methods, but does not guarantee thread-safe access to the entire object, so in multithreaded programming, thread-safety needs to be handled by the developer himself. About selection: Getters and setters generated by atomic systems guarantee the security of GET and set operations, but atomic is more expensive and slower than nonatomic. Therefore, on small devices such as iphones, if there is no communication between multiple threads, nonatomic is used A better choice

Because getter/setter methods are locked, the current operation is performed before another thread can read or write the property.

  • “Assign” (previously used unsafe_unretained in iOS5),strong,weak, and copy.

Assign: Assign is used for non-pointer variables. It is generally used for basic types and C data types. These types are not objects and are managed by the system stack. Weak: A weak reference to an object. It does not increase the reference count of the object and does not hold the object. After the object is destroyed, it is set to nil to prevent wild Pointers. **strong: a strong reference to an object increases the reference count of the object. If it points to an empty object, it will result in a wild pointer. **retain: ** Declaring attributes with strong or retain has the same effect (more developers seem to prefer strong). However, when declaring blocks, using strong and retain can have very different effects. Retain is equal to assign **copy: ** creates a new object with a reference count of 1. Assignment makes a copy of the value passed in, so when you use the copy keyword, you copy an object to the property. Instead of holding the object, the property creates a new object and copies the value of that object to it. Objects that use the copy keyword must implement the NSCopying protocol. **unsafe_unretained: ** Similar to weak, we declare a weak reference, but when the reference count is 0, the variable is not automatically set to nil. Weak is still used.

  • There are read and write permissions, which default to readWrite, and readonly, which you declare when you want to expose properties that can’t be modified by outsiders.

  • Atomicity — nonatomic qualities

By default, methods synthesized by the compiler ensure atomicity through a locking mechanism. If the property is nonatomic, spin locks are not used. Note that although there is no quality called "atomic" (if a property is not nonatomic, it is atomic), you can still specify this in the attribute quality and the compiler will not report an error. If you define your own access methods, you should adhere to atomicity consistent with the attributes. Read/write permission -- ReadWrite and readonly Memory management semantics --assign, strong, weak, unsafe_unretained, and copy method name --getter=<name> , the setter = < name >Copy the code
  • The essence of @property is instance variable (IVar) + access method (getter + setter), that is, @property = IVar + getter + setter;

    Properties, as a feature of Objective-C, encapsulate data in objects. Objective-c objects typically store the data they need as various instance variables. Instance variables are typically accessed through an “access method.” Getters are used to read variable values, and setters are used to write variable values.

  • Ivar, getters, and setters are automatically synthesized in this class

    Once the attributes are defined, the compiler automatically writes the methods needed to access them, a process called autosynthesis. It is important to note that this process is implemented by the compiler at compile time, so the source code for these synthesized methods is not available in the editor. In addition to generating getters and setters for the method code, the compiler automatically adds instance variables of the appropriate type to the class and precedes the attribute names with an underscore as the name of the instance variable. In the previous example, two instance variables are generated with names _firstName and _lastName. You can also specify the name of an instance variable in the class implementation code by using the @synthesize syntax.

2, sandbox directory structure, store data

Sandbox structure:

  • Application: Stores Application source files, which must be digitally signed before being uploaded and cannot be modified after being uploaded.
  • Documents: Common directory, which stores important data (such as personal Settings) generated by an application during runtime that needs to be stored for a long time. –iCloud backup directory
  • Caches: To store bulky data that doesn’t need to be backed up. (Common cache path)–iCloud Non-backup directory 2.Preference: User Preference directory. Use NSUserDefault to read and write –iCloud backup directory.
  • TMP: Stores temporary files. Data in this directory can be deleted at any time -iCloud non-backup directory.

3. Reuse principle of TableView

  • The reuse mechanism mainly uses a mutable array visibleCells and a mutable dictionary type reusableTableCells, where visiableCells stores the cells displayed by the current UITableView. ReusableTableCells are used to store cells that have been cached with ‘identify’. When UITableView scrolls, reusableTableCells will check if there is a cached cell by identify. If there is a cached cell by identify, it will not initialize it.

4. Difference between bounds and frame

  • Frame: Position and size of a view in the superview coordinate system. (The reference point is the superview’s coordinate system)
  • Bounds: The position and size of a view in its own coordinate system. (The reference point is its own coordinate system)

Setting the bounds allows you to change the origin position of your own coordinate system, which affects the display position of its “child view.”

5. Memory management

Memory allocation

First of all, since we need to manage memory, we need to know how and where memory is allocated. In iOS, data exists in the heap and on the stack, whereas our memory management manages the memory on the heap, not the memory on the stack.

  • Non-oc objects (underlying data types) are stored on the stack
  • OC objects are stored on the heap

Memory management in OC is also referred to as reference counting — a memory management technique in computer programming languages.

What is reference counting

When we create a new object, the reference count to 1, when there is a new pointer to the object, we will be the reference count of 1, when a pointer pointing to the object no longer, we will be the reference counting minus 1, when the object reference count becomes zero, this will no longer be any pointer to the object, At this point we can destroy the object and reclaim memory.

Memory Management mode

In the case of manual Reference counting (MRC) or Automatic Reference counting (ARC), Objective-C adopts the memory management mode of reference counting, which has the following characteristics:

Self generated objects, own. Objects that are not generated by themselves can be held by themselves. Release when you no longer need to hold objects yourself. Objects that are not owned by you cannot be released. ARC automatically manages reference counts

MRC

In MRC mode, the developers manage the memory manually, which often takes up a lot of time and energy for developers to debug projects. Based on this situation, Apple proposed automatic reference Counting (ARC) at WWDC in 2011.

ARC

ARC is also based on reference counting, relying on the compiler’s static analysis capabilities, Automatically insert appropriate memory management code (retain, Release, copy, AutoRelease, autoreleasepool) into existing code at compile time and do some optimizations at Runtime. IOS development is now based on ARC, so developers don’t need to think about memory management for the most part. Individual cases include:

  • The underlying Core Foundation objects are not managed by ARC, so you need to manually manage the reference count for these objects.
  • Also, in the case of circular citation, the reference count will never be reduced to 0 because objects are strongly referenced to each other, so you need to actively disconnect the circular reference so that the reference count can be reduced.
Ownership modifier

To handle objects in Objective-C programming, variable types can be defined as id types or various object types. The id type and object class in ARC must have an ownership modifier attached to their type. There are four ownership modifiers: __strong __weak __unsafe_unretaied __autoreleasing

  • __strong indicates a strong reference, corresponding to the strong used in defining property. When an object does not have any strong references to it, it is released. If a reference is declared without a modifier, it defaults to a strong reference. When you want to release strong references to objects, you need to ensure that all strong references to objects are set to nil. The __strong modifier is the default ownership modifier for ID types and object types.

  • __weak indicates a weak reference, corresponding to the weak used in defining property. Weak references do not affect the object’s release, and when an object is released, all weak references to it are set to nil, preventing wild Pointers. Variables decorated with __weak are used with objects registered in autoreleasePool. One of the most common uses of __weak is to avoid loops. Note that the __weak modifier can only be used with iOS5 and older. Instead, use the __unsafe_unretained modifier for iOS4 and later.

  • __unsafe_unretained

ARC was introduced in iOS5, and the __unsafe_unretained modifier was primarily intended to be compatible with iOS4 and older systems when ARC was first released, because they didn’t have weak references. This modifier is unsafe_unretained when defining a property. The __unsafe_unretained modifier pointer points purely to the object without any additional operations. Holding the object makes the retainCount +1. And when the object is released it still points to the original address of the object, it’s not automatically set to nil, so it’s a wild pointer, very unsafe.

  • __autoreleasing

Assigning an object to a variable with the __autoreleasing modifier is the same as calling the object’s autorelease method in MRC.

Memory management issues – Circular references

What is a circular reference? A circular reference is when two objects become strongly referential to each other, and the reference count is increased by one, so that the object can never be released. This creates a memory leak. The two situations where circular references are most likely to occur are Delegate and Block. Therefore, the concept of weak reference is introduced to modify the object. The weak keyword is used to modify the object. The reference count of the object will not +1, and the referenced object will be set to nil when the object is released. This weak reference does not increase the reference count of the object by 1. When the reference count of the object goes to 0, the system uses this table to find all weak reference Pointers and sets them to nil. The weak table is a hash table maintained by the Runtime to store all Pointers to an object that is weak. Key is the address of the pointed object and Value is the address array of the weak pointer (the Value of which is the address of the pointed object pointer). Currently, the root cause of a memory leak in an ARC environment is a circular reference in the code that prevents some memory from being freed and ultimately prevents the dealloc() method from being called. So memory management in ARC is all about finding these memory Leaks, and Instrument provides tools like Allocations/Leaks to detect memory Leaks. IOS memory leak detection method and cause analysis

conclusion

Memory management for iOS developers has been greatly reduced with the help of ARC, but we still need to understand the advantages and common problems of reference counting as a way of managing memory, especially with circular references. There are two main solutions to the circular reference problem: one is to actively break the circular reference, and the other is to avoid the circular reference by using weak reference. For Core Foundation objects, since they are not managed by ARC, we still need to continue managing reference counts manually. Instruments is a great tool for debugging memory problems, and using Instruments saves us a lot of debugging time.

6. Security singleton

In order to ensure the uniqueness of the singleton, we should intercept it in the Alloc phase. When we call the alloc method, the OC will call the allocWithZone method to allocate memory. We override this method and then call the shareInstance method in this method to return the singleton. Copying objects works the same way, overwriting the copyWithZone method and then calling the shareInstance method in that method to return a singleton.

#import "Single.h" static Single *single = nil; @implementation Single +(instancetype) shareInstance{ static dispatch_once_t onceToken ; dispatch_once(&onceToken, ^{ single = [[super allocWithZone:NULL] init]; }); return single ; } +(id) allocWithZone:(struct _NSZone *)zone{ return [Single shareInstance] ; } -(id) copyWithZone:(struct _NSZone *)zone{ return [Single shareInstance] ; } @endCopy the code

7. Stack differences

  • Structurally

Stack: A stack is a data structure that extends to a lower address and is a contiguous area of memory. Heap: A heap is a data structure that extends to a high address and is a discontinuous area of memory. Because the system uses a linked list to store the free memory address, it is naturally discontinuous, and the traversal direction of the list is from low address to high address. The size of the heap is limited by the amount of virtual memory available in the computer system. Thus, the heap is more flexible and larger.

  • According to management
For the stack, it is managed automatically by the system compiler and does not need to be managed manually by the programmerCopy the code

In the case of the heap, the release work is manually managed by the programmer, not timely collection can cause memory leaks

  • According to the way of distribution

The heap allocates and reclaims memory dynamically. Stacks without static allocation can be allocated in one of two ways: Static allocation and dynamic allocation Static allocation is done by the system compiler, such as the allocation of local variables dynamic allocation is allocated by the alloc function, but stack dynamic allocation is different from the heap, its dynamic allocation is also released by the system compiler, does not need to be manually managed by the programmer

The difference between

  • A heap is a sorted tree data structure, with each node having a value; The heap is commonly used to implement priority queues, which are accessed at will.
  • A stack is a linear data structure with lifO (last in, first out), also known as lifO (last in, first out) linear table, which is limited to insert and delete operations at the end of the table.

A: Management mode: for the stack, it is automatically managed by the compiler without our manual control; In the case of the heap, the release is controlled by the programmer, leading to memory leaks. Application size: Stack: Under Windows, a stack is a data structure that extends to a lower address and is a contiguous area of memory. The address at the top of the stack and the maximum size of the stack are specified by the system. Under WINDOWS, the stack size is 2M (or 1M). If the stack size exceeds the available space, overflow will be prompted. Because of this, less space can be obtained from the stack. Heap: A heap is a data structure that extends to a high address and is a discontinuous area of memory. This is because the system uses a linked list to store the free memory address, which is naturally discontinuous, and the traversal direction of the list is from low address to high address. The size of the heap is limited by the amount of virtual memory available in the computer system. Thus, the heap is more flexible and larger. Fragmentation problem: For the heap, frequent new/ DELETE will inevitably lead to discontinuous memory space, resulting in a large amount of fragmentation, making the program inefficient. For stacks, this is not a problem, because stacks are first-in, last-out queues, and they are so one-to-one that there can never be a block of memory popping out of the stack: the heap is dynamically allocated, there is no statically allocated heap. There are two types of stack allocation: static allocation and dynamic allocation. Static assignment is done by the compiler, such as assignment of local variables. Dynamic allocation is done by the Alloca function, but stack dynamic allocation is different from heap dynamic allocation, which is released by the compiler without manual implementation. Allocation efficiency: the stack is a data structure provided by the machine system, and the computer provides support for the stack at the bottom: special registers are allocated to store the address of the stack, and special instructions are executed for pushing and removing the stack, which determines the high efficiency of the stack. The heap is provided by the C/C++ library, and its mechanism is quite complex.

introduce

The heap

  • A heap is a sorted tree data structure, with each node having a value. The data structure of a heap is usually a binary tree. So a heap in a data structure can often be thought of as an array object of a tree. And the heap needs to satisfy the following two properties:

    1) The value of a node in the heap is always no greater than or less than its parent;

    2) The heap is always a complete binary tree.

  • There are two types of heap, maximum heap and minimum heap. The heap with the largest root node is called the maximum heap or the large root heap, and the heap with the smallest root node is called the minimum heap or the small root heap. In a minimum heap of placed elements, the elements in the parent node must be smaller than the elements in the children, but there is no rule on the size of the left and right nodes.

  • Heap are commonly used to implement a priority queue, access to heap is random, it’s like we of the bookshelf in the library book, although the book put is sequential, but we want to take any one don’t have to be like a stack, first take out in front of all the books, bookshelves this mechanism is different from the box, we can directly take out we want to book.

The stack

  • A stack is a linear table that limits insert and delete operations to the end of the table. We call the end that allows insertion and deletion the top of the stack, the other end the bottom of the stack, and the stack that does not contain any data elements the empty stack. The special thing about the stack is that it limits where this linear table can be inserted and deleted; it always happens at the top of the stack.

  • Stack is a data structure with LIFO (Last In First Out), also known as LIFO (Last In First Out). In other words, it is similar to removing the object that was placed at the bottom of the box (the object that was put in earlier) and removing the object that was placed on top of it (the object that was put in later).

  • Some operations are defined in the stack. The two most important ones are PUSH and POP. The PUSH operation adds an element to the top of the stack. The POP operation, in contrast, removes an element at the top of the stack and decreases the stack size by one.

  • Application of stack – recursion

The queue

  • A queue is a linear table that allows only an insert at one end and a delete at the other. The end that allows insertion is called the tail, and the end that allows deletion is called the head. It is a special type of linear table, special in that it allows only delete operations at the front of the table and insert operations at the back of the table. Like a stack, a queue is a linear table with limited operations.

  • Queue is a FIFO (First In First Out) data structure, also called FIFO (First In First Out) linear table. That is to say, those put in first come out first, those put in later come out later, just like when luggage goes through security check, those put in first always come out first at the other end, and those put in last come out at the back.

8. The difference between arrays and lists

  • Array: ordered, subscript values, contiguous memory.

Find: So using subscript values (because memory is contiguous, and the size of the storage unit is known, so you can quickly locate the memory address where the subscript is located) can be found quickly, much faster than linked lists. Insert: But to insert, you need to move all the memory addresses behind the subscript one cell back. So if the insert is not at the end and there’s a lot of data, it’s slower than a linked list. But: arrays in OC are optimized for this with a ring buffer, which can be calculated to move the least amount of memory. For example, if it is close to the beginning, the memory of the head is moved; If you get close to the tail, you move the memory in the tail. The circular buffer is implemented by linked lists.

  • Linked list: ordered, this node stores the address of the next node, memory is not contiguous (cannot use subscript value).

Lookup: Can only be searched from scratch, so lookup is slower than array. Insert: The cost of insert is very low. You only need to interrupt two nodes to insert and reconnect, and it has no impact on other unrelated nodes. Faster than an array.

  • So, for the most part in app development, arrays are stronger and more appropriate than linked lists, which is probably why linked lists are rarely used.

Advantages and disadvantages of arrays, linked lists, and hashes

The second part

IOS has a deeper problem

1. When are the load and initialize methods called

The load method is called when the class or class is loaded into the Runtime. 2. The load method is called only once; If a class does not implement a load method, its parent class’s load method will not be called. This method is called when the class object is generated for the first time. Initialize may be called multiple times. (if the subclass does not implement the initialize method, the subclass will call the initialize method of its parent class first when receiving the message.)

  • Both the load and Initialize methods are called before the object is instantiated, with the main function being called before and the initialize function after. These two methods are called automatically; you cannot call them manually.
  • The load and Initialize methods do not explicitly call the parent class’s methods, but are called automatically, even if the subclass does not have an initialize method. The load method does not call the parent class.

The load Method is usually used for Method Swizzle and the Initialize Method is used to initialize global or static variables.

  • The Load and Initialize methods use locks internally, so they are thread-safe. Keep the implementation as simple as possible, avoid blocking threads, and stop using locks

2, response chain, event transmission

Responder Object (UIResponder)
  • Learning about touch events starts with an important concept – the responder object (UIResponder).

Not every object in iOS can handle events, only objects that inherit from UIResponder can accept and handle events, which we call “responder objects.” All of the following are inherited from UIResponder, so they can receive and handle events.

Occurrence of an event
  • When a touch event occurs, the system adds the event to a uiApplication-managed event queue. Why queue instead of stack? Since queues are characterized by FIFO, first in, first out, first-generated events are processed first, so events are added to queues.
  • UIApplication pulls the uppermost event from the event queue and dispatches the event for processing, usually first to the application’s main window (keyWindow).
  • The main window will find the most appropriate view in the view hierarchy to handle the touch event, which is the first step in the event processing process.

When the appropriate view control is found, the view control’s Touches method is called for specific event handling.

Event passing
  • Touch events are passed from parent control to child control
UIApplication-> Window -> find the best view to handle the eventCopy the code

Note: If the parent control cannot accept touch events, then the child control cannot receive touch events

  • The process of finding the right view

1. First determine whether you can receive touch events. HitTest :withEvent: does not return nil. Cannot receive events: 1, userInteractionEnabled = NO 2, hidden 3, transparency <0.01). 2. Determine if the touch point is on your body. (pointInside method). 3. The child control array is traversed in reverse order, that is, from the top down, and the child control repeats the first two steps. 4. If there is no child control that matches the condition, then it considers itself the most appropriate view to handle the event. (hitTest:withEvent: return self) ###### event response

  • When we pass the event, we first see if the view handles the event, and if it handles it, we handle it and stop the event’s upward response (touches, slides, touches…). If not, the event is passed to its parent view (the superView of the view); If the superior view still cannot be processed, it will continue to be passed up; All the way to The Window, if the Window still can’t handle the event, it continues to be passed to the application, and if the Application still can’t handle the event, it is discarded.

# # # # # #

  • 1. Click on A UIView or generate A touch event, which is added to the event queue managed by UIApplication (that is, UIApplication receives the event first).

2.UIApplication fetches the uppermost event (say touch event A) from the event pair column and passes event A to the application’s main window (keyWindow). 3. The window will find the most appropriate view in the view hierarchy to handle touch events. (At this point, step 1 is complete.)

  • The responder chain

The response chain starts with the most appropriate view and passes the processing event to the next responder. The responder chain passes the event in the opposite way. If all responders do not process the event, the event is discarded. We usually use the responder chain to get the next few levels of responder, which is the nextResponder method of UIResponder.

(1) If part of a button is out of range of the parent control and cannot respond to clicks, what should I do if I want it to respond to clicks

IOS UIButton click on a button response outside the scope of the parent control Override button parent view – (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method

  • (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{//if should be, when the touch point is outside the superview part, but in the button part if (…..) { return YES; } return NO;

}

3, Runtime, ISA pointer, application scenarios

IOS Runtime Runtime overview iOS Runtime Runtime overview

A quick summary of Runtime
  • The Runtime is precisely a set of APIS implemented by C, C++, and assembly. Runtime is a Runtime library written in C++ that adds object-oriented capabilities to C, an important feature that distinguishes C from static languages such as C, where function calls are made at compile time and executed sequentially after compilation. OC is a dynamic language (polymorphic and Runtime), function calls are messages, and it is not known at compile time which function is called, so Runtime is the problem of the Runtime finding which method to call

Polymorphism: Polymorphism in OC refers to the different response ways of different objects to the same message. The subclass changes the implementation of the same method by rewriting the methods of the parent class to reflect polymorphism

Summary: The three ability start addresses are struct Pointers to ISA and can all be considered objects in objC

1. Object-oriented ability (inheritance, encapsulation, polymorphism)

2. Load class information dynamically and distribute messages (ISA horizontal search, inherit vertical search, and call _objc_msgForward for message forwarding if the search fails)

Message forwarding 1. Dynamic method resolution and dynamic method addition 2. Alternate receiver 3. Complete message forwarding 4. Exception throwing order: Instance — >class — >method — >sel — (Cache) — > IMP — >sel — >sel — (Cache) — > IMP — >sel — >sel — IMP is value. During compilation, a unique int identifier is generated based on the method name, which is the SEL identifier. IMP is the function pointer to the final function implementation. The runtime core is the objc_msgSend function, which sends a message to SEL to find a matching IMP

Runtime- Runs the system to dynamically create classes and objects, messaging, and forwarding. The core is that the Messaging OC code is eventually converted into runtime code by the compiler, and the function call mode is determined by the Messaging mechanism, which is also the basis for the use of OC as a dynamic language.

Runtime messaging
  • The system first finds the receiving object of the message and then finds its class through the object’s ISA.
Look for method_list in its class, and see if there's a selector. If not, look for the parent's method_list. Find the corresponding method and execute its IMP. Forward IMP return value.Copy the code
Runtime Message Forwarding

As described earlier, sending a message searches the list of methods in the relevant class object, and if none is found, searches up the inheritance tree to the root of the inheritance tree (usually NSObject). If still can’t find and forward failed returned to perform doesNotRecognizeSelector: method to unrecognized selector that wrong. So what exactly is message forwarding? The last three opportunities will be described one by one.

  • Dynamic method parsing

First, the Objective-C runtime calls +resolveInstanceMethod: or +resolveClassMethod:, giving you the opportunity to provide a function implementation. If you add the function and return YES, the system will restart the message sending process at runtime. If the resolve method to return NO, runtime will move to the next step: forwardingTargetForSelector.

  • Alternate receiver

Implements – forwardingTargetForSelector: if the target object, the Runtime will call this method at this moment, give you the opportunity to put forward this message to other objects.

  • Full message forwarding

If you could not handle unknown messages in the previous step, the only thing you can do is enable the full message forwarding mechanism. First of all, it will send – methodSignatureForSelector: message function parameters and return values of the type. If – methodSignatureForSelector: returns nil, the Runtime will send – doesNotRecognizeSelector: news, program will hang up now. If a function signature is returned, the Runtime creates an NSInvocation object and sends a -Forward Invocation: message to the target object.

Isa pointer
  • Isa: isa pointer to a Class. The reason why isa isa pointer is because Class isa pointer to the objc_class structure, and isa is its only private member variable. That is, all objects have isa Pointers.

Object definition in Objective-C:

struct objc_object {
    Class isa;
};
typedef struct objc_object *id;
Copy the code
  • Here you see the familiar id, which is used to perform operations similar to generics in C++. Objects of this type can be converted to any object. Here ID is defined as a pointer to objc_Object. Objc_object is the definition of a common object. It contains only one ISA pointer. That is, the only information an object holds is the address of its Class. When we call a method on an object, it finds the corresponding objc_class through ISA and then executes the method we called in objc_class’s methodLists.
The Runtime application

The Runtime is a great tool for building large frameworks. There are many application scenarios, and the following are some common ones.

  • Objective-c Associated Objects add attributes to a classification
  • Method Swizzling adds and replaces and KVO implementations
  • Message forwarding (Hot update) Fixes bugs (JSPatch)
  • NSCoding automatic archiving and automatic file solution
  • Implement automatic transformation of dictionaries and models (MJExtension)

4, kvo

KVO- Key value observation mechanism, the principle is as follows:

  • 1. When adding KVO to class A, use RuntimeAPI to dynamically generate A subclass and have instance object’s ISA point to the new subclass
  • 2. When modifying the instance object’s properties (rewrite surveillance attribute setter method, within the setter method calls the Foundation), invokes the Foundation _NSSetObjectValueAndNotify function
  • 3. _NSSetObjectValueAndNotify willChangeValueForKey will first call function within a) b) and then to the property assignment set method (call) c) finally call didChangeValueForKey d) The didChangeValueForKey method internally calls the observer’s observeValueForKeyPath to tell the listener that the property value has changed.
  • 4. Rewrite dealloc to do some KVO memory freeing
kvc

When an object calls the setValue method, the following operations are done inside the method: Check if there is a set method for the corresponding key, and call the set method if there is. 2). If the set method does not exist, it looks for an underlined member variable with the same name as key, and if it does, it assigns the value directly to the member variable attribute. 3). If _key is not found, the attribute key of the same name will be looked for, if there is a value directly assigned. 4). If you haven’t found, the call to valueForUndefinedKey: and setValue: forUndefinedKey: method. The default implementation of these methods is to throw exceptions, and we can override them as needed.

Runloop, timer, and Perform delays are invoked in child threads

What is RunLoop RunLoop

  • A RunLoop is essentially an object-oriented mechanism for handling events and messages. It is an object. It is essentially a do-while loop, and the usual code logic looks like this:
function loop() { initialize(); do { var message = get_next_message(); Process_message (message); process_message(message); // If there are events/messages, process} while (message! = quit); }Copy the code
  • This model is often referred to as the Event Loop. Event Loop is implemented in many systems and frameworks, such as Node.js Event processing, Windows message Loop, and OSX/iOS RunLoop. The key points to implement this model are how to manage events/messages and how to make threads sleep when they are not processing messages to avoid resource usage and wake up as soon as a message arrives.

So, a RunLoop is essentially an object that manages the events and messages it needs to process and provides an entry function to execute the logic of the Event Loop above. Once the thread executes the function, it will remain in the “receive message -> wait -> process” loop within the function until the loop ends (such as the incoming quit message) and the function returns.

  • How does RunLoop implement the Event Loop model logic

The core of RunLoop is based on Mach Port, and when it goes to sleep it calls mach_msg(). To send and receive messages, the mach_msg() function actually calls a Mach trap, the function mach_MSg_trap (). When you call mach_MSg_trap () in user mode, the trap mechanism is triggered, switching to kernel mode; The mach_msg() function implemented by the kernel in the kernel state does the actual work. At the heart of the RunLoop is a mach_msg() function that the RunLoop calls to receive a message. If no one else sends a port message, the kernel puts the thread into a waiting state.

Runloop- Only the main thread automatically runs a Runloop when it is created by default and has a timer. Normal child threads do not have these. In this way, when called in the child thread, the code in our code will wait for the timer to be scheduled, but there is no such timer in the child thread, so our code will never be called. Therefore, perform needs to be aware of the environment when used! PerformSelector withObject afterDelay is a method that doesn’t call SEL in a child thread, performSelect withObject is a method that calls SEL directly. The reasons are as follows: 1. In afterDelay mode, the timer of the current thread is used to invoke SEL after a certain time. In NO afterDelay mode, SEL is directly invoked. The main thread runloop is enabled by default, and the child thread runloop is not enabled by default. Therefore, the timer will not be executed in the child thread. You need to manually enable the runloop

1.NSTimer is a class provided by the Foundation library and implemented based on Runloop. It can be executed only once or periodically repeated (with the repeat parameter set). If it is executed only once, it is automatically destroyed after execution. Repeated execution must be manually called invalidate to destroy. Note the following when using: 1.) Must be used in a thread with runloop. If a method is not in the Timer mode, it cannot respond to a Timer event. 2. PerformSelector is a member method implemented by NSObject. NSTimer implementation depends on NSTimer implementation, so there are problems with NSTimer. Provides the function of the package, so it is more convenient to use. 3. Dispatch_after is the C interface provided by GCD. There is no set of problems with NSTimer. The biggest problem with this interface is that it cannot Cancel.

6. Application startup process

How to optimize and monitor App startup speed

  • Generally speaking, the startup time of an App refers to the time between the user clicking on the App and the user seeing the first interface. To sum up, the startup of App mainly includes three stages: 1) before the execution of main() function; 2) after main() is executed; 3) After the first screen rendering is completed.
  • Before the main() function

Before the main() function is executed, the system does a few things: 1) load the executable (a collection of the App’s.o files); 2) Load the dynamic link library, adjust the Rebase pointer and bind the bind symbol; 3) Initial processing of Objc runtime, including registration of Objc related classes, category registration, selector uniqueness check, etc.; 4) initialization, which includes calls to functions that perform the +load() method, attribute(((constructor)) modifier, and creation of C++ static global variables.

  • After the main () function performs the main () function execution stage, refers to from the main () function performs, into the appDelegate didFinishLaunchingWithOptions method first screen rendering completes relevant methods. Home page business code is to be executed in this stage, that is, before the first screen rendering, mainly includes:
1) Read and write the configuration file required for initialization on the first screen; 2) Big data reading of the first screen list; 3) A lot of calculations for the first screen rendering, etc.Copy the code
  • After the first screen rendering is completed, this stage after the first screen rendering is mainly to complete the initialization of other business service modules other than the first screen, the registration of listening, and the reading of configuration files. On the function of it, this stage means by didFinishLaunchingWithOptions method within the scope of the first screen rendering after finish all methods of execution. Simple said, this stage is from the beginning of the rendering is finished, to the end of the didFinishLaunchingWithOptions method at the end of the scope.

7. IOS static library configuration -ObjC

1, if the static library has a category, you need to add the -objc parameter identifier, otherwise it may report: unrecognized selector sent to instance

2, parameter descriptions (quote from: www.cnblogs.com/robinkey/ar…

-ObjC: After this parameter is added, the linker loads all objective-C classes and categories from the static library into the final executable

-all_load: this will cause the linker to load all found object files into the executable file, but do not use this parameter carelessly! If you use more than one static library file and then use this parameter, you may get ld: duplicate symbol error because different libraries may have the same object file, so it is recommended to use the -force_load parameter when -objc fails.

-force_load: This does the same thing as -all_load, except that -force_load needs to specify the path of all library files to be loaded. In this way, you only load one library file completely without affecting the rest of the library files to be loaded on demand

The third part

Project related

Project structure, key and difficult technology, project design ideas

The difference between ToB and ToC products is enough to know these three points

The fourth part

Simple algorithm

1. Ordered arrays find specific elements

2. Selection sort

3. Common sorting algorithms

The three sorting algorithms of selection sort, bubble sort and insert sort can be summarized as follows: they divide the array into sorted parts and unsorted parts. Select sort defines the sorted part at the left end, and then selects the smallest element of the unsorted part to swap with the first element of the unsorted part. Bubble sort defines the sorted part at the right end, and swaps the largest element to the right end as the unsorted part is traversed. Insert sort defines the sorted part on the left and inserts the first element of the unsorted part element into the appropriate position of the sorted part.Copy the code
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** And the third, and the fourth... The number swap position * the n-1st pass, and finally the ascending (descending) arrangement of the data can be achieved. * */ void selectSort(int *arr, int length) { for (int i = 0; i < length - 1; Int j = I ++) {int j = I + 1; j < length; J++) {/ / times if comparing (arr [I] > arr [j]) {int temp = arr [I]; arr[i] = arr[j]; arr[j] = temp; }}}} /** * 【 bubble sort 】 : adjacent elements compare in pairs, compare a trip, the maximum value appears at the end * the first trip: compare two adjacent numbers in turn, constantly exchange (decimal place before, large number after) one by one advance, the maximum value finally appears in the NTH element position * the second trip: Compare the two adjacent numbers in turn, continuously swap (before the decimal, after the large number) to advance one by one, the most value finally appears in the n-1st element *...... ... */ void bublleSort(int *arr, int length) {for(int I = 0; i < length - 1; I++) {for(int j = 0; j < length - i - 1; J++) {/ / times if comparing (arr [j] > arr [j + 1]) {int temp = arr [j]; arr[j] = arr[j+1]; arr[j+1] = temp; }}}} /** * Split search: optimize search time (without traversing all data) ** Split search principle: * 1> Array must be ordered * 2> Must know min and Max (know the range) * 3> Dynamically calculate the value of mid, extract the corresponding value of mid for comparison * 4> If the corresponding value of mid is greater than the value to be searched, If the value of mid is less than the value to be searched, The min to be greatly mid + 1 * * / / / known an ordered array, and a key to find the key from an array corresponds to the index position int binarySearch (int * arr, int length, int key) { int min = 0, max = length - 1, mid; while (min <= max) { mid = (min + max) / 2; If (key > arr[mid]) {min = mid + 1; } else if (key < arr[mid]) { max = mid - 1; } else { return mid; } } return -1; }Copy the code

IOS bubble sort, insert sort, select sort, quicksort, binary search

Sort (bubble, select, fast, insert, hill, merge, cardinality) algorithms commonly used in iOS development

/** Bubble sort 1. First put all the numbers to be sorted into the work list; 2. Check the list from the first digit to the penultimate digit: if the digit above one digit is greater than the digit next to it, swap it with its next digit; 3. Repeat step 2 (add 1 to the reciprocal number. For example: first to penultimate number, second to penultimate number, and so on...) Until they can no longer exchange. The best time is O(n), the worst time is O(n^2), and the average time is O(n^2) */ - (NSMutableArray *)bubbleSortWithArray:(NSArray *)array {id temp; NSUInteger i, j; NSMutableArray *a = [NSMutableArray arrayWithArray:array]; for (i = 0; i < a.count-1; i++) { for (j = 0; j < a.count-1-i; J ++) {if (a[j] > a[j]) {// ascending temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } NSLog(@"bubbleSort:%@", a); return a; } /** insert sort 1. Initially, a[0] is an ordered region, and the unordered region is a[1..n-1]. Let I =1 2. Merge a[I] into the current ordered region A [0... I -1] to form the ordered region a[0... I]. 3. I ++ and repeat step 2 until I ==n-1. Sorting done. The best time complexity is O(n), the worst time complexity is O(n^2), the average time complexity is O(n^2) */ - (NSMutableArray *)insertSortWithArray:(NSArray *)array {id temp; NSUInteger i, j; NSMutableArray *a = [NSMutableArray arrayWithArray:array]; for (i = 1; i < a.count; i++) { temp = a[i]; for (j = i; j>0 && a[j-1]>temp; j--) { a[j] = a[j-1]; } a[j] = temp; } NSLog(@"insertSort:%@", a); return a; } /** Select sort 1. Let the array contain n numbers to be sorted. Array subscripts start at 0 and end at n-1. 3. Find the smallest element from the a[I +1] element to the NTH element of the array. (The specific process is: first set a[I] (I =0) as the minimum, compare one by one, and swap if smaller than); 4. Swap the minimum element found in the previous step with a[I] element. 5. If I =n-1 algorithm ends, otherwise go to Step 3. The best time complexity is O(n^2) the worst time complexity is O(n^2) the average time complexity is O(n^2) */ - (NSMutableArray *)selectSortWithArray:(NSArray *)array {id temp; NSUInteger min, i, j; NSMutableArray *a = [NSMutableArray arrayWithArray:array]; for (i = 0; i < array.count; i++) { min = i; for (j = i+1; j < array.count; j++) { if (a[min] > array[j]) { min = j; } } if (min ! = i) { temp = a[min]; a[min] = a[i]; a[i] = temp; } } NSLog(@"insertSort:%@", a); return a; } /** Quicksort 1. First take a number from the sequence as the reference number; 2. Partitioning, you put everything to the right of this number, everything less than or equal to this number to the left; 3. Repeat the second step for the left and right intervals until each interval has only one number. The best time complexity is O(nlog2n). The worst time complexity is O(n^2). The average time complexity is O(nlog2n) */ - (void)quickSortWithArray:(NSMutableArray *)array {[self quickSortWithArray:array left:0 right:array.count-1]; } - (void)quickSortWithArray:(NSMutableArray *)a left:(NSUInteger)left right:(NSUInteger)right { if (left >= right) { return; } NSUInteger i = left; NSUInteger j = right; id key = a[left]; while (i < j) { while (i < j && key <= a[j]) { j--; } a[i] = a[j]; while (i < j && key >= a[i]) { i++; } a[j] = a[i]; } a[i] = key; [self quickSortWithArray:a left:left right:i-1]; [self quickSortWithArray:a left:i+1 right:right]; } #pragma mark - pragma mark /** * When using binary search, the data should be sorted. Basic idea: Assume that the data is sorted in ascending order. For a given value x, start the comparison from the middle of the sequence. If the current position value is equal to x, the search succeeds. If x is less than the current position value, look in the first half of the sequence; If x is greater than the current position value, the search continues in the second half of the sequence until it is found. Time complexity: O(logn) */ - (NSInteger)BinarySearch:(NSArray *) Array target:(id)key {NSInteger left = 0; NSInteger right = [array count] - 1; NSInteger middle = [array count] / 2; while (right >= left) { middle = (right + left) / 2; if (array[middle] == key) { return middle; } if (array[middle] > key) { right = middle - 1; } else if (array[middle] < key) { left = middle + 1; } } return -1; } - (void)print:(NSArray *)array { for (id m in array) { NSLog(@"%@", m); } NSLog(@"-----------------"); }Copy the code

Products related to: If you were given a new product, what aspects would you take to ensure its quality?

  • It can be guaranteed from three aspects: code development, test guarantee and online quality.

In the code development stage, there are unit testing, code Review, static code scanning, etc. In the test guarantee stage, there are functional test, performance test, high availability test, stability test, compatibility test, etc. Online quality, including gray release, emergency rollback, failure drill, online monitoring and inspection.

Five encryption algorithms

IOS encryption in detail several common iOS encryption summary!

IOS Development — BAT Interview Questions Collection (ongoing update)

Copy the code