This article is not intended as a solution to any questions. It is only a personal study record. Please correct any mistakes.

IOS Basics

1: Tell me your understanding of noatomic & nonatomic

The internal implementation of atomic seter/getter uses mutex to keep the seter/getter safe in multiple threads. However, atomic objects are custom and may not be locked. Atomic objects are not thread safe in multiple threads.

Nonatomic setter/getter methods are implemented without mutex, so nonatomic modified objects are thread-safe, and nonatomic setter/getter methods are thread-safe, but perform better than atomic methods because they don’t have mutex.

(Example: When multiple threads simultaneously call the same property read method, thread 1 will get a certain value, but the value of get is not controllable. It could be thread 2 or thread 3… The value after set, or the value before)

2: What happens to weak objects when they are released? How is it done? You know sideTable? Can I draw the structure inside?

Weak objects are automatically set to nil when they are released.

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 the address array 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.

In the Runtime memory space, SideTables is a 64-element hash array that stores the SideTable. The hash key of SideTables is the address of an object obj. So we can say that 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. RefcountMap Refcnts (hash table where key is the address of obj and value is the address of obJ) Weak_table (weak reference global hash table), weak_table stores the address of weak reference pointer to OBJ, its essence is a key to obJ address, The address of a pointer to obj that weakly references the hash table for value. The node type of the hash table is Weak_entry_t.

3: What does block look like? The strong can?

Since block variables are declared stack variables by default, blocks must be copied to the heap in order to be used outside the declaration domain of blocks.

For the strong modifier:

First, there are three types of blocks in OC:

  • _NSConcreateGlobalBlockGlobal staticblock, does not access any external variables.
  • _NSConcreateStackBlockStored on the stackblockWill be destroyed when the function returns.
  • _NSConcreateMallocBlockSave in the heap areablockIs destroyed when the reference count is 0.

In the MRC environment, blocks are stored in the global area, heap area, stack area, ARC environment only global area, heap area (stack block, ARC is automatically copied to the heap area).

In an MRC environment, if a block accesses an external variable, you must use copy. In an ARC environment, if a block accesses an external variable, the stack block is automatically copied to the heap, so you can also use strong. Copy is just the MRC legacy, habit

4: Why can blocks capture external variables? What does __block do?

For local variables used in a block, an instance variable with the same name as the local variable is created dynamically at compile time in the block structure. This instance variable holds the value of the external local variable, and when the block is executed, the stored value is retrieved.

All __block does is copy the memory address of the external variable in the stack to the heap whenever it is observed that the variable is held by the block. __block wraps variables into objects, and then encapsulates captured variables in the structure of the block. The variables stored in the block are Pointers to the structure, which can be used to find the memory address and change the value of the variable.

5: Talk about your understanding of the transmission and response chains of events

Transport chain:

(1) After a touch event occurs, the system will use Runloop to add the event to a queue event managed by UIApplication.

(2)UIApplication will fetch the uppermost event from the event queue and distribute the event for processing, sending the event to UIWindow, the main window of the application.

(3) The main window will find the most appropriate view in the view hierarchy to handle touch events

[Touches] [touches] [touches] [touches] [touches] [touches] [touches] This child control is the first responder we need to find

Response chain:

(1) Judge whether the first responder can respond to the event. If the first responder can respond, the transmission of the event in the response chain is terminated. If the first responder cannot respond, the event is passed to the nextResponder, which is the usual SuperView for event response

(2) If the event continues to be uploaded to UIWindow and cannot respond, it will continue to report the event to UIApplication

(3) If the event continues to be reported to UIApplication and cannot respond, it will report the event to its Delegate

(4) If the final event is still not responded, it will be abandoned by the system

Note: Through the event, expand the response area.

6. Talk about the understanding of KVC and KVO?

Key-value-coding (KVC) is a method of indirectly accessing instance variables. Provides a mechanism for indirectly accessing properties of objects.

1. Assign values to private variables.

