1. Nil, nil, NSNULL ‘What’s the difference?

  • Nil is the equivalent of an empty address in memory. Represents a null pointer
  • NSNULL represents an empty object

2. How to implement a thread-safe NSMutableArray?

  • NSMutableArray is thread-unsafe and can cause crashes or data errors when multiple threads operate on arrays at the same time
  • Thread locks: Use thread locks to lock reads and writes to arrays
  • Dispatch queue: use more dispatch queue and less synchronization lock. It is pointed out in “serial synchronization queue” that reads and writes are arranged in the same queue to ensure data synchronization.
  • Through the concurrent queue, combined with the barrier of GCD, data synchronization can not only achieve thread safety, but also more efficient than the serial synchronization queue.

3. How to define the uniqueness of an iOS device?

  • UUID + keyChain storage
  • Get UUID
[[UIDevice currentDevice] identifierForVendor] UUIDString]

Copy the code
  • When you upgrade or reinstall the software, the UUID will change, and when you retrieve the UUID, the value will be different, but it will still be the same device
  • Keychain: a password management system in the Mac OS of apple. The information stored in the keychain is not lost after the App is deleted. After the App is reinstalled, the data is still valid. Therefore, the UUID can be stored in the keychain and obtained from the keychain when needed to ensure the uniqueness of the UUID.

4. Are atomic modified properties completely safe? Why is that?

  • Not necessarily. Security is limited to Setter and Getter accessor methods
  • The mutex method is used to prevent multiple threads from accessing the same memory address and causing data errors.
  • However, it cannot guarantee the safety of multithreading. When two asynchronous threads are opened to frequently perform +1 operation on OJB, it is not thread-safe. The solution is to lock

5. What should I pay attention to when using isEqual and hash methods?

  • hash
    • Performs the bit or operation on the hash value of the key attribute as the hash value
  • isEqual
    • The == operator determines if it is the same object, because the same object must be identical
    • Checking whether the type is the same can not only improve the efficiency of equivalence, but also avoid the potential risk of implicit type conversion
    • Check if the object is nil. Check the validity of arguments
    • Each attribute is judged by default judgment method
    • Returns the and results of all attribute evaluations

6. What’s the difference between ID and instanceType?

  • The same
    • Instancetype and ID are both universal Pointers to objects.
  • Difference:
    • Id does not determine the true type of an object at compile time. Instancetype does determine the true type of an object at compile time.
    • Id can be used to define variables, as a return value type, as a parameter type; Instancetype can only be used as a return value type.

7. Explain your understanding of the Super keyword

  • Sending messages using the super keyword is converted by the compiler to calling objc_msgSendSuper and related functions
id objc_msgSendSuper(struct objc_super *super, SEL op, ...) ;Copy the code
  • The super is no longer the super we wrote when we called [super init], it’s the struct objc_super structure pointer.

What do 8.@synthesize and @dynamic do, respectively?

  • At sign property has two words, at sign synthesize, and at sign dynamic. If at sign syntheszie and at sign dynamic don’t write, then the default is @syntheszie var = _var;
  • The semantics of the at sign synthesize is that if you don’t implement setter and getter methods manually, then the compiler automatically adds them for you.
  • @dynamic tells the compiler that setter and getter methods for a property are implemented by the user and not automatically generated. (Of course, you only need to provide getters for readonly properties).
  • If a property is declared as @dynamic var, and you don’t provide @setter and @getter methods, that’s fine at compile time, but when the program runs to instance.var =someVar, the lack of setter methods will crash the program; Or when someVar = var is run, it will also crash due to the lack of getter methods. Compile time is fine, and the corresponding method is executed at run time, which is called dynamic binding.

9. Reflection in Objective-C?

  • IOS reflection: The runtime selects which instances to create and dynamically selects which methods to call.
// whether the current object is an instance of this Class or its subclasses - (BOOL)isKindOfClass:(Class)aClass; // whether the current object is an instance of this Class - (BOOL)isMemberOfClass:(Class)aClass; // whether the current object complies with the Protocol - (BOOL)conformsToProtocol:(Protocol *)aProtocol; // whether the current object implements this method - (BOOL)respondsToSelector:(SEL)aSelector;Copy the code
  • Three ways to get a Class
