Analysis of the latest IOS interview questions and Solutions

Time:2021-1-14

Many IOS interviews are written or operated directly on the computer. We have sorted out the latest types of questions that are asked the most

Using the third-party library, do you see how they implement it?

Example: SD, YY, AFN, MJ, etc!

<1> . SD as an example:

1. Entrance setima geWithURL:placeholderImage :options:
The placeholder image is displayed first, and then the sdweb image manager starts to process the image according to the URL.
2. Enter sdwebimagemanagerdownlo adWithURL:delegate : options:userInfo :,
Give it to sdimagecache to find out whether the image has been downloaded from the cache cheForKey:delegate : userInfo:.
3. First, find out whether there are pictures from the memory image cache,
If there is already an image cache in memory, sdimagecachedelete calls back to I mageCache:didFindImage : forKey:userInfo : to sdwebimagemanager.
4. Sdwebimagemanagerdelegate callback webimage geManager:didFinishWithImage :
Go to uiimageview + webcache to display pictures.
5. If not, generate nsinvocationoperation
Add to the queue to start looking from the hard disk to see if the picture has been cached.
6. According to the urlkey, try to read the image file in the hard disk cache directory.
This step is an operation in nsoperation, so it returns to the main thread to call notifydelegate: the result.
7. If the previous operation read the picture from the hard disk, add the picture to the memory cache
(if the free memory is too small, the memory cache will be cleared first).
Sdimagecachedelete callback I mageCache:didFindImage : forKey:userInfo :。
And then the callback shows the picture.
8. If the image cannot be read from the hard disk cache directory,
This indicates that the image does not exist in all caches, and the image needs to be downloaded,
Callback I mageCache:didNotFindImageForKey :userInfo:。
9. Share or regenerate a downloader sdwebimagedownloader to start downloading pictures.
10. Image download is done by nsurlconnection,
The related delegate is implemented to judge whether the picture is being downloaded, whether the download is completed or not.
11.c onnection:didReceiveData : medium
Using imageio to do the loading effect according to the picture download progress.
12. Connectiondidfinishloading: after the data is downloaded, it will be sent to sdwebimagedecoder for image decoding.
13. Picture decoding is completed in an nsoperation queue,
It won't slow down the mainline UI. If it is necessary to process the downloaded image twice,
It's better to finish it here. The efficiency will be much better.
14. In the main thread notifydelegateonmainthreadwithinfo:
Declare decoding complete,
imageDecoder:didFinishDecodingImage:userInfo
Call back to sdwebimagedownloader.
15.imageDownloader:didFinishWithImage:
Call back to sdwebimagemanager to inform the image download is completed.
16. Notify all downloaddelegates that the download is complete,
Call back to show the picture where you need it.
17. Save the picture to sdimagecache,
Memory cache and hard disk cache are saved at the same time.
Writing files to the hard disk is also completed in a separate nsinvocation operation,
Avoid slowing down the main thread.
18. Sdimagecache will register some message notifications during initialization,
Clean up memory image cache when memory warning or back to background
Clean up expired images at the end of the app.
19. Sdwi also provides uibutton + webcache and
Mkannotationview + webcache, easy to use.
20. Sdwebimageprefetcher can download pictures in advance,
Convenient for subsequent use.

2. Do you understand strongly connected components?

Concept:

Strong connected component of digraph: in digraph g, if there is a directed path from VI to VJ between two vertices VI and VJ (VI > VJ), and there is also a directed path from VJ to VI, then two vertices are called strong connected

connected)。 If every two vertices of a digraph G are strongly connected, G is said to be a strongly connected graph. The maximal strongly connected subgraph of a digraph is called strongly connected component

connected components)。

definition:

The strong connected components of digraph are as follows

In a digraph g, if there is at least one path between two vertices, two vertices are strongly connected.

If every two vertices of a digraph G are strongly connected, then G is said to be a strongly connected graph.

The maximal strongly connected subgraph of a directed graph of a non strongly connected graph becomes strongly connected components.

In the following figure, the subgraph {1,2,3,4} is a strongly connected component, because the vertices 1,2,3,4 are reachable in pairs, {5}, {6} are also two strongly connected components.

According to the definition directly, we use the method of bidirectional ergodic communication to find the strong connected component, and the time complexity is O (n ^ 2 + m). A better method is kosaraju algorithm or tarjan algorithm

The time complexity of both is O (n + m). This paper introduces tarjan algorithm.

Algorithm principle: (tarjan)

need-to-insert-img