2. Assign values to internal properties of the control (such as custom UITextFiled clearButton, or placeholder color). Generally, the internal property name of the control can be obtained by the Runtime. Ivar * Ivar = class_getInstanceVariable gets instance member variables).

[textField setValue:[UIColor redColor] forKeyPath:@"placeholderLabel.textColor"];
Copy the code

3, combined with the Runtime, model conversion and dictionary (setValuesForKeysWithDictionary, class_copyIvarList for Ivar member list) of the specified class

KVO is an observer pattern based on KVC implementation. KVO notifies the observer automatically or manually when the properties of the specified observed object change.

Listen to the contentOffSet property of ScrollView

[scrollview addObserver:self forKeyPath:@"contentOffset"  options:NSKeyValueObservingOptionNew context:nil];
Copy the code

7: What does RunLoop do? Is its inner workings understood?

RunLoop basic functions:

(1). Keep the program running and accept user input:

When the program starts, it opens a main thread, which runs a RunLoop corresponding to the main thread. The RunLoop ensures that the main thread will not be destroyed, thus ensuring that the program continues to run.

(2) Determine which events the program should process when

Examples include touches, timers, and Selectors

When the program is running and there are no event sources, The RunLoop tells the CPU to go into hibernation, and the CPU frees up its resources to do other things. When an event source arrives, the RunLoop wakes up to handle the event source.

8: how does apple implement autoreleasepool?

Autoreleasepool is implemented as an array of queues and is implemented using three functions: (1).objc_AutoReleasepoolPush (2).objc_AutoReleasepoolPOP (3).objc_AutoRelease

As you can see from the name of the function, push and POP are performed on the autorelease. The release operation is performed when the object is destroyed.

iOS — Autorelease & AutoreleasePool

9: Talk about your understanding of FRP (functional response)

Functional responsive programming — RxSwift

10: Have you ever played Instrument in normal development?

The following tools are available:

(1).Time Profiler: performance analysis, used to detect application CPU usage. You can see how the various methods in your application are consuming CPU time.

(2).Zoombies: Checks whether zombie objects are accessed, but this tool only checks from the top down and is not smart

(3).allocations: Used to check memory, also used by the people who wrote the algorithm

(4).leaks: Check memory to see if there are memory Leaks

(5).Core Animation: Evaluates graphics performance. This option checks whether the image is scaled and whether the pixels are aligned. Zoomed images are marked yellow, and misaligned pixels are marked purple. The more yellow and purple, the worse the performance.

Runtime

1: What is ISA and what does ISA do?

2: What does an instance object’s ISA point to? What does the class object point to? What does metaclass ISA point to?

Is a pointer of type Class.

Each instance object has a pointer to ISA, which points to the object’s Class, and the Class has a pointer to Isa, which points to a meteClass. Metaclasses hold a list of class methods. When a class method is called, the metaclass looks for its implementation from itself. If not, the metaclass looks for the method from its parent. Note also that a metaclass is also a class; it is also an object. A metaclass also has an ISA pointer, whose ISA pointer ultimately points to a root metaclass. The isa pointer to the root metaclass points to itself, forming a closed inner loop.

3: What are the essential differences and connections between class methods and instance methods in ObjC?

Methods:

(1). Class methods belong to class objects

(2). Class methods can only be called from class objects

(3). Self in a class method is the class object

(4). Class methods can call other class methods

(5). Member variables cannot be accessed in class methods

(6). Class methods may not call object methods directly

Instance methods:

(1). Instance methods belong to instance objects

(2). Instance methods can only be called from instance objects

(3). Self in the instance method is the instance object

(4). Member variables can be accessed in instance methods

(5). Call instance methods directly from instance methods

(6). Instance methods can also call class methods (by class name).

4: The difference between load and initialize?

Thing in common:

(1).+ Load and +initialize are called automatically and cannot be called manually.

(2). If a subclass implements +load and +initialize, it implicitly calls the +load and +initialize methods of its parent class

The.+ Load and +initialize methods use locks internally, so they are thread-safe.

