Data structures, algorithms, and network structures
Please refer to algorithms and Networks for these two categories of interview questions
Object oriented fundamentals
-
How many principles of object-oriented design?
- SOLID Principles (update: should be seven according to a friend’s reminder)
- Single Responsibility Principle
- Open Close Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
- Law of Demeter(Leaset Knowledge Principle)
- Composite Reuse Principle
- SOLID Principles (update: should be seven according to a friend’s reminder)
-
Implementation of Hash table?
- By mapping a key value to a location in a table to access records, Hash functions and conflict resolution (chaining and open addressing) are key to Hash implementation.
-
What are processes and threads? What’s the difference?
- Process: a running activity of a program in a computer on a data set. It is the basic unit of resource allocation and scheduling in the system.
- Thread: The smallest unit in which an operating system can schedule operations
- Difference: Threads are contained within a process and are the actual operating unit of the process. A thread is a single sequential flow of control in a process, and multiple threads can be concurrent in a process, each performing a different task in parallel.
-
How many large areas of memory? Respective functions?
- Stack area: automatically allocated and released by the compiler, usually storing function parameter values, local variables, etc.
- Heap area: allocated and released by the programmer, if not released, the end of the program by the operating system.
- Global (static) : Managed (allocated and freed) by the compiler and freed by the system when the program ends. Global and static variables (two adjacent partitions, initialized and uninitialized).
- Text constants: managed by the compiler (allocation release), released by the system at the end of the program; Store constant characters.
- Program code area: store the binary code of the function.
-
What are the differences between architecture, framework, and design patterns?
- Architecture: A top-level, generalized design concept, such as a blueprint, that abstracts different requirements into concrete components and enables them to communicate with each other.
- Framework: Software framework is an architecture formed by extracting the common parts of software in a specific domain. Software projects in different domains have different types of framework.
- Design patterns: a set of repeated, well-known, cataloged summaries, a result of code design that can be applied to a solution to a practical problem in a variety of software frameworks. (a method developed in software development that is suitable for solving a problem)
-
The difference between MVC, MVVM and MVP architectures?
- MVC
- [Advantages] Simple and easy to use, no multi-layer call
- 【 Disadvantages 】 Strong coupling; It is not conducive to unit testing. Controller is responsible for too much event processing, handling user operations, managing View declaration cycle, API interface call, error handling, callback handling, notification monitoring, View direction handling, etc., which is easy to cause bloat and inconvenient to maintain
- MVP
- [Advantages] Conducive to unit testing, clear responsibility allocation
- [Disadvantages] You need to write some extra code (such as binding), if the business logic is complex, it will also cause redundancy of Presenter
- MVVM
- [Advantage] Clear division of responsibilities; Logical and clear; High testability; Two-way binding, easy to use with third-party open source libraries
- [Disadvantages] (1) Data binding makes it difficult to locate bugs; (2) For large projects, data binding requires more memory; Relying on open source libraries to achieve bidirectional binding is complicated to learn;
- MVC
IOS Basic interview questions
UI
- What’s the difference between UIView and CALayer?
- UIView and CALayer are UI manipulation objects. Both are subclasses of NSObject, and the operations that happen on UIView essentially happen on the corresponding CALayer.
- UIView is CALayer’s abstraction for interaction. UIView is a subclass of UIResponder (UIResponder is a subclass of NSObject). It provides a lot of interactive interfaces that CALayer doesn’t have. It handles user-triggered operations.
- CALayer is better at rendering images and animations. This is because UIView has redundant interfaces and is hierarchical compared to CALayer. CALayer can save a lot of time by rendering without having to deal with interactions.
- CALayer’s animations are implemented through logical trees, animation trees, and display trees
- What is loadView for?
- LoadView uses custom views. As long as this method is implemented, other views created through xiB or storyboard will not be loaded.
- What is the difference between layoutIfNeeded, layoutSubviews and setNeedsLayout?
- LayoutIfNeeded: Immediately after a method call, the main thread forces an updated layout for the current view and all its children.
- LayoutSubviews: the method can only be rewritten and cannot be actively called. It is automatically called by the system when the screen rotates, slides or touches the interface, or when the subview is modified, and is used to adjust the layout of the custom view.
- SetNeedsLayout: The method is similar to layoutIfNeeded, except that it is not forced to update the layout immediately after the method is called, but the next layout cycle.
- IOS response chain? What can affect the response chain?
- Event UIResponder: objects that inherit from this class can respond
- Event handling: touchesBegain, touchesMoved, touchesEnded, touchesCancelled;
- Event response process:
- UIApplication(and delegate) receives events passed to the keyWindow
- KeyWindow iterates through subViews’ hitTest:withEvent: method and pointInside method to find the view within the clicked area and process the event
- UIView’s subviews also iterate through their hitTest:withEvent: methods, and so on, until they find the topmost view in the clicked region, gradually returning the view to UIApplication
- The last view found becomes the first responder. If it can’t respond, it calls its nextResponder method until it finds an object in the response chain that can handle the event (UIControl subclasses don’t apply).
- If the Application still has no object that can handle the event, the event is discarded.
- The key is the hitTest:withEvent: method and the pointInside method
- ⚠️ Ignore the following: hidden is YES, alpha is less than or equal to 0.01, userInteractionEnabled is NO,
- Subclasses of UIControl and UIGestureRecognizer have higher priorities and break the response chain.
- How many ways can you add rounded corners to a UIImageView?
- CornerRadius (iOS9 does not cause off-screen rendering after)
- CoreGraphic draw
- UIBezierPath (same essence)
- What are the ways to animate on iOS?
- UIView Animation: The system provides an encapsulation based on CALayer Animation, which can realize functions such as translation, scaling and rotation.
- CALayer Animation: The underlying CALayer and the subclasses of CAAnimation can achieve more complex animations
- UIViewPropertyAnimator: an Animation introduced after iOS10 to handle interactions that can achieve all the effects of a UIView Animation.
- What are the effects of using drawRect?
- When handling touch events, setNeedsDisplay is called to force a redraw, incurring additional CPU and memory overhead.
OC basis
- IOS memory management mechanism?
- Reference Count, from Manuel Reference Count (MRC) to Automatic Reference Count (ARC). (Preferably the life cycle of the object)
- What are the relevant modifiers after @property?
- Atomicity:
- Nonatomic: nonatomic, not locked by the compiler (synchronous locking is expensive)
- Methods synthesized by the compiler are guaranteed to be atomic (non-thread-safe) by locking.
- Read and write permissions:
- Readwrite: Read-write (default). The compiler automatically generates setters and getters for it unless the @dynamic modifier is used, otherwise the compiler does not generate user-generated methods
- Readonly: read-only. If no dynamic modifier is used, only getters are generated. Otherwise, the compiler does not generate getters and the user implements them
- Memory management semantics:
- Strong: modifies the reference type (holding the current instance). New values are retained and old values are released. Copy is recommended to modify IMMutable types
- Copy: modifies an immutable collection type, an AttributeString, and a Block (ARC strong copies a Block from the stack to the heap, and copy does not require copy).
- Weak: Modifies the reference type (non-holding), does not retain new values, does not release old values (property values also clear empty nil when the object to which the property refers is destroyed)
- Assign: Decorates primitive data types (reference types can also be assigned, but wild Pointers may be produced), and performs simple assignment operations
- Unsafe_unretained: Redefines the reference type (also the base type). Property values are not deleted when the referenced object is destroyed (unsafe_unretained).
- The method name:
- Getter = Specifies the method name
- Setters (not commonly used)
- Atomicity:
- What’s the difference between dynamic and synthesis?
- Dynamic: tells the compiler not to automate the synthesis of setter and getter methods for me, but to implement them myself, otherwise the method will cause message forwarding when called.
- Synthesis: Specifies the name of the instance variable. The subclass overrides the parent class attributes and also requires synthesis(re-set and get, use dynamic, define attributes in Protocol, define attributes in category, not automatically synthesized by default).
- Why copy array? Why does mutableArray use strong?
- Array: Use copy to prevent changes that may occur unknowingly after a strong subclass is assigned a variable value.
- MutableArray with copy modifier returns an NSArray type. If you call add, delete, or modify methods of mutable types, crash because the corresponding method cannot be found.
- Deep copy and shallow copy (note the NSString type)?
- NSString: strong and copy are identical, pointing to the same memory address. MutableCopy is a memory copy.
- NSMutableString: strong is different from copy. Strong points to the same memory address. Copy copies memory, and mutableCopy copies memory.
- NSArray: the result is different for character types and custom objects. Strong and copy point to the same memory address, and mutableCopy is just a copy of a pointer. But mutableCopy can turn an Array into a mutableCopy
- PS: copy produces an immutable type, and mutableCopy produces a mutable type. MutableCopy copies characters for the character type, copy does not copy for NSArray, copy does copy for NSMutableArray; For object types, it’s just a pointer copy; (It is recommended to try manually)
- How many types of blocks are there?
- _NSConcreteGlobalBlock: GlobalBlock is also the default Block type, an optimization operation, private and public, keeping private to prevent external circular references, stored in the data area, and copied to the heap when capturing external variables
- _NSConcreteStackBlock: stack Block, stored in the stack area, automatically reclaimed by the system when its scope ends
- Nsconcretemallocblock: heap Block, destroyed when the counter is 0
- The difference between isEqual and “==”?
- == : Compares two Pointers themselves, not the object to which they point.
- IsEqual: If and only if pointer values (i.e. memory addresses) are equal; If you override this method, you need to ensure that isEqual is hash equal, hash equal is not necessarily equal; If the pointer value is equal, it is equal; if the value is not equal, the class of the object is judged; if the object does not belong to the same class, it is not equal; if the object belongs to the same class, it is judged whether each attribute is equal.
- What’s the difference between ID and NSObject?
- Id: a pointer to an object that is not type checked at compile time but is checked at runtime by sending a message to it.
- NSObject: The NSObject class and its subclasses, which do type checking at compile time and perform message forwarding when a message sent to it cannot be processed.
- id<NSObject> : the compiler does not type check the object. The default class to which the object belongs implements a Protocol called NSObject that responds to methods without type checking them.
- What are the differences between notification, proxy, KVO and Block?
- Notification: Applies to the transfer of unrelated pages or system messages, belonging to the one-to-many information transfer relationship. Such as receiving system volume, system state, keyboard, etc., application mode Settings and changes, are more suitable for using notifications to convey information.
- Proxy: One-to-one information transfer, suitable for information transfer between related pages, such as push and present pages and original pages.
- Block: one-to-one transmission of information, more efficient than the proxy (after all, direct IMP pointer operation). The scenario is similar to that of a proxy, which is page passing values between interrelated pages.
- KVO: Property monitoring. It monitors the change status of an attribute value of an object. It is used when it is necessary to monitor the change of an attribute of an object. For example, in UIScrollView, you listen to contentOffset, either using KVO or agents. However, in other cases, such as UIWebView loading progress and AVPlayer playing progress, KVO can only be used to monitor, otherwise the corresponding attribute value cannot be obtained.
- What is a circular reference? What is the difference between __weak, __strong, and __block?
- Cyclic references: Two objects hold each other, one of which needs to be freed first, and the delegate’s weak declaration is designed to prevent cyclic references. (Generally refers to bidirectional strong reference, one-way strong reference does not need to be considered, such as: UIView animation Block)
- __weak: A Block can catch instances that access a Block outside the scope of the Block, which runs the risk of memory leaks. Using __weak to indicate that a Block does not cause the instance reference counter to increment by 1. It can also force the Block to nil after the execution of the Block, so that the instances caught by the Block are freed. If only the basic data type is captured, the Block will only make a copy of its value, and no change in value will affect the operation inside the Block.
- __strong: An instance with an __weak modifier in a Block is easily released, so it needs to be locked to determine whether it is released or not. If it is not released, it will be strongly referenced to ensure that messages sent to the instance will not crash
- __block: By default, a Block does not allow you to change the value of an external variable. For example, if you access a variable in a Block, you Copy the variable and store it in a Block function. Then, changes to the variable outside the Block do not affect the value of the variable used in the Block. Variables must be modified with __block, which copies the stack memory address of the variable to the heap, so the new value can be written directly to memory. (Copy the pointer address of a variable on the stack to the heap)
- What’s the difference between memory leaks, wild Pointers, and zombie objects?
- Memory Leaks: Memory requested in the heap that is no longer used is not released, and the program ends the release (Analyzer, Leaks)
- Wild pointer: Refers to memory that has been freed or marked by the system as recyclable (debugged with Malloc Scribble).
- Zombie object: An object that has been freed and points to a chunk of memory that you don’t think you have access to or that it can’t execute the message. (EXC_Bad_Access, enable NSZombieEnabled detection)
- Nil, nil, NULL, NSNull?
- Nil: empty instance object (assign a null value to an object)
- Nil: empty Class object (Class Class = Nil)
- NULL: indicates a NULL pointer to type C
- NSNull: class, used as a placeholder for empty objects (used to replace empty objects in collections, and to determine if an object is empty)
- Static vs. const
- Const: Declare a global read-only variable. (Declaring a constant with the same name in another file without the static modifier is an error.)
- Static: Modifies the scope of a variable (in this file). The modified variable allocates only one memory, which is modified on the basis of the last modification.
- Generally, the two are used together, for example:
Static const NSTimeInterval kAnimationDuration = 1.0;
No external matches are created, and compile-time preprocessor instructions replace variables with constant values.
- What are the design patterns in iOS?
- [Singleton] Ensure that there is only one power object of this class in the life cycle of the application program, which is easy to access. Such as UIApplication, NSBundle, NSNotificationCenter, NSFileManager, NSUserDefault, NSURLCache, etc.
- [Observer] defines a one-to-many dependency relationship, which allows multiple observers to monitor a topic object at the same time. When the state or value of the topic object changes, all observers will be notified. KVO Notifies the object observing the property when it changes. Case representative: Notification and KVO
- 【 class clusters 】 (hiding implementation details behind abstract base classes) such as UIButton, NSNumber, NSData, NSArray, NSDictionary, NSSting. Use isMemberOfClass and isKindOfClass to judge.
- The NSInvocation encapsulates a request or behavior as an object, including the selector, method name, and so on.
- “I want to know what line in the list is the selected item”? Yes, as soon as you accept my commission; Just accept my commission to help me complete these several things, some must finish, some unnecessary finish, as to how you finish I don’t care.
- Decorator pattern: The decorator pattern dynamically adds new behaviors and responsibilities to an object without modifying the original code. It modifies the behavior of a class by wrapping the decorator object as an alternative to subclassing. Case representative: Category and Delegation
- What is the difference between static and dynamic libraries?
- Static library:.a(.h with) and. Framework (resource file. Bundle) files, compiled binary code, use link, compile a copy of the target program, easy to increase the target volume.
- Dynamic libraries:.tbd and.dylib, dynamically loaded into memory at runtime, can be shared, dynamic loading has performance loss and dependencies (system directly provided to the framework are dynamic libraries!)
- How many ways to introspect in iOS?
- Introspection is the ability of an object to reveal its own details as an object at run time. These details include the object’s position in the inheritance tree, whether it conforms to a particular protocol, and whether it responds to a particular message. And whether it responds to a message.
- Class and superclass methods
- IsKindOfClass: and isMemberOfClass:
- respondsToSelector:
- conformsToProtocol:
- isEqual:
OC advanced
-
Conversion between Foundation and CoreFoundation?
- __bridge: transfers Pointers between the OC and CF. The management right is not transferred. If the OC is connected to the CF, the CF cannot be used after the OC is released.
- __bridge_ Retained: Replace the OC with a CF object, transfer the ownership of the OBJECT, and strip the ARC management right. CFRelease is used to release the retained OBJECT.
- __bridge_transfer: Converts CF to OC and transfers object ownership to ARC, so CFRelease is not required.
-
What’s the difference between array and set? Which is faster, search speed or traversal speed?
- Array: Allocates a contiguous array of storage units in an orderly manner. The array search is not as fast as the Hash search.
- Set: the storage unit is not contiguous and the data is out of order. You can use Hash to map the storage location and determine whether the corresponding location exists by directly using the Hash of the data. The search speed is fast.
- Traversal speed: The data structure of array is a piece of continuous memory unit, which has a fast reading speed. Set is discontinuous and non-linear, which has a slow reading speed.
-
What is an inline function? Why is it needed?
- Functions that use inline modifications are not necessarily inline functions, and inline functions are always inline.
- Ordinary functions: Compilation generates call instructions (on and off the stack). When calling, the address of the call instruction is pushed onto the stack and the start address of the subroutine is entered. After execution, the address of the original function is returned, so there is some time overhead.
- Function code with #define macro definitions and inline modifications is put into the symbol table and replaced directly when used, with no overhead of invocation; Functions defined by the #define macro: when used, they are replaced from the symbol table, have format requirements, do not check the validity of parameters, and return values cannot be strong; Inline function: does not require precompilation, replaces and type checks when used, is a piece of code expanded directly in the function (macros are direct text replacements)
- PS: Inline function code is placed in the symbol table, which is used to replace the code directly (insert the code into the calling code).
- PS: An inline function may fail because it is not allowed to use a loop or switch statement, so it will be restored to an inline function. The inline keyword must be used with the function definition. If declared, it does not count as an inline function.
-
The process of picture display?
- Suppose we use the +imageWithContentsOfFile: method to load an image from disk without decompressing the image;
- And then assign the generated UIImage to UIImageView;
- Then an implicit CATransaction captures the UIImageView layer tree changes;
- On the next run loop of the main thread, Core Animation commits this implicit transaction, which may copy the image depending on whether the image is byte aligned, etc. This copy operation may involve some or all of the following steps:
- Allocate memory buffers to manage file IO and decompression operations;
- Read file data from disk to memory;
- Decoding compressed image data into uncompressed bitmap form is a very time-consuming CPU operation;
- Finally, Core Animation renders the UIImageView layer using uncompressed bitmap data. (Must understand bitmap related knowledge)
-
How can DISPATch_once be executed only once?
- In multithreading, if one thread is accessing its initialization operation, another thread will come in and wait for nothing. There are memory barriers to ensure that the program instructions are executed in sequence
void dispatch_once_f(dispatch_once_t *val, void *ctxt, void (*func)(void *)){ volatile long *vval = val; if(dispatch_atomic_cmpxchg(val, 0l, 1l)) { func(ctxt); // block does dispatch_atomic_barrier(); *val = ~0l; }else { do { _dispatch_hardware_pause(); } while (*vval != ~0l); dispatch_atomic_barrier(); } } Copy the code
-
NSThread, NSRunLoop, and NSAutoreleasePool?
- According to the NSRunLoop description in the official documentation, we know that each thread, including the main thread, has a dedicated NSRunLoop object, which is automatically created when necessary.
- According to the description of NSAutoreleasePool in the official documentation, we know that the NSRunLoop object in the main thread (should be the same in other system-level threads, such as through
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
The system automatically creates an AutoReleasepool before each event loop starts and drains at the end of the event loop. - Autoreleasepool needs to be added manually:
- If you write a loop that creates a lot of temporary objects;
- If you create a worker thread
-
Classification of extensible differences? (Can be answered from memory layout, load order, classification method, and execution order of the original class methods)
- Extension: must be added in.m. It participates in the memory layout as part of the class at compile time and has the same life cycle as the class. Add private implementation and hide private information of the class.
- Category: separate. H and. M files, independently compiled and dynamically loaded dyld, extending functionality for existing classes.
- Class limitations: Instance variables cannot be added, attributes can be added but instance variables are not generated for them (at run time, the memory layout of an object is determined, adding instance variables would break the memory layout of the class, which is disastrous for compiled languages)
- Class loading: instance methods, properties, and protocols are added to the class, or to the metaclass if there are any protocols and class methods. The list of methods of the runtime class is dynamically added to the list of methods of the class, before the original methods of the class.
- Method order: [load method] call the load method of the parent class first and then call the classification method, [rewrite method] because the classification method is in front of the original class method, so call the method in the classification first.
-
OC object release process? The runloop loop checks the reference count and releases the process: Release ->dealloc-> Dispose
- Release: The reference counter is decrement by one until it reaches zero
- Dealloc: Entry to object destruction
- Dispose: Destroys objects and releases memory
- Objc_destructInstance: calls C++ cleanup methods and removes associated references
- ClearDeallocating: Sets weak to nil, destroying the table structure of the current object, in one of two ways
- Sidetable_clearDeallocating: Cleans an object that has a pointer to ISA
- ClearDeallocating_slow: Clears non-pointer ISA objects
- ClearDeallocating: Sets weak to nil, destroying the table structure of the current object, in one of two ways
- Free: Free memory
- Objc_destructInstance: calls C++ cleanup methods and removes associated references
-
What’s the difference between CDDisplayLink and NS Mer?
- CADisplayLink: A timer that draws content to the screen at the same rate as the refresh rate of the screen. Runloops need to be added manually
- NSTimer: a runloop that can be automatically added to the current thread, default defualt mode, or optionally added loopMode;
-
What are the risks of swapping the Runtime implementation methods?
- Risk 1: If the exchange is not nonatomic in load, it is not safe in the Initial method
- Risk 2: When rewriting the parent class methods, most of them need to call the super method, and swizzling exchange methods. If they are not called, some problems may occur, such as naming conflicts, changing parameters, calling order, difficulty in predicting and debugging.
Runtime source code
-
Do you know AutoreleasePoolPage? How does it work?
- AutoreleasePool is implemented by AuthReleasePoolPage. The implementation of AutoreleasePoolPage is to insert POOL_SENTINEL into the next position of the AutoreleasePoolPage. And returns the memory address of the inserted POOL_SENTINEL. This address, also known as the pool token mentioned earlier, is used as an input parameter to the function when performing the POP operation.
- The specific insert operation is performed by calling the autoreleaseFast function; The autoreleaseFast function handles three cases differently when performing a specific insert operation:
- If the current page exists and is not full, add the object directly to the current page, where next points to.
- When the current page exists and is full, create a new page, add the object to the newly created page, and then associate the Child Page.
- When the current page does not exist, that is, there is no page, the first page is created and objects are added to the newly created page.
-
The underlying implementation of KVO? (If you have read the RAC source code, you should know that the RAC listening method is based on the same principle, but with a slight difference.)
- When an object has an observer, a subclass of the object class is dynamically created
- For each property being observed, override its setter method
- Call willChangeValueForKey: and didChangeValueForKey to notify the observer in the overridden setter method
- When a property has no observers, the override method is not removed until all observers are removed and dynamically created subclasses are removed.
// 1) human addObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionNew context:nil]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {/* handle the listener */} // 2) disable automatic notification of system observers + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {if ([key isEqualToString:@"name"]) { return NO; } return[super automaticallyNotifiesObserversForKey:key]; } // 3) call both methods [self willChangeValueForKey:@"name"]; /* Modify the value */ [self didChangeValueForKey:@"name”]; Copy the code
-
How can weak objects be set to nil? You know SideTable?
- A SideTable is used to manage the reference count table and the weak table of the registered class. The address of the weak object is stored as a key in the global reference table of the weak object. Value is the set of addresses pointing to the weak pointer. Calling release causes the reference counter to be decrement by one, dealloc is called when the reference counter is 0, and all weak Pointers to the object are set to nil when dealloc is executed to avoid dangling Pointers.
-
What is an associated object? What can it be used for? How does the system manage managed objects? Do you support KVO?
- Associated objects: Dynamically associate a lifetime variable (via objc_setAssociatedObject and objc_getAssociatedObject) to the specified object at run time to implement the ability of the category properties to hold data and pass values. (Support KVO, let the associated object as observer)
- Managing associated objects: The system manages a global hash table and obtains associated objects through the address of the object pointer and the address of the passed fixed parameter. Manage the life cycle of the object based on the parameter policy passed in by the setter. Use a global hash table to manage object association. Obtain the object association table based on the object pointer address, and then search for the corresponding value based on the user-defined key(external: key(object pointer)-value(hash table), inner table: key(user-defined name)-value(managed value)).
-
The relationship between ISA, object, class object, metaclass and superclass?
- Class: An object is an instance of aclass, and aclass is an instance of another class, a metaclass. Metaclasses hold the class methods of classes. When a class method is called, the metaclass first looks to see if it has an implementation of the class method. If it does not, the metaclass looks for the method from its parent until it reaches the root of the inheritance chain. If not, it forwards the method.
- Metaclass: Where does the isa pointer to a metaclass point? For design integrity, all isa Pointers to metaclass will point to a root metaclass. The isa pointer to the root metaclass itself points to itself, thus forming a closed loop. As mentioned above, the list of messages that an object can receive is stored in its corresponding class. In real programming, we rarely encounter messages to the metaclass, so its ISA pointer is rarely used in practice. But this design keeps object-oriented cleanliness, where everything is an object and has isa Pointers.
- Inheritance: Let’s look at inheritance again, because the definition of aclass method is stored in a metaclass, and the rule of method calls is that if the class does not have an implementation of a method, the search continues to its parent class. Therefore, in order to ensure that the methods of the parent class can be called in the child class, the metaclass of the child class inherits the metaclass of the parent class. In other words, class objects and metaclass objects have the same inheritance relationship.
-
Know the method objc_allocateClassPair to create a class? What exactly does the method do?
// objc-class-old.mm
Class objc_allocateClassPair(Class supercls, const char *name,
size_t extraBytes)
{
Class cls, meta;
if (objc_getClass(name)) return nil;
// fixme reserve class name against simultaneous allocation
if (supercls && (supercls->info & CLS_CONSTRUCTING)) {
// Can't make subclass of an in-construction class return nil; } // Allocate new classes. If (supercls) {// Allocate new classes. CLS = _calloc_class(supercls->ISA()->alignedInstanceSize() + extraBytes); meta = _calloc_class(supercls->ISA()->ISA()->alignedInstanceSize() + extraBytes); } else {// If the parent class does not exist, CLS = _calloc_class(sizeof(objc_class) + extraBytes); meta = _calloc_class(sizeof(objc_class) + extraBytes); } // Initialize objc_initializeClassPair(supercls, name, CLS, meta); return cls; } // objc-runtime-new.mm Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes) { Class cls, meta; rwlock_writer_t lock(runtimeLock); // Fail if the class name is in use. // Fail if the superclass isn't kosher.
if(getClass(name) || ! verifySuperclass(superclass,true/*rootOK*/)) {
return nil;
}
// Allocate new classes.
cls = alloc_class_for_subclass(superclass, extraBytes);
meta = alloc_class_for_subclass(superclass, extraBytes);
// fixme mangle the name if it looks swift-y?
objc_initializeClassPair_internal(superclass, name, cls, meta);
return cls;
}
Copy the code
- The difference between class_ro_t and class_rw_t?
- Class_ro_t is readonly, class_rw_t is readwrite;
- After compilation, the baseMethodList for class_ro_t is determined. When the image is loaded, the methodizeClass method adds baseMethodList to the methods list of class_rw_t, then iterates category_list and adds the category method to the methods list. By category, I mean a category, based on which a category can extend a class’s methods. This is often used in development.
- Class_ro_t is immutable in memory. At runtime, methods are dynamically added to the class, essentially updating the list of methods for class_rw_t.
- Do you know of any other message sending functions besides objc_msgSend?
- Objc_msgSend_stret: This function can process the message only when the CPU register is large enough to hold the return type of the message. If the CPU register is large enough, another function will execute and distribute the message. The original function will process the returned structure by assigning variables on the stack.
- Objc_msgSendSuper_stret: Sends a message to the parent class instance that returns a structure
- Objc_msgSendSuper: Send a message to the superclass ([super MSG])
- Objc_msgSend_fpret: When a message returns a floating-point number, a call to a function on some cpus requires special processing of the floating-point register. The range of floating-point registers varies depending on the architecture. (Registers are the part of the CPU that stores instructions, data, and addresses.)
- What is method swapping? How does it work?
- SEL method address and IMP function pointer is mapped by DispatchTable table, can be dynamically modified by the runtime SEL, so it can achieve method exchange (use experience according to the project to talk about).
Data persistence
- Plist: XML file. Reading and writing are the entire overwrite and the entire file needs to be read. It is suitable for a few data stores and is generally used to store information related to App Settings.
- NSUserDefault: use UserDefault to read and write plist files. The function and application scenario are the same as the preceding.
- NSKeyedArchiver: The serialized object must support the NSCoding protocol and can specify any data storage location and file name. The performance of reading and writing large data is low.
- CoreData: is officially launched large-scale data persistence solution, its basic logic is similar to SQL database, each table is Entity, then we can add, read, modify, delete object instances. Like SQL, it can provide complex operations such as fuzzy search, filtered search, table association, and so on. Although powerful, its disadvantages are a high learning curve and complex operation.
- SQLite (FMDB, Realm)
multithreading
-
What’s the difference between a serial queue and a concurrent queue? What’s the difference between synchronous and asynchronous?
- Serial Queue: Only one task can be executed in a Queue at a time. After the current task is executed, the next task can be executed. There is only one thread in the Serial Queue.
- Concurrent Queue: Allows multiple tasks to be performed at the same time, with multiple threads in a Concurrent Queue. Tasks on a serial queue must end in the order they started, while tasks on a concurrent queue do not necessarily end in the order they started.
- Sync: The current task is queued, and the thread will not return to the queue until the task is complete, which means synchronization blocks the thread.
- Async: It also adds the current task to the queue, but it returns immediately without waiting for the task to complete, that is, Async does not block the thread.
- PS: Both serial and concurrent queues can perform synchronous or asynchronous operations. Note that synchronized operations on serial queues can cause deadlocks, but not on concurrent queues. Asynchronous operations can be thread safe on both serial and concurrent queues.
-
The difference between GCD and NSOperation?
- NSOperation VS GCD
- Syntax: Object-oriented (heavyweight) – C-oriented (Lightweight)
- Advantages over GCD:
- Cancel an operation (unstarted task),
- Specify dependencies between operations (specify dependencies based on requirements)
- Monitoring properties of NSOperation objects (KVO) through key-value observation
- Specify the priority of the operation
- Reuse NSOperation objects
- Provide optional completion blocks
Thread safety
-
How to keep thread safe?
- Atomic operations: Operations that are not interrupted by thread scheduling; This operation, once started, runs through to the end without any context switch.
- Memory barriers: Ensure that Memory operations occur in the correct order and do not block threads. (Memory barriers are used at the bottom of locks to reduce the number of optimizations the compiler has to perform. Use them with caution.)
- The lock
- Mutex (pthread_mutex) : Works like a semaphore, but instead of using busy, it blocks threads and sleeps, requiring context switching.
- NSRecursiveLock: Essentially a PTHREAD_MUTEX_RECURSIVE lock that encapsulates a mutex, allowing the same thread to repeatedly lock its own lock without releasing it.
- Spin lock (OSSpinLock) : through the global variable, to determine whether the current lock is available, unavailable busy, etc.
- @synchronized(self) : A system-provided OC-oriented API that uses the object hash as a lock.
- NSLock: Essentially a lock of type PTHREAD_MUTEX_ERRORCHECK that encapsulates a mutex. This lock will lose some performance in return for an error message. Due to the object-oriented design, its performance is slower.
- NSConditionLock (condition variable)pthread_cond_t (condition variable), which is used to block the thread and wake it up when a waiting data is ready, such as the common producer-consumer mode.
- Semaphore (dispatch_semaphore)
// The value of dispatch_semaphoRE_create (1) should be >=0. If 0 is passed, block the thread and wait for timeout dispatch_semaphore_create(1) : // if the resource is locked, the signal value will be -1 dispatch_semaphore_wait(signal, overTime) : // unlock makes signal +1 dispatch_semaphore_signalCopy the code
-
What is a deadlock? How do I avoid deadlocks?
- Deadlock: A situation in which two or more threads wait for each other to stop in order to acquire a resource, but neither of them exits prematurely.
- Avoid synchronization tasks in serial queues; Avoid Operation dependencies;
-
What is an inversion of priorities?
- Low priority tasks will precede A high-priority task execution, assumption: task priority A > B > C, A waiting for access to C is using the critical resources, B will access the resource at the same time, the priority is higher than C, B at the same time, the higher priority task is B C preemptive priority task, thus unable to release the critical resources in A timely manner. In this case, the lower-priority task B gets execution, while higher-priority task A can only be blocked. You can set the same task priority to avoid priority inversion.
Questions related to project experience
- When to refactor? How did you reconstruct it? (Including but not limited to the following points for reference only)
- The current architecture does not support the business, the current design model has too many drawbacks, the project is rushed to launch without time to optimize, etc.
- Optimize business logic; Remove useless code (including third-party libraries, variables, methods, etc., except comments);
- Keep the principle of class and method singleness and migrate departments that do not belong to the functionality of this class to a new class
- Optimize properties in base classes (like BaseObject, etc.) for actual use
- Test every change you make to ensure that every refactoring step doesn’t affect the original functionality
- Specification (naming, syntax, etc.)
- Compiler optimization
- PS: Refactoring is a long-term process, and new features may need to be optimized with each urgent iteration, especially in multi-person development. If Code Review is not available before the project is released, it will be necessary during refactoring.
- How to slim down an AppDelegate?
- Mainly in order to ensure the function and efficiency and performance under the premise of the third party initialization code disassembly to other files for processing
- category
- Advantages: Simple and direct, without the assistance of any third party;
- Disadvantages: Adding attributes is not very convenient, need to use associated objects to achieve;
- FRDModuleManager
- Advantages: simple, easy to maintain, low coupling;
- Disadvantages: many modules need to allocate a lot of memory, objects are held for a long time (if there are dependencies, the priority is not clear)
- How to solve the problem?
- The main thread is stuck because it performs some time-consuming operations
- Time calculation: Execute in child threads if possible
- Image decompression: Force decompression in child thread
- Off-screen Rendering: Avoid causing off-screen rendering (pay attention to drawing methods)
- Optimize business process: reduce middle tier, business logic
- Rational thread allocation: UI operations and data sources are placed in the main thread to ensure that the main thread handles as few non-UI operations as possible, while controlling the number of App child threads.
- Preloading and delayed loading: balancing CPU and GPU usage; Loading visual content preferentially improves the speed of drawing the interface.
- How to Crash?
- Breakpoint: general Crash
- Zombie Object: Zombie object
- DSYM: a file that stores the mapping information of hexadecimal functions after iOS compilation (locate the range of the corresponding Crash code according to the memory address of Crash)
- How do I detect memory leaks? Did you get a memory warning? How did it work out?
- Dealloc method: A clumsy method of manual detection
- Third party libraries PLeakSniffer and MLeaksFinder: Automatic detection
- How to optimize App startup speed? (Before and after main)
- Set the environment variable DYLD_PRINT_STATISTICS or DYLD_PRINT_STATISTICS_DETAILS to 1 (more details), Xcode-> Edit Scheme-> Run-> Arguments, and add either of the above environment variables
Before main: Total pre-main time: 94.33 milliseconds (100.0%) Rebase /binding time: 3.09 milliseconds (3.09 milliseconds) // ObjC setup time: 10.78 milliseconds // initializer time: 18.50 milliseconds // various initializers used vs: / / in all kinds of initialization, the most time consuming as follows: libSystem. B.d ylib: 3.59 milliseconds (3.8%) libBacktraceRecording. Dylib: GTFreeWifi: 7.09 milliseconds (2.5 milliseconds)Copy the code
-
Factors influencing the elapsed time before main()
- The more dynamic libraries are loaded, the slower they start.
- The more ObjC classes, the slower the startup
- The more constructor functions C has, the slower it starts
- The more C++ static objects, the slower the startup
- The more + loads of ObjC, the slower it starts
-
Factors influencing the elapsed time after main()
- Perform applicationWillFinishLaunching time-consuming
- Loading of rootViewController and childViewController, loading of View and subviews
-
Specific optimization content:
- Remove dynamic libraries that are not needed
- Remove classes that are not needed
- Merge classes and extensions with similar functionality (categories)
- Compressed resource images
- Optimize applicationWillFinishLaunching
- Optimized rootViewController loading
- Dig for the last bit of performance optimization
-
PS: The loading before main() should be completed within 400ms. The whole process should not take more than 20 seconds. Otherwise, the system will kill the process and the App will fail to start
Open source library
This part is mainly related to the relevant library mentioned in the resume. It is recommended to be prepared for the open source library mentioned in the resume.
SDWebImage
SDWebImage is an open source library that almost every iOS developer has used. It is one of the most exposed open source libraries on a resume, and it is almost always asked in an interview, so be prepared to go there.
- The process from call to display?
- Determine if there is an ongoing operation based on the requested file URL path, and cancel and remove the operation mapping to the URL if there is.
- The placeholder placeholder is set regardless of whether the URL is empty and is executed synchronously in the current queue.
- Determines if the URL is empty, and if it is empty, the completedBlock callback is executed and ends.
- The URL is not empty. If it is the first time, initialization of the related class begins, for example: Load progress and its associated Block, SDWebImageManager (SDWebImageCache manages cache, SDWebImageDownloader manages), if not for the first time or the initial initialized instance, Because SDWebImageManager exists as a singleton.
- Start into the scope of SDWebImageManager, URL fault tolerant processing, create responsible for loading pictures and cancel the loading picture class, determine whether the current URL is in the blacklist, if there is a callback, return to the current operation class, no longer processing failed to download the URL, and end.
- If the URL is not in the blacklist, it will start to search in the memory cache and execute the doneBlock callback. In this callback method, it will determine whether the current operation has been canceled. If not, it will call back and asynchronously set the picture.
- If the memory cache is not found, it looks in the disk cache, usually asynchronously in the serial queue, finds the stored data according to the URL path and fetches it, then scales and unzip it back, performs a callback to set the image, and ends.
- If the disk is not found, download the picture, cache after downloading, set the picture; What are the optimizations made by SDWebImage for images: the child threads force decompression, the images obtained from the hard disk and downloaded are decompressed to improve the rendering efficiency and save the main thread’s workload.
ReactiveCocoa
The library is quite complex, and there are a lot of questions you can ask. The following is for reference only, and it is recommended to find your own answers (only after you understand them can you face them calmly).
- The difference between hot and cold signals?
- How does RAC listen for methods?
- What does the bind method do?
- What is the difference between RACObserver and KVO in RAC?
- What is the difference between an RAC map and a flattenMap?
tool
It is inevitable to encounter some questions about common tools, provide a few for reference only
- Git, SVN?
- Questions can be as simple as basic usage or related commands, or as deep as how Git works
- CocoaPods
- Pod Update vs. POD Install
- CI (Continuous integration, continuous deployment)
- Late update