// Get class class = NSClassFromString(@"NSString"); NSLog(@"class type : %@", class); STR = [[class alloc] init]; NSLog(@"%@", [str class]); // Get class NSLog(@"%d", class== nsString.class);Copy the code
  • The practical application
    • Dynamic page hopping is performed based on the data pushed from the background. After hopping to the page, corresponding operations are performed based on the returned data.
  • Advantages and disadvantages of using reflection in OC:
  • Advantages:
    • Loose coupling, with less dependency between classes
    • Build flexible
  • Disadvantages:
    • Bad for maintenance. Using reflection obscures what is actually happening inside the program and hides the logic of the program. This way of bypassing source code is more complex than direct code and increases maintenance costs
    • Poor performance. Indirect memory hits using the reflection match string are slower than direct memory hits. Of course, the degree depends on the usage scenario, and the performance impact can be negligible if only as a part of the program that is rarely covered. However, if reflection is used in the core logic of an application where performance is critical, the performance issue becomes particularly important

Typeof and __typeof, typedef?

  • typeof
    • Is a unary operation that precedes an operand, which can be of any type
    • We automatically recognize the variable type and return it based on the variables inside the typeof () parentheses.
    • Typeof is commonly used within blocks to avoid the problem of circular references.
  • typedef
    • Define an alias for a type, not just a simple macro substitution.
    • Typedefs are commonly used for naming (enums and blocks)

11. How to use self, weakSelf and strongSelf?

__weak __typeof(self)weakSelf = self;    //1

[self.context performBlock:^{      
    [weakSelf doSomething];          //2
     __strong __typeof(weakSelf)strongSelf = weakSelf;  //3
    [strongSelf doAnotherSomething];        
}];

Copy the code
  • 1. Use the __weak __typeof local variable to operate on self at compile time. The reference count remains the same. The block captures this local variable as its own property, accesses this property, and thus accesses self, since they all have the same memory address.
  • 2. Because weakSelf and self are two variables,doSomething may directly reduce the reference count of self to 0. So when [weakSelf doSomething], it’s hard for you to control whether or not self is going to be released. WeakSelf just watches.
  • 3.__strong __typeof is actually a strong reference to weakSelf during compilation. The reference count of the pointer joint self is increased. But you’re in a block, and the life cycle is only in the scope of the current block. So, when this block ends,strongSelf is released. Does not affect the life cycle of self outside the block.
  • 4. If you need to access self’s methods and variables within the Block, it is recommended to use weakSelf.
  • 5. If self needs to be accessed multiple times within a Block, strongSelf is used.

12. How to change obJ-C code to C++/C code?

Clang-rewrite-objc-fobjc-arc-fobjc-runtime =macosx-10.13 main.mCopy the code

13. Do you know where to download apple source code?

  • opensource.apple.com/source

16. What is the difference between objc_getClass(), object_getClass(), and Class?

14. What is the difference between objc_getClass(), object_getClass(), and Class?

  • All return Class objects
  • A Class method
    • A Class method can be called on either a Class object or an instance object, can be nested, and always returns a Class object of its own.
  • Object_getClass method
    • Object_getClass and class can also be nested, but object_getClass gets the address to which its ISA points.
  • Objc_getClass method
    • Objc_getClass cannot be nested because the argument is of type char and has the same effect as class

15. What are the advantages of NSCache over NSDictionary?

  • NSCache A set of caching mechanisms provided by Apple
    • Mainly for memory cache management;
    • Before we introduced NSCache, we managed caches using NSMutableDictionary, such as:
@property (nonatomic, strong) NSMutableDictionary *operationCache; @property (nonatomic, strong) NSMutableDictionary *imageCache;Copy the code
  • However, NSMutableDictionary is not thread-safe, which is clearly stated in Apple’s official documentation, and if NSCache is used, these problems do not occur.
  • Similarities:
    • The NSCache and NSMutableDictionary functions are basically the same.
  • The difference between:
    • NSCache is thread-safe, NSMutableDictionary threads are not; NSCache threads are safe, and classes developed by Mutable are generally not thread-safe;

    • NSCache automatically frees memory when it runs out of memory (so always check whether data is empty when fetching from the cache).

    • NSCache can specify the cache quota. If the cache quota is exceeded, the memory cache quota is automatically released.

      • Number of cache

      @property NSUInteger countLimit;

      • Caching cost

      @property NSUInteger totalCostLimit;

    • Apple has packaged NSCache with more methods and properties than NSMutableDictionary;

Code demo
  • First define the cache pool and lazily load the initialization:
#import "viewController.h" @interface ViewController () <NSCacheDelegate> strong) NSCache *cache; @end @implementation ViewController - (NSCache *)cache { if (_cache == nil) { _cache = [[NSCache alloc] init]; _cache.countlimit = 5; _cache.totalCostLimit = 1024 * 5; } return _cache; } - (void)viewDidLoad { [super viewDidLoad]; Value: string (int I = 0; i < 10; i++) { [self.cache setObject:[NSString stringWithFormat:@"hello %d",i] forKey:[NSString stringWithFormat:@"h%d",i]]; NSLog(@" add %@",[NSString stringWithFormat:@"hello %d", I]); } for (int I = 0; i < 10; i++) { NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]); }}Copy the code
The console output is:

It can be seen from the output results:
  • When we use NSCache to create a cache pool, we can set the cache quota flexibly.

  • When the number of applications exceeds our limit, the first one created will be removed;

  • If it has been removed, then when we print the data in the cache, only the data created later will be left.

  • Demonstrates the proxy method for NSCache

Set the proxy object first:
  • (void)viewDidLoad { [super viewDidLoad]; Self.cache. delegate = self.task = task; Calling the proxy method: HERE I use just one method to demonstrate:
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{NSLog(@" cache removed %@",obj); }Copy the code

  • The results show that NSCache is much more powerful than NSMutableDictionary.
When a memory warning is encountered
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Remove memory [self.cache removeAllObjects] when receiving a memory warning; For (int I = 0; i < 10; i++) { NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]); }}Copy the code
Console output:

  • As you can see from the result, all data in the NSCache cache pool will be empty after the data is cleared after receiving a memory warning!
When a memory warning is received and removeAllObjects is called, data cannot be added to the cache pool again
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; [self.cache removeAllObjects] [self.cache removeAllObjects] [self.cache removeAllObjects]; For (int I = 0; i < 10; i++) { NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]); }} // Touch events, - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[self.cache removeAllObjects]; For (int I = 0; i < 10; i++) { [self.cache setObject:[NSString stringWithFormat:@"hello %d",i] forKey:[NSString stringWithFormat:@"h%d",i]]; / / NSLog (@ "add % @", [nsstrings stringWithFormat: @ "hello, % d", I]); } for (int I = 0; i < 10; i++) { NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]); }}Copy the code
The console output is:

  • From the output, we can see that when we receive a memory warning and call removeAllObjects, we cannot add data to the cache again.

16.NSCache, NSDictionary, NSArray

NSArray
  • As an ordered collection of stored objects, NSArray is probably the most used collection class.
  • Performance characteristics
    • Inserting/deleting elements at the beginning and end of an array is usually an O(1) operation, while random inserting/deleting is usually O(N)
  • Useful method
    • Most methods of NSArray use isEqual: to check the relationship between objects (for example containsObject:). There is a special method
indexOfObjectIdenticalTo:

Copy the code
  • Used to check for pointer equality, this method can greatly speed up searches if you make sure to search in the same set
NSDictionary
  • A dictionary stores arbitrary object key-value pairs. For historical reasons, the initialization method uses the opposite object to value method
[NSDictionary dictionaryWithObjectsAndKeys:object, key, nil]

Copy the code
  • The new shortcut syntax starts with key
@{key : value, ... }Copy the code
  • Keys in NSDictionary are copied and need to be constant. If a key is changed after it is used to put a value in the dictionary, the value may become unreachable. An interesting detail is that keys are copied in NSDictionary, but only retained when using a Toll-free bridged CFDictionary. CoreFoundation classes have no method for copying generic objects, so copying is not possible at this point (*). This only works if CFDictionarySetValue() is used. If you use toll-free bridged CFDictionary with setObject:forKey, apple adds extra processing logic to make the keys copied. The reverse is not true — using CFDictionarySetValue() on an NSDictionary object converted to CFDictionary calls back setObject:forKey and copies the key.
NSCache
  • NSCache is a very strange collection. Added in iOS 4/Snow Leopard, mutable and thread-safe by default. This makes it ideal for caching objects that are expensive to create. It automatically reacts to memory warnings and cleans itself up based on configurable costs. In contrast to NSDictionary, keys are retained rather than copied.
  • The collection method of NSCache is uncertain, and NSCache can be set up to support automatic collection of objects implemented by the NSDiscardableContent protocol. A popular class that implements this property is NSPurgeableData, which was added around the same time, but was non-thread-safe prior to OS X 10.9
  • NSCache performance:
    • So how does NSCache survive NSMutableDictionary? The added thread-safety is bound to cost some;