Difference:

The +load method is called when the Runtime loads a class or class (by default). The +load method is called only once for each class or class.

The +load method of the parent class is executed first, followed by the +load method of the subclass, while the +load method of the class is executed after the +load method of its main class. (Classification is called in compile order)

The +initialize method is called the first time a message is sent to a class (via objc_msgSend) and only once, lazy-loading mode. At this point, all classes have already been loaded into memory. If the class has not been used, the + Initialize method is not called.

The +initialize method of the parent class is called first, and then the +initialize method of the subclass is called. If the subclass does not implement the +initialize method, the +initialize method of the parent class will be called several times. If the class implements the +initialize method, it ‘overrides’ the +initialize method of the class itself.

The load Method is usually used as an exchange for Method Swizzle, while the initialize Method is used to assign values to objects that are not easy to initialize at compile time, or to initialize static constants

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

_objc_msgForward is an IMP type (function pointer) for message forwarding: when a message is sent to an object and it is not implemented, _objc_msgForward will attempt to forward the message.

_objc_msgForward message forwarding does several things:

(1). Call resolveInstanceMethod: (or resolveClassMethod:). Allows users to dynamically add implementations to the Class at this point. If there is an implementation, it is called and returns YES, restarting the objc_msgSend process. This time the object responds to the selector, usually because it has already called class_addMethod. If not, proceed with the following action.

(2). Call forwardingTargetForSelector: method, trying to find a can respond to the message object. If it does, the message is forwarded directly to it, returning a non-nil object. Otherwise return nil and continue. Be careful not to return self here, otherwise it will form an infinite loop.

(3). Call methodSignatureForSelector: method, trying to get a method signature. If not, call doesNotRecognizeSelector directly to throw an exception. If available, return non-nil: Create an NSlnvocation and pass it to the forwardInvocation:.

(4). Call the forwardInvocation method, which wraps the method signature from step 3 as the Invocation in, and returns non-nil.

(5). Call doesNotRecognizeSelector:, the default implementation is throwing an exception. If step 3 fails to obtain a method signature, perform this step.

Once _objc_msgForward is called, the IMP lookup is skipped and “message forward” is triggered. If _objc_msgForward is called, objc_msgSend is told that no implementation of the method was found, even if the object actually implements the method. The most common scenario is when you want to get the NSInvocation object for a method.

6: Briefly describe the process of calling methods in Objective-C

Let’s look at the definition of Method in the header file:

typedef struct objc_method *Method;

struct objc_method {
    SEL method_name;
    char * method_types;
    IMP method_imp;
};
Copy the code

Method is defined as an objc_method pointer. The objc_Method structure contains a SEL and an IMP, where SEL is a pointer to objc_Selector, which is essentially a string holding the Method name. IMP is a “function pointer”, which is used to find the address of the function and then execute the function. So, Method associates SEL and IMP, and when sending a message to an object, it finds the IMP by the SEL and executes it.

In addition to the inheritance situation, it can be concluded that: When sending a message to an object, it looks for the class’s method cache (cache methodLists). If there is a cache, it skips to the method implementation. Otherwise, it continues to look for SEL in the class’s methodLists. Then go to the parent class’s cache list and method list, and work your way up until you find the base class. If the message cannot be found, the message is forwarded.

7: Can you 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 class is 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 also calls class_setIvarLayout or class_setWeakIvarLayout to handle strong weak references. So you can’t add instance variables to existing classes;

Classes created at run time can add instance variables and call the class_addIvar function. But after calling objc_allocateClassPair, before objc_registerClassPair.

Tell me about your understanding of aspect programming

AOP is a continuation of OOP, a derived paradigm of functional Programming. (Use objective-C Runtime’s Dark magic Method Swizzling.)

Advantages: It isolates all parts of the business logic, reduces the degree of coupling between all parts of the business logic, improves the reusability of the program, and improves the efficiency of development.

Rambling on the path to iOS AOP programming