Tarjan algorithm is based on the depth first search of graph. Each strongly connected component is a subtree in the search tree.

When searching, the unprocessed nodes in the current search tree are added to a stack, and whether the nodes from the top of the stack to the inside of the stack are a strong connected component can be checked when tracing back.

DFN (U) is defined as the order number (timestamp) of node u search. Low (U) is the secondary number of the earliest node in the stack that u or U’s subtree can trace back to.

It can be concluded from the definition that:

Low (U) = min {DFN (U), low (V)} ((U, V) is the Branch edge, u is the parent node of V, DFN (V), (U, V) is the backward edge (non transverse edge) pointing to the node in the stack))

When DFN (U) = low (U), all the nodes in the search subtree rooted in u are a strongly connected component.

3. Do you encounter tableview stuck? What are the causes of Caton?

The possible causes of tableview jam are as follows:

1. The most commonly used is the reuse of cell, registering reuse identifier

If a cell is not reused, a new cell will be created every time a cell is displayed on the screen

If there is a lot of data, a lot of cells will be piled up.

If you reuse a cell and create an ID for the cell, you will first go to the buffer pool to find a recyclable cell whenever you need to display the cell. If you do not re create the cell, you will find the recyclable cell

2. Avoid cell rearrangement

Cell layout filling and other operations are time-consuming. Generally, the layout is good when creating

If you can put the cell into a custom class, it will be laid out during initialization

3. Calculate and cache the properties and contents of the cell in advance

When we create the data source method of a cell, the compiler does not create the cell first and then determine the height of the cell

Instead, the height of each cell is determined according to the content. After the height is determined, the cell to be displayed is created. When scrolling, the height is calculated every time the cell enters the virtual window. The height is estimated in advance and the compiler is told. After the compiler knows the height, the cell will be created. Then the specific calculation method of the height is called. In this way, it can waste time to calculate the height other than the display cell

4. Reduce the number of controls in the cell

Try to make the layout of cells roughly the same. Different styles of cells can use unused reusable identifiers and add controls during initialization,

Those that are not applicable can be hidden first

5. Don’t use clearcolor, no background color, and don’t set transparency to 0

Rendering takes a long time

6. Use local update

If only a group is updated, reloadsection is used for local updating

7. Load network data, download pictures, use asynchronous loading and cache

8. Use less addview to dynamically add view to cell

9. Load the cells on demand. When the cells scroll quickly, only the cells in the range will be loaded

10. Don’t implement useless proxy methods. Tableview only abides by two protocols

11. Cache row height: the estimated height forrow and the layoutifneed in height forrow cannot exist at the same time. Only when the two exist at the same time can the “channeling” bug appear. So my suggestion is: as long as the row height is fixed, write the estimated row height to reduce the number of row height adjustments and improve performance. If it is a dynamic line height, do not write the estimation method. Use a line height cache dictionary to reduce the number of code calls

12. Don’t do extra drawing. In the implementation of drawRect: its rect parameter is the area to be drawn, and those outside this area do not need to be drawn. For example, in the above example, you can use cgrectintersectsrect, cgrectintersection or cgrectcontainsrect to determine whether image and text need to be drawn, and then call the drawing method.

13. Pre rendered image. When a new image appears, there will still be a short pause. The solution is to draw it once in the bitmap context, export it to uiimage object, and then draw it to the screen;

14. Use the correct data structure to store data.

4. What do you know about M, V and C communication rules?

MVC is a design idea, a framework pattern, and a strategy to organize all classes in an application. It divides your program into three parts, namely

M (model): it’s actually about “what”, what your program is essentially, and it works independently of the UI. The part of a program that deals with application logic and is usually responsible for accessing data.

C (controller): controls how your model is presented on the screen. When it needs data, it tells the model that you can help me get data. When it needs UI display and update, it tells the view that you can help me generate a UI to display data. It is a bridge between model and view.

V (view): the subordinate of the controller. It is the class to be used by the controller. It is used to build the view, which is usually created according to the model.

To understand how MVC works, you first need to understand how the three modules communicate.

MVC communication rules

Controller to Model

It can communicate directly in one way. The controller needs to present the model to the user, so it needs to know everything about the model, have the ability to fully communicate with the model, and be able to use the public API of the model at will.

Controller to View

It can communicate directly in one way. The controller uses view to lay out the user interface.

Model to View

Never communicate directly. Model is independent of UI and does not need to communicate with view directly. View obtains model data through controller

View to Controller

View cannot know too much about controller, so it needs to communicate indirectly.

Target

