This is the record of my interview with Baidu. I can answer some questions. If I cannot answer them or have better answers, I will put relevant links for your reference. Senior Tang Qiao said that these are basic questions about iOS and we should have a deep understanding of them. When I first saw them, I couldn't answer most of them because I didn't think about them carefully. Most of the concepts here will be encountered in the process of learning OC, but you still have to write code to have a deeper understanding. Anyway, I was confused when I saw those design patterns. I knew every word, but I didn't know what they meant. Even now, there are some things that I don't understand very well. Objective-C Low Level Objective-C runtime library: Objective-C object model, underlying implementation structure of Block, message sending, message forwarding, category, method implementation, class loading. I rarely touch upon runtime, and have not studied it systematically. Moreover, I forget what I have read many times, so here are some links to good articles for reference. These issues have been explained in depth in "iOS 7 Programming Pushing the Limits" (I have the electronic version, which is a pirated copy. Here is the address of this book on Github. After I start working, I will buy back all the pirated books I read last year. There is no iOS 8 version. I don't know if it is due to too many pirated copies). In addition, senior Tang Qiao has written an article discussing the first two: 1. "Objective-C Object Model and Application" Tang Qiao also mentioned the changes brought about by iOS 64-bit in the postscript: Then let's take a look at Session 404 Advanced in Objective-C, which talks about related things starting from the 36th minute. Oh, I don't understand it, so let's take a look at this. The Further Reading: objc_explain_Non-pointer_isa section of "iOS 7 Programming Pushing the Limits" discusses this issue. 2. " On the Implementation of Objective-C Block " The content is very informative, especially the part about Block types. I strongly recommend taking the quiz mentioned at the beginning of the article: Objective-C Blocks Quiz. 3. Message sending and message forwarding Message sending is relatively easy to understand. Let's first understand the runtime. You can check the official document "Objective-C Runtime Guide". When I was learning other languages before, I didn't pay attention to what happened behind the call of the function. In Objective-C, calling a method on an object is called sending a message, such as [receiver message]; this line of code, when compiled, the compiler converts it into a call to the underlying C function objc_msgSend: objc_msgSend(receiver, selector); at runtime, which method to call is completely determined by the runtime, and the called method can even be replaced at runtime. This is the fundamental reason why Objective-C is called a dynamic language. As for message forwarding, to be honest, I don't know the application scenario of this yet. Most of the blogs I have seen say that message forwarding gives you a remedy to deal with the unimplemented method to prevent crashes or implement a mechanism similar to multiple inheritance. I have a question, why not implement that method, but deal with it in the forwarding mechanism with a high cost. In the 12th tip of the book "Effective Objective-C 2.0", @dynamic is used to demonstrate the example of implementing dynamic method resolution to illustrate the significance of message forwarding. To be honest, I still don't understand the significance of this. Here is a Chinese translation of the official document and some annotations. 4. Implement categories and methods I found this article from a post-90s person who is much more capable than me: "Dig Deep into Objective-C Runtime (3) - Messages and Categories" (the original link of the article conflicts with the handling of Jianshu, so the link given here is the blog address, not the specific address of the article, but it is easy to find). 5. Class loading You can read this blog: "Objective-C Class Loading and Initialization". I checked the author's Github and found that he was a foreign programmer whom I followed before. Looking at his repo and stars, the quality is guaranteed. Looking at the list of blog posts, there are a lot of in-depth content, a treasure trove. In addition, this issue is also discussed in Section 51 of the book "Effective Objective-C 2.0" "Streamlining the Implementation of Initialize and Load". I was confused at first, but now I can finally understand it. Core Data: Multi-threaded synchronization of large amounts of data I have put this question in a separate article here, adding more basic knowledge and introduction. Step 1: Build a Core Data multithreaded environment The first thing to solve this problem is to build a Core Data multi-threaded environment. NSManagedObjectContext is not thread-safe. You can't just start a background thread to access the managed object context for data operations and call it multi-threading support. Core Data has good support for multi-threading. When initializing NSManagedObjectContext, you can specify the concurrency mode. There are three options: 1.NSConfinementConcurrencyType This mode is for backward compatibility. When using this mode, you should ensure that the context is not used in other threads, but this is difficult to ensure and is not recommended. This mode has been deprecated in iOS 9. 2.NSPrivateQueueConcurrencyType Creates and manages a context in a private queue. 3.NSMainQueueConcurrencyType This mode is similar to the second mode, except that the context is bound to the main queue and therefore very close to the application's event loop. This mode is used when the context is related to UI updates. The solution for building a multi-threaded Core Data environment is generally as follows: create a NSMainQueueConcurrencyType context to respond to UI events, and use the NSPrivateQueueConcurrencyType context for other operations involving a large amount of data that may block the UI. Now that the environment is built, how do we implement multi-threaded operations? The official document "Using a Private Queue to Support Concurrency" demonstrates this for us. When operating in the context of a private queue, you should use the following methods:
When using managed object context in different threads, we do not need to create a background thread and then access the managed object context for operation. Instead, we hand it over to the private queue bound to the context itself for processing. We only need to perform operations in the Block of the above two methods. Moreover, this method should also be used to perform operations in the context of NSMainQueueConcurrencyType, so as to ensure that the context itself is operated in the main thread. Step 2: Data synchronization The simplest solution for multi-context synchronization is as follows:
After performing a save operation, NSManagedObjectContext will issue NSManagedObjectContextDidSaveNotification, which contains all the change information of the context, including information about newly added, updated, and deleted objects; and the mergeChangesFromContextDidSaveNotification(_ notification) method is used to merge changes that occur in other contexts. If the context does not observe the NSManagedObjectContextDidSaveNotification notification of other contexts, and the persistent store has been modified by other contexts when saving, then there is a high probability that there will be differences. At this time, there are several options for synchronization: choose to save the version in the context, replace the context version with the persistent store version, or merge the two versions. This synchronization method is determined by the mergePolicy property of NSManagedObjectContext. 1.NSErrorMergePolicy The default strategy is to fail to save when there is a conflict, keep the persistent store and context as they are, and return an error message. This is the only merge strategy that returns an error message. 2.NSMergeByPropertyStoreTrumpMergePolicy When there is a conflict between the versions in the persistent store and the context, the version in the persistent store takes precedence and the context is replaced with the version in the persistent store, but non-conflicting changes in the context will not be affected. 3.NSMergeByPropertyObjectTrumpMergePolicy In contrast to the above, the version in the context takes precedence and the persistent store uses the version in the context to replace it, but non-conflicting changes in the persistent store are not affected. 4.NSOverwriteMergePolicy Use the version in the context to force overwrite the version in the persistent store. 5.NSRollbackMergePolicy Abandon all changes in the context and replace them with the version in the persistent store. Synchronization is a very complicated matter. In fact, you still need to choose a synchronization solution based on actual needs. The first of the two solutions above is simple in concept and easy to implement, while the second is more complicated and relatively dangerous, so you need to choose a synchronization strategy carefully. Another point to note is that if you need to use a managed object across threads, do not use the managed object directly in other contexts, but fetch the object into the context using the objectID of the object. ***, handle a lot of data Multithreading and synchronization issues are solved, and the biggest difficulty is: large amounts of data. Large amounts of data mean that we need to pay attention to memory usage and performance. When writing code, we need to remember the following rules: 1. Cache required data as much as possible, and keep irrelevant data in faults state. 2. Be as accurate as possible when fetching and avoid introducing irrelevant data. 3. When building multiple contexts, try to centralize similar managed objects to minimize the need for merging. 4. Improve operational efficiency and make full use of new features such as Asynchronous Fetch, Batch Update, and Batch Delete. Multithreaded Programming In iOS programming, multithreading needs to be handled in the following situations: UI events must be performed in the main thread, and others can be performed in the background; and tasks that take a long time or block threads should be performed in the background thread. There are several multithreading technologies in iOS: threads, GCD, and NSOperationQueue. Threads are a more complex technology, and multithreaded programming has always been "complexity is death". It is recommended to use the latter two as much as possible, but threads have an advantage that the latter two do not have: they can accurately guarantee the time of task execution. GCD stands for Grand Central Dispatch, which is the external code name of the libdispatch library and is implemented based on the bottom layer of C; and NSOperationQueue, commonly known as the operation queue, is implemented based on GCD. NSOperationQueue can basically do what GCD can do, and it also has some features that are not easy to implement in GCD, such as suspending and canceling tasks. Although GCD also provides the function of canceling tasks in iOS 8, there are great limitations on suspending and canceling tasks in GCD. Although in most cases, a higher-level abstraction API, that is, NSOperationQueue, should be used, I prefer GCD for general background tasks, mainly because GCD is easy to use with Blackcok and very convenient. How to choose, the following two links are worth reading about this issue: StackOverflow: NSOperation vs. Grand Central Dispatch Blog: When to use NSOperation vs. GCD In addition, the following articles are recommended: objc's concurrent programming special "Concurrent Programming" and its Chinese translation version; Lei Chunfeng's blog "iOS Concurrent Programming Operation Queues"; NSHipster's "NSOperation". Design Patterns Evaluate the advantages and disadvantages of several design patterns: Delegate, Notification, KVO I don't think this is a good question. Instead of comparing the pros and cons of these design patterns, it is better to talk about their respective characteristics, because they are designed to solve certain types of problems and have their own suitable usage scenarios. In addition, here is an introduction to design patterns in iOS: iOS Design Patterns. Why do questions like to compare these three design patterns? Notification and KVO are both used to assist communication between objects: an object listens to the occurrence of an event, and when an event occurs, the object will be notified and respond. These sentences are probably what I have read in books before. If you have never been exposed to design patterns before, you will always see vague words such as events and responses when you first learn them, which will make you confused. Well, I am talking about me. But delegate, it should be said that it does not have the function of listening, but when an event occurs or the time is right, it requires the delegate object to do something. When I first started learning OC, a book compared the delegate to an assistant. I didn’t understand it very well at that time, but now I think this metaphor is very appropriate. Although the delegate pattern can be seen everywhere in OC and is widely present in the UIViewController class, I only encountered a custom protocol/delegate once in the process of developing FaceAlbum, and later replaced it with KVO. Compared with the Notification and KVO modes, using the delegate mode you will know exactly what the object's delegate can do, because to become the delegate of an object, the object must comply with the specified protocol, which specifies the methods that the delegate object needs to implement. ,包括:NSNotification和KVO和 ... The response method is predefined in the protocol. Having said so much, it is not intuitive. Let me talk about a practical scenario. For example, when selecting a cell in UICollectionView, you hope that the title can track the number of selected cells. This can be achieved with both NSNotification and KVO, but I prefer KVO, which feels more elegant. Because when using NSNotification mode, when selecting a cell, you have to manually post a notification in the selection method, while KVO only needs to implement KVO-compatible methods for the observed properties; and for the delegate, you have to make your own delegate. When facing some system events, such as the appearance and disappearance of the keyboard and changes in the photo library, it is more natural to use NSNotification, because KVO is limited to tracking object properties. |
<<: How good is the product manager in a programmer’s dream?
>>: Rumor has it that Alibaba will swallow up Sina and take over Weibo
Internet advertising generally follows the follow...
A few days ago, an expert revealed that Xiaohongs...
What is a conversion? 1. Conversion rate Let’s ta...
The Internet is a sea of pictures and texts, an...
A few days ago A shocking video of the constructi...
From 0:00 to 24:00 on April 2, 31 provinces (auto...
The concept of private domain traffic has been ve...
Introduction to commonly used chart resources for...
Google recently released a new job posting on its...
Fans can breathe a sigh of relief. After several ...
What is ASO ? ASO is the abbreviation of " A...
You have been sitting on the toilet for a long ti...
Multiple media reported that Douyin Pay has been ...
Card-Film and Television Commentary Training Camp...
It’s the Lantern Festival again. Have you thought...