IOS builds the cache with NSCache instead of NSDictionary
  • When system resources are running out, NSCache can automatically delete the cache. If you’re using a regular dictionary, you’ll write your own hooks and manually delete the cache when the system notifies you, and NSCache will delete the objects that are being used for the longest time
  • NSCache does not copy the key, but keeps it. This behavior is also possible with NSDictionary, but requires more complex code to write. The reason NSCache objects do not copy keys is that many times keys are used by objects that do not support copying operations. Therefore, NSCache objects do not automatically copy keys, so this class is more convenient than dictionaries in cases where keys do not support copy operations
  • NScache is thread-safe, NSDictionary is not. Multiple threads can access NSCache at the same time without writing the locking code themselves. Thread-safety is often important for caches because a developer may be reading data from a thread, and if the specified key cannot be found in the cache, the data corresponding to that key must be downloaded

17. What are delegate, Notification, and KVO?

Delegate.
  • Delegation is a form of agreement, which, as the name implies, entrusts someone else to do something for you.
  • Very strict grammar. All events to be heard must be clearly defined in the Delegate protocol, with clear syntax and easy to read.
  • Compile warnings/errors occur if a method in the delegate is not implemented
  • When releasing the proxy object, be careful to change the delegate to nil. If the setting fails, the call to the free object method will cause memory crash
Notification (notice)
  • There’s one in iOS app developmentNotification Center(Notification center) concept. It is a singleton that allows some objects to be notified when an event occurs
  • Multiple objects can respond to a given notification, making the 1-to-many approach easy to implement
  • The controller can pass the Context object (dictionary), which carries custom information about sending notifications
  • It is difficult to track the application work and control process during debugging;
KVO
  • KVO provides a mechanism to automatically notify responding observers when the properties of a specified object being observed are modified. KVC(key-value coding) is the foundation of KVO, which is based on the Runtime
  • Provides an easy way to synchronize two objects. For example: synchronization between Model and View;
  • The ability to respond to state changes of objects that we did not create, namely internal objects, without changing the implementation of internal objects (SKD objects);

18. How to select Delegate, Notification, and KVO?

All three patterns involve one object passing events to another object without coupling them.
  • Delegate. One-on-one
  • Notification one-to-many, many-to-many
  • KVO one-to-one
The three have their own characteristics:
  • The delegate syntax is concise, easy to read, and easy to debug
  • Notification is flexible and can be used across multiple classes
  • KVO implements attribute listening, model and View synchronization
  • You can use different approaches depending on the scenarios you encounter in your actual development

19. If you were to design a notification center, what would it be?

Personal understanding: Refer to existing notification centers
  • 1. Create a notification center singleton class with a global NSDiction that holds notifications
  • 2. For classes that register notifications, use the registration notification name as the key, the method and class that execute it, and some parameters as an array of values
  • 3. To send notifications, you can call the notification center and find the corresponding class and method through the dictionary key(notification name) to execute the call and pass the value.

20. What is the difference between a structure and an array?

  • Structs can hold different types of elements, whereas arrays can only hold the same type
  • Structure types need to be defined ourselves. An array is a different type plus the number of elements
  • Structure memory allocation is very special, using the alignment principle, not necessarily the sum of the bytes of all elements, but the array must be the sum of the bytes of all elements.
  • Struct Pointers can be pointer names -> struct element names (take elements); Arrays don’t work.

21. What is the implementation principle of NSDictionary

  • Hash table (NSDictionary uses hash tables to map and store keys and values)

22. What are the interaction modes between OC and JS?

  • By blocking urls
  • Using a MessageHandler (WKWebView)
  • JavaScriptCore (UIWebView)
  • Using the three-party library WebViewJavascriptBridge, can provide JS call OC, and OC call JS

23. What are the ways in which JS calls OC code?

Method 1: Intercept urls
  • By intercepting urls (for UIWebView and WKWebView)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *url = request.URL.absoluteString; If ([url rangeOfString: @rangeofString]. Location! = NSNotFound) {return NO; } return YES; }Copy the code
Method 2: messageHander
  • When the JS side wants to send some data to iOS, they call the following methods to send it.
  • Window. Its. MessageHandlers. < method name >. PostMessage (< data >) in the above code write complains JS end, cause behind the web business does not perform. This can be done using a try-catch.
  • Then the processing method in OC is as follows. It is the proxy method of WKScriptMessageHandler. Name corresponds to the method name in JS above.
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