action。 First, the controller will leave a target for itself, and then give the matching action to view as the contact information. So view

When some changes are received, the view will send an action to the target, so as to achieve the purpose of notification. Here, view only needs to send

You don’t need to know how the controller executes the method.

Agent. Sometimes view doesn’t have enough logic to judge whether the user’s operation conforms to the specification. It will delegate the power to judge these problems to other objects. It just needs to get the answer, and it doesn’t care who gives the answer.

DataSoure。 The view does not have the right to display the data they display. The view can only request the data from the controller for display. The controller obtains the data of the model and provides it to the view after collation and typesetting.

Model access controller

Similarly, the model is independent of the UI, so it cannot communicate directly with the controller. However, when the information of the model itself changes, it will communicate indirectly through the following ways.

Notification & KVO is a method similar to radio station. When the model information changes, it will broadcast messages to interested people. As long as the controller receives the broadcast, it will actively contact the model to obtain new data and provide it to view.

From the above brief introduction, let’s briefly summarize the advantages of MVC mode.

1. Low coupling

2. It is conducive to the division of labor in development

3. It is conducive to component reuse

4. Maintainability

5. Is nstimer accurate? What do you think? If not, how to implement an accurate nstimer?

1. No

2. The reasons are as follows:

1. Nstimer is added to main runloop. The mode is nsdefaultrunloop mode. Main is responsible for all main thread events, such as UI interface operation and complex operation. In this way, timer will block in the same runloop.

2. The change of mode. There are two preset modes in the runloop of the main thread: kcfrnloopdefaultmode and uitracking runloop mode.

When you create a timer and add it to the default mode, the timer will get repeated callbacks. However, when you slide a Scrollview, runloop will switch the mode to tracking runloop mode. In this case, the timer will not be called back and the sliding operation will not be affected. Therefore, it will affect the situation of nstimer inaccuracy.

PS: defaultmode is the app’s normal state, and racking runloopmode is the state of tracking Scrollview sliding.

Method 1

1. The nstimer operation is performed in the main thread, but the nstimer instance is added to the specific mode of the main runloop. Avoid interference by complex operation or UI interface refresh.

self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(showTime) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

2. The nstimer is operated in the sub thread, and then the UI interface is modified in the main thread to display the operation results;