IOS faceted programming AOP practices

Network & Multithreading

1: What are the drawbacks of HTTP?

(1) Unencrypted plaintext is used in communication, and the content will be captured.

(2) for the server or client, the identity of the communication party will not be verified, so it may be disguised by the middleman.

(3). The integrity and security of the sent message cannot be verified, and the content of the message may be tampered by a middleman.

2: Talk about three handshakes, four waves! Why three handshakes, four waves?

IOS: Why do TCP connections need three handshakes and four waves

3: The difference between a socket connection and an Http connection

HTTP is an application layer protocol based on TCP connections. It mainly deals with how to package data. HTTP connection is a short connection. The client sends a request to the server. The server responds to the request and disconnects the connection, saving resources.

The Socket is the encapsulation of TCP/IP. The Socket itself is not a protocol, but an API. Through the Socket, we can use TCP/IP. The Socket connection is a long connection. The client directly connects to the server through the Socket, and the connection is not specified. Therefore, the client and the server maintain the connection channel, and both sides can actively send data. The default connection timeout period of the Socket is 30 seconds, and the default size is 8K (understood as a packet size).

4: HTTPS, the latest security layer in addition to SSL? What additional parameters does the client send first in a parameter handshake

5: What is HTTPS? Handshake process, SSL principles, asymmetric encryption

HTTPS parsing

6: When did POP network and Alamofire encapsulation network URLSession need Moya?

POP: Protocol oriented programming protocol oriented = protocol + extension + inheritance Functions are divided by protocol and extension to reduce the coupling between modules and enhance the extensibility of code. One of the weaknesses of iOS is multiple inheritance, and protocols address multiple inheritance. In Swift, structures become more powerful, defining not only attributes but also methods, and multiple inheritance protocols, which OC does not provide.

If Alamofire is already used to abstract urlSessions, why not use some method to abstract the essence of urls, parameters, etc. Therefore, the basic idea of Moya is that we need some network abstraction layer to fully encapsulate the layer that actually calls Alamofire directly.

7. How to implement dispatch_once

Dispatch_once ensures that tasks are executed only once, even if multiple threads are invoked simultaneously. Often used to create singletons, swizzeld method, and other functions.

@implementation ZHClass

+ (id)sharedInstance {
    static ZHClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
Copy the code

8: Can I write a read-write lock? Talk about specific analysis

Semaphore mode:

- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view.
	self.semaphore = dispatch_semaphore_create(1);
	
	for (NSInteger i = 0; i < 10; i ++) {
		[[[NSThread alloc]initWithTarget:self selector:@selector(read) object:nil]start];
		[[[NSThread alloc]initWithTarget:self selector:@selector(write) object:nil]start];
	}
}

- (void)read{
	dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
	NSLog(@"%s",__func__);
	dispatch_semaphore_signal(self.semaphore);
}
- (void)write{
	dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
	NSLog(@"%s",__func__);
	dispatch_semaphore_signal(self.semaphore);
}
Copy the code

Pthread_rwlock_t way:

@property (nonatomic,assign) pthread_rwlock_t rwlock; // Initialize the read/write lock pthread_rwlock_init(&_rwlock, NULL); dispatch_queue_t queue = dispatch_get_global_queue(0, 0);for (NSInteger i = 0; i < 3; i ++) {
		dispatch_async(queue, ^{
			[[[NSThread alloc]initWithTarget:self selector:@selector(readPthreadRWLock) object:nil]start]; [[[NSThread alloc]initWithTarget:self selector:@selector(writePthreadRWLock) object:nil]start]; }); } // read - (void)readPthreadRWLock{
    pthread_rwlock_rdlock(&_rwlock);
    NSLog(@"Read file"); sleep(1); pthread_rwlock_unlock(&_rwlock); } // write - (void) writepThreadlock {pthread_rwlock_wrlock(&_rwlock); NSLog(@"Write file"); sleep(1); pthread_rwlock_unlock(&_rwlock); } // destroy lock - (void)dealloc{pthread_rwlock_destroy(&_rwlock); }Copy the code