Copy the code
Method 3: WebViewJavascriptBridge
1. Set the webViewBridge _bridge = [WKWebViewJavascriptBridge bridgeForWebView: self. WebView]; [_bridge setWebViewDelegate:self]; 2. Register the handler method, which needs to negotiate the method name with the preceding segment, which is used by JS to call Native. [_bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {// OC call NSString *scanResult = @"http://www.baidu.com" responseCallback(scanResult); }]; ResponseCallback :^(id responseData) {NSLog(@responsedata) {responseCallback:^(id responseData) {NSLog(@responseData); %@",responseData); }];Copy the code

24. What are the ways in which OC calls JS code?

A: stringByEvaluatingJavaScriptFromString direct call
NSString *jsStr = @" JS code executed "; [webView stringByEvaluatingJavaScriptFromString:jsStr];Copy the code
Method 2: Use JavaScriptCore framework
# import < JavaScriptCore/JavaScriptCore. H > - (void) webViewDidFinishLoad webView: (UIWebView *) {/ / access to the content of JS in the webView JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; NSString *runJS = @" JS code executed "; [context evaluateScript:runJS]; }Copy the code

25. The difference between Block and Protocol. What problem is a Block used to solve

  • A common feature of a proxy and a Block is the callback mechanism. The difference is that the proxy has more methods, more dispersed, common interface, more methods, and also uses a delegate to decouple
  • Code using blocks is more centralized and uniform, and asynchronous and simple callbacks to blocks are better

What problems are blocks used to solve? Personal opinion:

  • Blocks are created for scheduling between multiple threads;
  • Block is also an OC object that can be passed as an argument, which is easy to use, simple, flexible, and requires very little code to implement code callbacks. Much less code than Protocol

26. How do dictionaries work? How to get a value from 100W quickly?

  • NSDictionary uses hash tables to map and store keys and values. The design of hash functions affects the search and access efficiency of data.
(void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
Copy the code
  • NSDictionary in Objective-C is actually a hash table underneath, and in fact dictionaries in most languages are implemented through hash tables
Hash table:
  • The essence of a hash table is an array, and each element in the array is called a bin, which holds key-value pairs. The length of the array is the number of boxes.
  • Hash tables have another important property: Load factor, which is used to measure the degree of empty/full hash table, can also reflect the efficiency of query to some extent. The calculation formula is as follows: Load factor = total key-value logarithm/number of bins A larger load factor means that the hash table is more full, more likely to cause conflicts, and lower performance. Therefore, in general, when the load factor is greater than a constant (maybe 1, 0.75, etc.), the hash table will automatically expand.
  • Reference: www.jianshu.com/p/88dfc8f40…

27. IsEquel, Hash, isEquelToString

isEquel
  • IsEquel is used to compare two objects for equality. Unlike ==(address comparison), * * isEquel first compares the addresses of two objects and returns YES if they are the same. If they are different, isEquel compares the object type and the value of the attribute
  • IsEquel is comparing two NSObject methods
hash
  • Hash is a class method that can be called by any class and returns an NSInteger value. (If two objects are equal, they must have the same hash value. However, if two objects have the same hash value, it does not necessarily follow that they are equal.)
isEquelToString
  • IsEquelToString compares two string values for equality

Notifications no longer need to be removed manually in iOS 9

  • The iOS 9 notification Center holds registrantsunsafe_unretainedPointer to the
  • After iOS 9, the notification center holds registrantsweakPointer to the

29. How to KVO NSMutableArray

  • In general, KVO is triggered only when a value is changed by calling the set method. But NSMutableArray’s set method is not triggered when it calls the addObject or removeObject family of methods. So in order to implement THE KVO of NSMutableArray, we are provided with the following methods
@property (nonatomic, strong) NSMutableArray *arr; // Add element [[self mutableArrayValueForKey:@"arr"] addObject:item]; [[self mutableArrayValueForKey:@"arr"] removeObjectAtIndex:0];Copy the code

30. Difference between function pointer and Block

Similarities:
  • Both can be viewed as a snippet of code.
  • Both function pointer types and Block types can be used as types for variables and function parameters
Difference:
  • Function Pointers can only point to pre-defined blocks of function code, and the address of the function is determined when the link is compiled. From a memory perspective, a function pointer is simply a piece of executable code that points to a code area
  • A block is essentially an OC object, a subclass of NSObject, which is dynamically created in stack memory during program execution. You can send a copy message to it to copy the block object to the heap memory to extend its life cycle.