mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
Add 3 chapter notes and update chapter index
This commit is contained in:
88
Chapter1 - iOS/1.1.md
Normal file
88
Chapter1 - iOS/1.1.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Image Assets Optimization for Project Size
|
||||
|
||||
> A small iOS project with many features can grow large in size. Under an Xcode project, image assets can take up a lot of space, and if an app needs a one-click skin/theme change, imagine how many images that requires. Each set of images also needs 1x, 2x, 3x, etc.
|
||||
|
||||
## Introduction
|
||||
|
||||
IconFont technology originated in the web field from Web Font technology. Over time, web design became more beautiful. But system-installed fonts on computers could no longer satisfy designers, so Web Font technology was born. An English character font set is not large; by downloading fonts over the network, webpages can be rendered. With Web Font technology, designers gained much more freedom.
|
||||
|
||||
In web design, icons need to adapt to multiple resolutions, and each icon would require a separate network request. Someone thought to use the Web Font approach to solve both problems: make vector icons into a font, so a single network request suffices and the icons scale cleanly. Another way to solve this is using sprite images.
|
||||
|
||||
The web community has used IconFont-like techniques for years—when I first encountered Bootstrap in 2015, Font Awesome was very popular. Recently IconFont technology has been applied to iOS image assets. I had some time to research and整理 (organize) it, and I record my learning here.
|
||||
|
||||
## Advantages
|
||||
|
||||
* Reduce size — font files are smaller than images
|
||||
* Icon fidelity when scaling — solves 2x/3x and future n× image issues
|
||||
* Easy to change color and size, image reuse
|
||||
|
||||
## Disadvantages
|
||||
|
||||
* Only suitable for
|
||||
`single-color icons`
|
||||
* Using Unicode characters is hard to understand
|
||||
* Need to maintain the font library
|
||||
|
||||
There are many tutorials online about how to make IconFonts; I won't discuss that here.
|
||||
|
||||
## How to use
|
||||
|
||||
1. First pick some rich resource sites. I've used Alibaba's IconFont for years and didn't research others, so I'll use Alibaba's product here. Address: http://www.iconfont.cn/plus
|
||||
|
||||
2. Open the site and select suitable icons into the cart, as shown:
|
||||

|
||||
|
||||
3. After selecting, view the cart and click to download the code.
|
||||
|
||||
4. Open the downloaded file; its structure is as follows. In iOS development we use the Unicode form of IconFont, so open demo_unicode.html
|
||||

|
||||
|
||||
**Note:** Create UIFont using the font's PostScript name, not the file name; text values are 8-digit Unicode characters. We can open demo.html to find the HTML entity Unicode code for each icon. For example: the icon "店" corresponds to HTML entity Unicode code: 0x3439. Converted it becomes: \U00003439 — replace 0x with \U and pad with zeros to reach 8 characters.
|
||||
|
||||
# Using IconFont in Xcode
|
||||
|
||||
Initial attempt usage
|
||||
|
||||
1. First see how to use IconFont simply.
|
||||
2. Add the downloaded **iconfont.ttf** into the Xcode project and ensure it's included in Build settings.
|
||||
|
||||

|
||||
|
||||
3. How to use?
|
||||
|
||||
```objective-c
|
||||
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"\U0000e696 \U0000e6ab \U0000e6ac \U0000e6ae"];
|
||||
[attributedStr addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 1)];
|
||||
[attributedStr addAttribute:NSForegroundColorAttributeName value:[UIColor orangeColor] range:NSMakeRange(3, 1)];
|
||||
[attributedStr addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(9, 1)];
|
||||
self.label.attributedText = attributedStr;
|
||||
[self.view addSubview:self.label];
|
||||
|
||||
#pragma mark - getter and setter
|
||||
-(UILabel *)label{
|
||||
if (!_label) {
|
||||
_label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, BoundWidth-200, 40)];
|
||||
_label.font = [UIFont fontWithName:@"iconfont" size:24];
|
||||
_label.textColor = [UIColor purpleColor];
|
||||
}
|
||||
return _label;
|
||||
}
|
||||
```
|
||||
|
||||
#### Further encapsulation for easier use
|
||||
|
||||
Generating a UIImage from IconFont only requires LBPIconFontmake(par1, par2, par3), where par1: the iconfont Unicode value; par2: image size; par3: image color. LBPIconFontmake is a macro: #define LBPIconFontmake(text,size,color) [[LBPFontInfo alloc] initWithText:text withSize:size andColor:color].
|
||||
|
||||
```objective-c
|
||||
self.latestImageView.image = [UIImage iconWithInfo:LBPIconFontmake(@"\U0000e6ac", 60, @"000066") ];
|
||||
```
|
||||