- (void)timerMethod2 {
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];
[thread start];
}
- (void)newThread
{
@autoreleasepool
{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(showTime) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
}

Conclusion:

At the beginning, the system implicitly started the main runloop of the main thread for us.

When creating a thread, you can actively obtain the runloop of the current thread. Each child thread corresponds to a runloop

Method 2

Use examples

Using Mach kernel level functions can use mach_ absolute_ Time() gets the count value of the tick count of the CPU, which can be accessed through the “mach_ timebase_ The “info” function achieves nanosecond accuracy. Then use mach_ wait_ until(uint64_ T deadline function, until the specified time, you can execute the specified task.

On data structure mach_ timebase_ Info is defined as follows:


struct mach_timebase_info {uint32_t numer;uint32_t denom;};
#include
#include
static const uint64_t NANOS_PER_USEC = 1000ULL;
static const uint64_t NANOS_PER_MILLISEC = 1000ULL * NANOS_PER_USEC;
static const uint64_t NANOS_PER_SEC = 1000ULL * NANOS_PER_MILLISEC;
static mach_timebase_info_data_t timebase_info;
static uint64_t nanos_to_abs(uint64_t nanos) {
return nanos * timebase_info.denom / timebase_info.numer;
}
void example_mach_wait_until(int seconds)
{
mach_timebase_info(&timebase_info);
uint64_t time_to_wait = nanos_to_abs(seconds * NANOS_PER_SEC);
uint64_t now = mach_absolute_time();
mach_wait_until(now + time_to_wait);
}

IOS interview questions: Tencent two sides and reference ideas:

What does the compilation process do?

1. C + +, objective C are compiler languages. When compiling language is executed, machine code must be generated by compiler first. Machine code can be executed directly on CPU, so execution efficiency is high.

The common languages for IOS development are objective and swift. Both are compiled languages, in other words, they need to be compiled to execute. The compilation of both depends on clang + llvm. OC and swift. Because they are similar in principle, it’s OK to know one!

IOS compilation

Both OC and swift use clang as the front end of the compiler and llvm (low level vrital machine) as the back end. So the simple compilation process is shown in the figure

Compiler front end

The task of compiler front-end is: syntax analysis, semantic analysis, generation of intermediate representation. In this process, type checking will be carried out, and if errors or warnings are found, which line will be marked.

Compiler backend

The compiler back-end optimizes machine independent code, generates machine language, and optimizes machine related code. The process of compiling IOS is as follows

Lvvm optimizer will generate bitcode, link period optimization and so on

Llvm machine code generator will generate different machine codes for different architectures, such as arm64.

Process of executing Xcode build once

When you select build in Xcode (shortcut key command + b), the following procedure will be performed

The compilation information is written into the auxiliary file to create the compiled file architecture( name.app )

Handle file packaging information, such as in the debug environment

Execute cocoapod precompile script

For example, checkpods is executed for projects that use cocoapod Manifest.lock

Compile each. M file, using the compilec and clang commands.

Compile each. M file, using the compilec and clang commands.

1.CompileC ClassName.o ClassName.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
2.export.US-ASCII
3.export PATH="..."
4.clang-x objective-c -arch x86_64 -fmessage-length=0 -fobjc-arc...
-Wno-missing-field-initializers ... -DDEBUG=1 ... -isysroot
IPhone simulator 10.1.sdk - FASM blocks... - I file mentioned above - f required framework - iquote required framework... - C classname. C - O classname. O

From this compiled command, we can see that

2. The principle of dictionary implementation;

1: Dictionary principle

Nsdictionary uses hash table to realize the mapping and storage between key and value

Methods: (void) setobject: (ID) anobject for key: (ID) akey;

The bottom layer of nsdictionary in Objective-C is actually a hash table

2: Hash principle

Hash table (also known as hash table) is a data structure directly accessed according to the key value. In other words, it can access records by mapping key values to a location in the table to speed up the search. This mapping function is called hash function, and the array of records is called hash table.

Given a table m, there is a function f (key). For any given key value, if the address of the record containing the key in the table can be obtained after substituting into the function, then table m is called hash table, and function f (key) is hash function.

Hash concept: the essence of a hash table is an array. Each element in the array is called a bin, in which key value pairs are stored.

3: Hash stored procedure

1. Calculate its hash value H according to the key.

2. Suppose the number of boxes is n, then the key value pair should be placed in the (H% n) box.

3. If there are key value pairs in the box, open addressing method or zipper method is used to solve the conflict.

When using zipper method to solve hash conflict, each box is actually a linked list, and all key value pairs belonging to the same box will be arranged in the linked list.

The hash table also has an important attribute: load factor, which is used to measure the emptiness / fullness of the hash table. To a certain extent, it can also reflect the efficiency of the query

Load factor = total key value logarithm / number of boxes

The larger the load factor is, the fuller the hash table is, the easier it is to cause conflicts, and the lower the performance is. Therefore, generally speaking, when the load factor is greater than a constant (maybe 1, or 0.75, etc.), the hash table will be automatically expanded.

When the hash table is automatically expanded, it usually creates two times as many boxes as the original number. Therefore, even if the hash value of the key remains unchanged, the result of the remainder of the number of boxes will change. Therefore, the storage location of all key value pairs may change. This process is also called rehash.

The expansion of hash table does not always solve the problem of large load factor. Assuming that the hash values of all keys are the same, their positions will not change even after the expansion. Although the load factor will decrease, the length of the linked list actually stored in each box will not change, so the query performance of the hash table cannot be improved.

Based on the above summary, careful friends may find two problems in hash table:

1. If there are many boxes in the hash table, it is necessary to re hash and move the data when expanding the capacity, which has a great impact on the performance.

2. If the hash function design is unreasonable, the hash table will become a linear table in extreme cases, and the performance is extremely low.

3. Understanding of block and function pointer;

Similarities:

Both function pointer and block can implement callback operation, and the declaration is very similar, and the implementation can be regarded as a code fragment.

Both function pointer type and block type can be used as the types of variables and function parameters. (after typedef defines an alias, the alias is a type.)

difference:

The function pointer can only point to the pre-defined function code block (it can be defined in other files and passed in dynamically through function parameters). The function address has been determined when compiling and linking.

Block is an Objective-C object in essence, which is a subclass of nsobject and can receive messages.

Function can only access global variables, while block code block can not only access global variables, but also have the readability of current stack memory and heap memory variables (of course, through__ The local variables modified by the block access indicator can also be modified in the block code block).

From the perspective of memory, function pointer is just a piece of executable code pointing to the code area, while block is actually an object dynamically created in stack memory during program running. You can send copy message to it to copy the block object into heap memory to extend its life cycle.

4. How do you think about your architecture when you start a project?

Reference article 1

Reference article 2

5. What do you know about UIKit structure?