Dispatch_barrier way:

Self. testQueue = dispatch_queue_create(self.testqueue = dispatch_queue_create("rw.thread", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (NSInteger i = 0; i < 5; i ++) {
	dispatch_async(queue, ^{
		[self readBarryier];
		[self readBarryier];
		[self readBarryier];
		[self writeBarrier];
	});
}

- (void)readBarryier{
	dispatch_async(self.testqueue, ^{
		NSLog(@"Read file %@",[NSThread currentThread]);
		sleep(2);
	});
}
- (void)writeBarrier{
	dispatch_barrier_async(self.testqueue, ^{
		NSLog(@"Write file %@",[NSThread currentThread]);
		sleep(1);
	});
}
Copy the code

9: When do deadlocks occur? How to avoid it?

A deadlock is a phenomenon in which two or more processes are blocked during execution, either by competing for resources or by communicating with each other, and cannot proceed without external action. The system is said to be in a deadlock state or a deadlock occurs in the system. These processes that are always waiting for each other are called deadlocked processes. An error at the operating system level, short for process deadlock.

A deadlock can occur if certain conditions are met:

(1) mutually exclusive condition: a process is exclusive to the allocated resources, that is, a resource can only be occupied by one process until it is released by the process.

(2). Request and hold conditions: when a process is blocked due to request occupied resources, it holds on to acquired resources.

(3). Non-deprivation condition: any resource cannot be deprived of by any other process before it is released by this process.

(4). Circular waiting condition: When a deadlock occurs, the waiting process must form a loop (similar to an infinite loop), causing permanent blocking.

10: What kinds of locks are there? How do they work? What’s the difference between them? It’s best to use it in context

(1).NSLock implements the most basic mutual exclusion. It follows the NSLocking protocol and locks and unlocks through lock and unlock.

NSRecursiveLock is a recursive lock that can be acquired multiple times by a thread without causing a deadlock. It records the number of times the lock was successfully acquired. For each successful lock acquisition, there must be a corresponding release lock so that a deadlock is not caused. Only after all locks have been released can other threads acquire the lock

(3).NSCondition is a special type of lock through which the scheduling of different threads can be realized. A thread is blocked by a condition until another thread satisfies the condition to send a signal to that thread so that it can execute correctly.

(4). The mutexes defined by NSConditionLock can be locked and unlocked under certain conditions. It’s very similar to NSCondition, but implemented differently.

(5). Pthread_mutex, mutex is a super easy to use mutex, you only need to initialize a pthread_mutex_t to use pthread_mutex_lock to lock pthread_mutex_unlock, when the use is complete, Remember to call pthread_mutex_destroy to destroy the lock.

(6). Pthread_rwlock, read/write lock, in the file operation, write operation is exclusive, once multiple threads write operation on the same file, the consequences are immutable, but it is possible, multiple threads read without any problem.

When a read/write lock is held by a thread in read mode, the other threads of the write operation are blocked and the other threads of the read operation can continue. When a read-write lock is held by a thread in write mode, the other threads of the write operation are blocked, and the other threads of the read operation are also blocked.

(7). Dispatch_semaphore mechanism to lock, wait for signals, and send signals, when there are multiple threads for access, as long as one of the signals, the other threads must wait for the signal release.

(8).@synchronized, a convenient way to create a mutex that does everything other mutex does.

Different locks should be used for different operations:

When reading or writing files, it is better to use pthread_rwlock. Reading or writing files consumes a lot of resources. Using mutex to read files simultaneously blocks other file reading threads, but pthread_rwlock does not. Pthread_mutex or dispath_semaphore can be used when performance requirements are high. OSSpinLock does not guarantee thread safety. Os_unfair_lock is available only in iOS10. This ensures both speed and thread safety. For NSLock and its subclasses, speed NSLock < NSCondition < NSRecursiveLock < NSConditionLock.

Updates continue at……….