Manual burying, automatic burying, visual burying
Manual burying, automatic burying and visual burying are commonly used data collection methods in iOS applications. They each have their own characteristics and applicable scenarios, and I will introduce them in detail below.
Manual buried points
Manual burying means that developers actively insert burying code into the code to collect the required data. Developers need to add code to the specific method of triggering the event to record relevant information, and upload the data to the background according to the reporting strategy. The advantage of manual tracking is that it is highly flexible and can customize the collected data content and reporting method according to specific needs. However, there are also some problems with manual buried points, such as the need to release new buried points, the coupling of buried point code and business code, etc. [1]
Automated buried points
Automated tracking uses automated tools to collect data without manually inserting tracking codes. The automated tracking tool will automatically monitor the application’s page loading, clicks and other events, and automatically embed monitoring code to collect data. The advantage of automated burying is that it reduces the developer’s workload and eliminates the need to manually insert burying code. However, there are also some problems in automated burying, such as the huge amount of data and the difficulty of data cleaning [1] .
Visual buried points
Visualization is to configure data collection through visualization tools. Developers can use visual tools to select specific page elements and generate configuration information. During user operation, the visual tracking tool will determine whether the event needs to be collected based on the configuration. The advantage of visual buried points is that the configuration is convenient and fast, without the need to manually write code. Visual burying can also solve some problems in manual burying. For example, new buried points do not need to be released, and the coupling between the buried point code and the business code is reduced. However, visual burying also needs to solve some problems, such as how to determine the unique identifier of page elements, how to carry business parameters, etc. [ 1]
To sum up, manual burying, automatic burying and visual burying are all commonly used data collection methods in iOS applications. They each have their own advantages, disadvantages and applicable scenarios. Developers can choose the appropriate burying method for data collection based on specific needs.
MVC、MVP、MVVM
Design Patterns
In iOS development, commonly used design patterns include MVC (Model-View-Controller), MVP (Model-View-Presenter) and MVVM (Model-View-ViewModel). These design patterns have their own characteristics and applicable scenarios.
- MVC (Model-View-Controller) MVC is the architectural pattern officially recommended by Apple. It divides the application into three main parts: Model, View and Controller.
- Model: Responsible for handling the data logic of the application, including data acquisition, processing and storage.
- View: Responsible for displaying data to the user and receiving user input.
- Controller: As an intermediary between the model and the view, it is responsible for processing user input, updating model data, and displaying the updated data on the view.
The advantage of MVC is its ability to separate the application’s logic and interface, making the code clearer and easier to maintain. However, as business logic increases, the controller may become bloated, resulting in increased maintenance costs [1] .
- MVP (Model-View-Presenter) MVP is an evolved version of the MVC pattern. It separates the View and the Controller into two parts: the View and the Presenter.
- Model: Same as the model in the MVC pattern, responsible for processing data logic.
- View: Responsible for displaying data to the user and receiving user input.
- Presenter: As an intermediary between the model and the view, it is responsible for processing user input, updating model data, and displaying the updated data on the view.
The advantage of MVP is that it further decouples the view and business logic, allowing the view to be modified independently of the model. At the same time, the presenter can test business logic independently and improve the testability of the code [2] .
- MVVM (Model-View-ViewModel) MVVM is an architectural pattern proposed by Microsoft. It merges the View and the Controller into two parts: the View and the ViewModel.
- Model: Same as the model in MVC and MVP patterns, responsible for processing data logic.
- View: Responsible for displaying data to the user and receiving user input.
- ViewModel: As an intermediary between the model and the view, it is responsible for processing user input, updating model data, and displaying the updated data on the view.
The advantage of MVVM is that it can extract the state and behavior of the view to form a new abstraction, which separates business logic and business display and improves the maintainability and reusability of the code [1] .
To sum up, MVC, MVP and MVVM are all commonly used iOS design patterns, and each pattern has its applicable scenarios, advantages and disadvantages. Choosing appropriate design patterns can improve the maintainability and testability of your code, making development more efficient.
Common design patterns
In iOS development, common design patterns include the following:
- Singleton mode: The singleton mode can ensure that there is only one instance of a class in the system, and is often used in scenarios of shared resources. In iOS, some common singleton objects include UIApplication, NSNotificationCenter, NSFileManager, NSUserDefaults, etc. [1] .
- Factory pattern: The factory pattern defines an interface for creating objects, letting subclasses decide which class to instantiate. In iOS, the use of class clusters is an application of the factory pattern, such as NSNumber, NSArray, NSString, etc. [1] .
- Decoration mode: Decoration mode can dynamically add some additional functions to an object without changing the original object. In iOS, Category is a disguised decorator pattern that can add methods to the original class [1] .
- Proxy mode: The proxy mode provides a proxy for an object, and the proxy object controls access to the original object. In iOS, common proxy mode applications include UITableViewDelegate, UITextFieldDelegate, etc. [1] .
- Observer pattern: The observer pattern defines a one-to-many dependency relationship. When the state of an object changes, all objects that depend on it will be notified and automatically updated. In iOS, NSNotificationCenter is an implementation of the observer pattern, which can realize message passing between different objects [1] .
- Command pattern: The command pattern encapsulates requests into objects so that other objects can be parameterized using different requests, queues, or logs. In iOS, common command mode applications include UIControl’s Target-Action mechanism, NSOperationQueue, etc. [1] .
- Flyweight mode: Flyweight mode uses shared objects to reduce memory usage and improve performance. In iOS, common flyweight mode applications include NSCache, NSURLCache, etc. [1] .
These design patterns are widely used in iOS development, and you can choose the appropriate design pattern to solve the problem according to specific needs.
Common routing solutions and comparison of advantages and disadvantages
Common routing solutions for iOS mainly include URL-based routing and runtime-based routing. Here is a comparison of the pros and cons of the two routing options:
- Routing scheme based on URL type:
- Principle: Learn from the front-end Router and system App jump method to complete the routing request through the URL. Save the corresponding relationship between the URL and the page in a registry, and the routing process is to find the corresponding page through the URL [2] .
- advantage:
- The server can dynamically control page jumps to achieve flexible page management.
- It can uniformly handle multi-end request methods such as iOS, Android, H5/RN/Weex, etc.
- shortcoming:
- It needs to be registered in the load method, which affects the App startup speed.
- The URL involves hard coding, and the parameters are not easy to maintain.
- Object type parameters need to be implemented using a dictionary [2] .
- Common third-party libraries: JLRoutes, Routable-ios, HHRouter, ARLouter [2] .
- Routing scheme based on runtime type:
- Principle: Based on Mediator mode and Target-Action mode, the runtime feature of Objective-C is used to complete the call. According to the target and action in the routing information, the target instance is generated, the corresponding action operation is called, and the routing is completed [2] .
- advantage:
- No registration required, take full advantage of Runtime’s features.
- Unify the component calling entrance and simplify the calling relationship between components.
- There is verification to ensure security and verify the URL [2] .
- shortcoming:
- Involving hard coding, some parameters need to be packaged into dictionaries.
- Common third-party libraries: CTMediator [2] .
To sum up, the routing scheme based on the URL type is suitable for scenarios that require flexible management of page jumps, while the routing scheme based on the runtime type is more suitable for scenarios where the unified component call entry is required.
How to ensure the stability of iOS projects
Ensuring the stability of iOS projects is an important goal. Here are some common methods and practices to improve the stability of iOS projects:
- Unit testing and integration testing: Write comprehensive unit testing and integration testing to cover key functions and boundary conditions in the project to ensure the correctness and stability of the code.
- Continuous integration and continuous delivery: Use continuous integration and continuous delivery tools to automate the build, test and deployment process to ensure that each code submission is automatically tested and can be quickly deployed to the production environment.
- Error monitoring and logging: Integrate error monitoring tools, such as Crashlytics, Sentry, etc., to capture and record application crashes and exceptions in a timely manner to quickly locate and fix problems.
- Performance Optimization: Perform performance analysis and optimization to ensure that applications can run stably under various devices and network conditions and provide a good user experience.
- Memory management and resource release: Reasonably manage the use of memory and resources, avoid memory leaks and resource waste, and timely release objects and resources that are no longer used.
- Exception handling and fault-tolerance mechanisms: Add exception handling and fault-tolerance mechanisms to key business logic to prevent applications from crashing or functions from functioning properly due to abnormal situations.
- Security considerations: Pay attention to security during the development process and avoid common security vulnerabilities and attacks, such as input verification, data encryption, etc.
- Version control and code review: Use a version control system to manage code and ensure code traceability and recoverability. Conduct code reviews to identify and fix potential issues and bugs.
- Update and maintenance: Update dependent libraries and frameworks in a timely manner and fix known vulnerabilities and problems. Continuously carry out code refactoring and optimization to improve code readability and maintainability.
- User feedback and user experience: Actively collect user feedback, promptly respond to and solve problems encountered by users, improve user experience, and increase user satisfaction.
Through the above methods and practices, you can improve the stability of iOS projects, reduce potential problems and risks, and ensure that applications can run stably and provide a good user experience.
how to design agit diff
How to design a git diff
Git diff is a tool for comparing differences between codes. When designing a git diff, you need to consider the following aspects:
- Select the scope of comparison: You can choose to compare the differences between two commits, or compare the differences between two branches. Choose the appropriate comparison range based on your needs.
- Select the output format: Git diff can output difference information in different formats, such as patch format, statistical information format, etc. According to your needs, choose the appropriate output format.
- Choose the comparison algorithm: Git diff provides a variety of comparison algorithms, such as the default algorithm, patience algorithm, histogram algorithm, etc. Depending on your needs, choose an appropriate comparison algorithm.
- Choose the context to display: Git diff can display the context of the difference. You can choose how many lines of context information to display. Depending on your needs, choose the appropriate contextual display.
- Choose what to output: Git diff can output detailed information about the differences, such as the number of modified lines, the number of added lines, the number of deleted lines, etc. Choose the appropriate output content based on your needs.
Here are some commonly used git diff commands and options:
git diff
: Compare the differences between the work area and the staging area.git diff --cached
: Compare the differences between the staging area and the latest commit.git diff commit1 commit2
: Compare the differences between two commits.git diff branch1 branch2
: Compare the differences between two branches.git diff --stat
: Displays differences as statistics.git diff --color-words
: Displays differences in word units and color-coded.
Design a thread pool? Draw your architecture diagram
Designing a thread pool in iOS can be implemented using GCD (Grand Central Dispatch). The following is a simple thread pool design architecture diagram:
+-------------------+
| Task Queue |
+-------------------+
| |
| |
| |
| |
+-------------------+
|
|
v
+-------------------+
| Thread Pool |
+-------------------+
| |
| |
| |
| |
+-------------------+
Architecture diagram explanation:
- Task Queue: used to store tasks to be executed, which can be a serial queue or a concurrent queue. Tasks can be closures (blocks) or custom operation objects (Operations).
- Thread Pool: A pool composed of multiple threads used to execute tasks in the task queue. Thread pools can be fixed size or dynamically resized.
Thread pool design ideas:
- Create a task queue to store tasks to be executed.
- Create a thread pool containing multiple threads to execute tasks in the task queue.
- When a task needs to be executed, the task is added to the task queue.
- Threads in the thread pool obtain tasks from the task queue and execute them.
- After executing the task, the thread returns to the thread pool and waits for the next task.
The design of the thread pool can be adjusted according to specific needs. For example, the maximum number of threads, thread priority, etc. can be set.
What is your app architecture, what are its advantages and disadvantages, why do you do this, and how can you improve it?
The app architecture is based on the MVVM (Model-View-ViewModel) design pattern.
advantage:
- Separation of concerns: MVVM separates data logic and interface logic, making the code clearer and maintainable.
- Testability: Business logic in ViewModel can be verified through unit testing, improving code quality and stability.
- Reusability: ViewModel can be implemented independently of specific views and can be reused in different interfaces.
- Reactive programming: By using the observer pattern and binding mechanism, ViewModel can update the view in real time to provide a better user experience.
shortcoming:
- Learning curve: Compared with the traditional MVC (Model-View-Controller) architecture, MVVM requires more learning and understanding.
- Introducing additional complexity: MVVM introduces additional components such as ViewModel and binding mechanisms, which increases the complexity of the code.
- Project size limitations: For small projects, MVVM may seem too cumbersome and not suitable for simple applications.
Why choose MVVM architecture:
- Separation of concerns: MVVM separates data logic and interface logic, making the code clearer and maintainable.
- Testability: Business logic in ViewModel can be verified through unit testing, improving code quality and stability.
- Reusability: ViewModel can be implemented independently of specific views and can be reused in different interfaces.
- Reactive programming: By using the observer pattern and binding mechanism, ViewModel can update the view in real time to provide a better user experience.
How to improve:
- Modularization: Split the application into multiple modules, each module is responsible for specific functions, improving the maintainability and reusability of the code.
- Use dependency injection: Decouple dependencies through a dependency injection framework to improve code flexibility and testability.
- Introducing unified data management: Use a unified data management mechanism, such as Redux or RxSwift, to manage application status and data flow and simplify data processing logic.
other problems
What bug
can cause crashes and how to protect against them
Common iOS crash bugs and prevention methods are as follows:
- Container Crash (container class crash):
- Common container class crashes include array out-of-bounds, nil insertion and other incorrect operations [1] .
- Protection method: Customize methods for exchange, and add conditional restrictions and judgments to the custom methods to avoid out-of-bounds and nil insertion [1] .
- NSString Crash (string class crash):
- String class crashes may be caused by operations such as null pointers and out-of-bounds operations [1] .
- Protection method: Before using string methods, make a non-null judgment first to avoid crashes caused by null pointers [1] .
- Object method or class method not found:
- When calling a non-existent object method or class method, it will cause a crash [1] .
- Protection method: Before calling a method, first determine whether the method exists to avoid calling non-existent methods [1] .
- KVO and KVC Crash:
- Improper use of KVO (Key-Value Observation) and KVC (Key-Value Coding) can lead to crashes [1] .
- Protection method: Use KVO and KVC correctly, follow relevant specifications, and avoid crashes caused by incorrect operations [1] .
- NSNotification Crash:
- Improper use of NSNotification may lead to crashes, such as not removing the observer or still sending notifications after the observer is released [1] .
- Protection method: Remove the observer at the appropriate time to avoid still receiving notifications after the observer is released [1] .
- NSTimer Crash:
- Improper use of NSTimer may cause a crash, such as not releasing it in time or starting the timer repeatedly [1] .
- Protection method: Release the timer at the appropriate time to avoid starting the timer repeatedly [1] .
- Bad Access Crash (wild pointer):
- Wild pointer access to memory may cause a crash [1] .
- Protection method: Check the validity before using the pointer to avoid wild pointer access [1] .
- Threading Crash (non-main thread refreshes UI):
- Refreshing the UI on a non-main thread may cause a crash [1] .
- Protection method: Refresh the UI in the main thread and avoid operating the UI in non-main threads [1] .
- NSNull Crash:
- Incorrect use of NSNull may lead to crashes, such as using NSNull as an object of other types [1] .
- Protection method: Perform type judgment before using NSNull to avoid incorrect use of NSNull [1] .
- Crash on iOS16:
- There may be new crash issues on iOS16, which need to be protected according to specific circumstances [1] .
The above are the common bugs and protection methods that cause iOS crashes. Through reasonable protective measures, the crash rate of applications can be reduced and the stability and user experience of applications can be improved.
How to monitor crashes
In iOS, you can monitor crashes using:
- Use crash log collection tools: There are some third-party tools that can help you collect crash logs, such as Bugly, Firebase Crashlytics, etc. These tools can automatically capture crash logs and upload them to the server for analysis and monitoring.
- Register a signal handler: Crash in iOS is usually caused by a signal. You can register a signal handler to capture the crash signal and process it. Catch the exception signal by registering
signalHandler
a function, and then obtain the stack information in the processing function and save or upload it [1] . - Use exception handling mechanism: The exception handling mechanism in iOS can help you catch and handle exceptions. You can use
@try-@catch-@finally
syntax blocks to catch exceptions and@catch
handle exceptions within the block. In the exception handling block, you can record exception information, save stack information, etc. [2] . - Use crash analysis tools: Xcode provides crash analysis tools that can help you analyze crash logs. You can use Xcode’s “Organizer” feature to view your application’s crash logs and obtain symbolic stack information. This information can help you locate and resolve crash issues [1] .
Summary: To monitor iOS crashes, you can use crash log collection tools, register signal processing functions, use exception handling mechanisms, or use crash analysis tools. These methods can help you discover and solve application crash problems in time, and improve application stability and user experience.
app
The startup process (inspecting the LLVM compilation process, static linking, dynamic linking, and runtime initialization)
The startup process of an iOS application can be divided into the following stages:
- Compilation phase:
- Use the LLVM compiler to compile the source code into an executable file (Mach-O format) [1] .
- Static linking: Link the application’s target files with system libraries and other dependent libraries to generate the final executable file [1] .
- Dynamic linking stage:
- When the application starts, the dynamic linker (dyld) loads the application’s executable file and dependent dynamic libraries [1] .
- dyld will recursively load all the dynamic libraries that the application depends on, and perform symbol binding and offset correction [1] .
- Symbol binding: Bind symbols in the application to actual addresses in the dynamic library, so that the application can correctly call functions and methods in the dynamic library [1] .
- Offset correction: Add the address offset value in the application to the ASLR address allocated at runtime to obtain the real memory address [1] .
- Runtime initialization phase:
- ObjC runtime initialization: register ObjC related classes and categories, check the uniqueness of the selector, etc. [1] .
- Execute the +load() method: After the dynamic library is loaded, the +load() method of each class will be called to perform some initialization operations [1] .
- Execute attributes ((constructor)) modified functions: These functions will be automatically executed when the application starts and are used to perform some initialization operations [1] .
- main() stage:
- dyld calls the main() function to start executing the main logic of the application [1] .
- Call the UIApplicationMain() function to create the UIApplication object and AppDelegate object [1] .
- Call the applicationWillFinishLaunching and didFinishLaunchingWithOptions methods to complete the initialization of the application and display the home page [1] .
The role of each folder division of the sandbox directory
The sandbox directory is a folder in the iOS system used to store application data. Each folder has a specific role within the sandbox directory. The following is the division of each folder in the sandbox directory:
- Documents directory:
- Purpose: Used to store user data files for applications.
- Features: Files in this directory will be synchronized by iTunes, and iTunes shared files can be configured through configuration [1] .
- Library directory:
- Purpose: Store the application’s support files and preference files.
- Subdirectory:
- Caches directory: used to store application-specific support files, such as cached images, offline data, etc. The data in this directory will not be synchronized by iTunes, and the system will not automatically clean up the files in it.
- Preferences directory: Contains the application’s preference files. You can obtain and set application preferences through the NSUserDefaults class. The data in this directory will be synchronized by iTunes [1] .
- tmp directory:
- Purpose: Used to store temporary files, such as temporarily downloaded files, etc.
- Features: The files in this directory will not be synchronized by iTunes, and the system will automatically clean up the files in it, such as when restarting the phone [1] .
The division of these folders allows applications to store data in different locations according to different needs, and to control which data will be synchronized by iTunes and which data will be automatically cleaned by the system.
Briefly describe match-o
the file structure
The Mach-O file structure is an executable file format used by Apple operating systems (OSX and iOS). It is a binary file format used to store code and data and defines the composition and linking rules of program files. Understanding the Mach-O file structure is very important for understanding the underlying mechanism of Apple’s operating system and the linking and loading process of the program.
Mach-O files consist of the following parts:
- File header (Mach Header): Contains general information about the binary file, such as byte order, architecture type, number of load instructions, etc. [1] .
- Load Commands: is a table containing multiple load commands, used to describe the location and attributes of each part of the file, such as the location of the area, symbol table, dynamic symbol table, etc. [1] .
- Data area (Data): Usually the largest part of the object file, containing the specific data of each segment (Segment) [1] .
Specifically, the structure of a Mach-O file is as follows:
- File header (Mach Header): Contains general information about the file, such as byte order, architecture type, number of load instructions, etc.
- Load Commands: is a table containing multiple load commands, describing the location and attributes of each part of the file.
- Data segment (Segment): stores data, including codes, character constants, classes, methods, etc. A Mach-O file can have multiple data segments, and each segment can contain multiple areas (Section).
- Symbol Table: The bridge that connects addresses and symbols, and stores the location of symbols in the string table.
- String Table: Stores all variable names, function names and other strings.
- Dynamic Symbol Table: stores the offset information of dynamically linked symbols in the symbol table.
The above is the basic structure of the Mach-O file. For more detailed information, please refer to official documents and related information.