|
||||
|
||||
1. LBPFontInfo encapsulates font information.
|
||||
2. UIColor+picker sets color from a hex string.
|
||||
3. LBPIconFont registers the IconFont into the system and uses it.
|
||||
4. UIImage+LBPIconFont provides a UIImage category for using IconFont.
|
||||
|
||||
# Demo repository
|
||||
|
||||
https://github.com/FantasticLBP/IconFont_Demo
|
||||
165
Chapter1 - iOS/1.2.md
Normal file
165
Chapter1 - iOS/1.2.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Understanding Initializers
|
||||
|
||||
## Initializers
|
||||
|
||||
* The internal implementation of the new method is to call alloc first, then call init.
|
||||
* alloc: Sends the alloc message to a class; alloc returns an instance of that class.
|
||||
* init: An instance method whose role is to initialize the object.
|
||||
* Steps to create an object: first use alloc to create an object, then use init to initialize it before using the object.
|
||||
* Using an uninitialized object is dangerous.
|
||||
* init method: Purpose — initialize the object and set initial values; this is called a constructor (initializer).
|
||||
|
||||
## Overriding init
|
||||
|
||||
* If you want the created object's properties to have values other than the default initialization values, you need to override init.
|
||||
* Rules for overriding init:
|
||||
* You must first call the superclass's init method (because initialization of the current class proceeds through [super init]), and assign the returned value to self.
|
||||
* Calling init may fail; if it fails, return nil.
|
||||
* Check whether the superclass initialized successfully. If self != nil, initialization succeeded.
|
||||
* If initialization succeeded, initialize the current class's properties.
|
||||
* Finally return self.
|
||||
|
||||
#### Clarifications:
|
||||
|
||||
1. Why call the superclass init method?
|
||||
1. The current object has an isa pointer; the isa pointer is set through the superclass's init.
|
||||
2. You need to ensure that the superclass's properties are also initialized.
|
||||
2. Pattern for overriding init:
|
||||
|
||||
```
|
||||
-(instancetype)init{
|
||||
if (self = [super init]) {
|
||||
// todo: custom property initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
```
|
||||
|
||||
```objc
|
||||
// Person
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Person : NSObject
|
||||
@property NSString* name;
|
||||
@property int age;
|
||||
|
||||
-(void)sayHi;
|
||||
|
||||
@end
|
||||
|
||||
#import "Person.h"
|
||||
@implementation Person
|
||||
|
||||
-(void)sayHi{
|
||||
NSLog(@"Hi");
|
||||
}
|
||||
|
||||
-(instancetype)init{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.name = @"杭城小刘";
|
||||
self.age = 22;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
// Test
|
||||
|
||||
Person *p1 = [[Person alloc] init]; // p1.name = "杭城小刘", p1.age = 22;
|
||||
Person *p2 = [Person new]; // p2.name = "杭城小刘", p2.age = 22;
|
||||
```
|
||||
|
||||
If two classes have a composition relationship and one property is an object of another class, that property defaults to nil when the containing class is initialized. How to initialize it?
|
||||
|
||||
```
|
||||
-(instancetype)init{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.name = @"lbp";
|
||||
self.age = 22;
|
||||
self.pig = [[Pig alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Test
|
||||
Person *p1 = [[Person alloc] init]; // p1.pig != nil
|
||||
```
|
||||
|
||||
## Custom initializers
|
||||
|
||||
* Current situation: Although each created object's properties are not the default values, every initialized object has the same values.
|
||||
* Requirement: Allow callers to decide the property values when instantiating.
|
||||
* Solution: Custom initializer.
|
||||
* Rules for custom initializers:
|
||||
* The return type should be instancetype.
|
||||
* The method name must begin with initWith.
|
||||
* The implementation is similar to init.
|
||||
* Note: You cannot use new to call a custom initializer. (new performs alloc then init; default init assigns the default property values.)
|
||||
|
||||
```
|
||||
-(instancetype)initWithName:(NSString *)name andAge:(int)age{
|
||||
if (self = [super init]) {
|
||||
self.name = name;
|
||||
self.age = age;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
```
|
||||
|
||||
```objc
|
||||
// Person
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface Person : NSObject
|
||||
@property NSString* name;
|
||||
@property int age;
|
||||
|
||||
-(instancetype)initWithName:(NSString *)name andAge:(int)age;
|
||||
@end
|
||||
|
||||
#import "Person.h"
|
||||
@implementation Person
|
||||
|
||||
-(instancetype)init{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.name = @"lbp";
|
||||
self.age = 22;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// You cannot assign to self outside of an initializer.
|
||||
// The compiler treats only methods starting with initWith as initializers.
|
||||
|
||||
-(instancetype)initWithName:(NSString *)name andAge:(int)age{
|
||||
if (self = [super init]) {
|
||||
self.name = name;
|
||||
self.age = age;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Test
|
||||
Person *p1 = [[Person alloc] init];
|
||||
Person *p2 = [Person new];
|
||||
Person *p3 = [[Person alloc] initWithName:@"杭城小刘2号" andAge:23];
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
An experiment about "custom initializers must start with initWith"
|
||||
|
||||

|
||||
|
||||
The error message is clear: you cannot assign to self outside of an initializer.
|
||||
|
||||
Because the compiler considers only methods starting with initWith as initializers.
|
||||
81
Chapter1 - iOS/1.3.md
Normal file
81
Chapter1 - iOS/1.3.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# loadView
|
||||
|
||||
1. Purpose: load the controller's view
|
||||
2. When it's called: it's called the first time the controller's view is used
|
||||
3. Use case: implement this method when you want to provide a custom view for the controller
|
||||
|
||||
Accessing the controller's view is equivalent to calling the controller's view getter:
|
||||
```objective-c
|
||||
-(UIView *)view
|
||||
{
|
||||
if(_view == nil){
|
||||
[self loadView];
|
||||
[self viewDidLoad];
|
||||
}
|
||||
return _view;
|
||||
}
|
||||
```
|
||||
|
||||
# Controller view loading flow
|
||||

|
||||
|
||||
- The controller's `init` method internally calls `initWithNibName`
|
||||
|
||||
`MyViewController *vc = [[MyViewController alloc] init];`
|
||||
|
||||
Notes:
|
||||
|
||||
The system's decision logic assumes: no nibName specified; no custom loadView method; the controller is named ...Controller
|
||||
|
||||
Decision rules:
|
||||
|
||||
- Check whether a nibName was specified; if specified, load that nib
|
||||
- Check whether there's an xib with the same name as the controller but without "Controller" in its name; if present, load it
|
||||
- If the previous step doesn't find one, check whether an xib with the same name as the controller class exists; if present, load it
|
||||
- If no xib describes the controller's view, do not load any xib
|
||||
|
||||
## How MyViewController loads its view
|
||||
|
||||
- Check whether an xibName was specified; if so, load the specified xib
|
||||
- Check whether there's an xib with the same name as the controller class but without "Controller" in the name
|
||||
- Check whether there's an xib with the same name as the controller class; if present, load it
|
||||
- Otherwise, create an empty view directly
|
||||
|
||||
Example
|
||||
|
||||
```objective-c
|
||||
// in AppDelegate
|
||||
ViewController *vc = [[ViewController alloc] init];
|
||||
vc.view.backgroundColkor = [UIColor redColor];
|
||||
self.window.rootViewController = vc;
|
||||
[pself.window makeKeyAndVisable];
|
||||
|
||||
// ViewController
|
||||
-(UIView *)view{
|
||||
if(!_view){
|
||||
[self loadView];
|
||||
[self viewDidLoad];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)loadView{
|
||||
UIView*view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
view.backgroundColor = [UIColor greenColor];
|
||||
self.view = view;
|
||||
}
|
||||
|
||||
-(void)viewDidload{
|
||||
[super viewDidload];
|
||||
self.view.backgroundColor = [UIColor brownColor];
|
||||
}
|
||||
```
|
||||
|
||||
### What color will the interface be at this point?
|
||||
|
||||
Many people might answer "green." Actually, the answer is red.
|
||||
|
||||
Why? In AppDelegate, `vc.view.backgroundColor` calls vc's view getter. Inside the getter it checks if `_view` exists; if not, it creates a new UIView by calling `[self loadView]`. After creating the view it calls `viewDidLoad`; if the view already exists it returns it directly. So the sequence is: first green, then brown, and finally red.
|
||||
|
||||
#### An official explanation
|
||||
|
||||

|
||||
@@ -119,7 +119,7 @@ Part One mainly introduces problems encountered or interesting knowledge in iOS
|
||||
* [114. Swift optimizations](1.114.md)
|
||||
* [115. AI empowerment on the endpoint](1.115.md)
|
||||
* [116. Deep dive into Swift classes](1.116.md)
|
||||
* [117. Swift protocol exploration](1.117.md]
|
||||
* [117. Swift protocol exploration](1.117.md)
|
||||
* [118. Swift error handling](1.118.md)
|
||||
* [119. Analyze Swift String](1.119.md)
|
||||
* [120. Swift access control](1.120.md)
|
||||
@@ -127,7 +127,16 @@ Part One mainly introduces problems encountered or interesting knowledge in iOS
|
||||
* [122. Swift literal fundamentals](1.122.md)
|
||||
* [123. Swift pattern matching](1.123.md)
|
||||
* [128. SwiftUI research](1.128.md)
|
||||
|
||||
* [129. Swift Dictionary](1.129.md)
|
||||
* [130. GCD](1.130.md)
|
||||
* [131. Package management tools](1.131.md)
|
||||
* [132. Dynamic debugging](1.132.md)
|
||||
* [133. Using PGO in the compiler to optimize app performance](1.133.md)
|
||||
* [134. Removing dead code](1.134.md)
|
||||
* [135. Framework design](1.135.md)
|
||||
* [136. Engineering practices](1.136.md)
|
||||
* [137. Quality testing](1.137.md)
|
||||
* [138. AFNetworking source code walkthrough](1.138.md)
|
||||
* [139. Graphics rendering techniques](1.139.md)
|
||||
* [140. Aspects](1.140.md)
|
||||
* [143. AI empowerment on the endpoint](1.143.md)
|
||||
|
||||
Reference in New Issue
Block a user