基礎(chǔ)理解篇
Objective-C是一種面向?qū)ο蟮木幊陶Z言,它支持元編程。元編程是指編寫程序來生成或操縱其他程序的技術(shù)。
Objective-C中,元編程可以使用Objective-C的動態(tài)特性來實現(xiàn)。例如可以使用Objective-C的運行時函數(shù)來動態(tài)地創(chuàng)建類、添加屬性和方法等等。
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@property (nonatomic, strong) NSString *name;
- (void)printName;
@end
@implementation MyClass
- (void)printName {
NSLog(@"%@", self.name);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *myObj = [[MyClass alloc] init];
[myObj printName];
// 動態(tài)添加屬性和方法
[[myObj class] addMethod:@selector(sayHello:) withSignature:@"v"];
[[myObj class] addProperty:@"age" withType:@integerValue withAttribute:NONE];
// 動態(tài)調(diào)用方法
((void (*)(id, SEL))[[myObj class] performSelector:@selector(sayHello:) withObject:nil]))(myObj, @selector(sayHello:));
// 動態(tài)添加屬性
((void (*)(id, SEL, id))[[myObj class] performSelector:@selector(setProperty:forKey:) withObject:[NSNumber numberWithInt:100] forKey:@"age"])(myObj, @selector(setProperty:forKey:), @100);
// 動態(tài)刪除屬性和方法
[[myObj class] removeMethod:@selector(sayHello:)];
[[myObj class] removeProperty:@"age"];
}
return 0;
}
Objective-C是一種動態(tài)編程語言,它將靜態(tài)語言在編譯和鏈接時需要做的一些事情給延后到運行時執(zhí)行。例如方法的調(diào)用,只有在程序執(zhí)行的時候,才能具體定位到哪個類的哪個方法。這就需要一個運行時庫,就是Runtime。
Runtime機制是指Objective-C運行時系統(tǒng),它提供了一些類和方法來幫助我們動態(tài)地創(chuàng)建、修改和訪問對象。其中最重要的是objc_msgSend函數(shù),它可以用來發(fā)送消息并調(diào)用對象的方法。除此之外,還有很多其他的類和方法可以用來實現(xiàn)動態(tài)行為,比如class_addMethod、method_exchangeImplementations等等。
推薦閱讀:什么是元編程(meta-promgramming)?
工程知識篇
1.Xcode創(chuàng)建工程
Xcode創(chuàng)建工程:iOS–>App–>填寫工程名選擇語言(OC\Swift)–>選擇存放路徑(一般放在User目錄下,訪達(dá)–>前往–>個人可以打開用戶個人文件夾 。理由忘了,歡迎評論區(qū)大佬解答)
2.創(chuàng)建工程后AppDelegate 和 ViewController的說明
AppDelegate是應(yīng)用程序委托對象,其父類是UIResponder類(繼承關(guān)系),并實現(xiàn)UIApplicationDelegate委托協(xié)議.
[UIResponder:實現(xiàn)應(yīng)用程序的處理響應(yīng)事件的能力]
[UIApplicationDelegate委托協(xié)議使AppDelegate成為應(yīng)用程序的委托對象,這種對象能夠響應(yīng)應(yīng)用程序的生命周期]
(生命周期在程序運行的不同階段進行回調(diào))
//AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate: UIResponder <UIApplicationDelegate>
@property (strong,nonatomic) UIWindow* window; //ios程序視圖中只有一個UIWindow
@end
//AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLauchingWithOptions:(NSDictionary *)launchOptions{return YES;}
//應(yīng)用啟動并進行初始化時會調(diào)用該方法并發(fā)出通知UIApplicationDidFinishLauchingNotification.這個階段會實例化根視圖控制器
- (void)applicationWillResignActive:(UIApplication *)application{}
//應(yīng)用從活動狀態(tài)進入非活動狀態(tài)時調(diào)用該方法并發(fā)出通知UIApplicationWillResignActiveNotification
- (void)applicationDidEnterBackground:(UIApplication *)application{}
//應(yīng)用進入后臺時候調(diào)用該方法并發(fā)出通知UIApplicationDidEnterBackgroundNotification
- (void)applicationWillEnterForeground:(UIApplication *)application{}
//應(yīng)用進入前臺時候但未處于活躍狀態(tài)時候調(diào)用該方法并發(fā)出通知UIApplicationWillEnterForegroundNotification
- (void)applicationDidBecomeActive:(UIApplication *)application{}
- (void)applicationWillTerminate:(UIApplication *)application{}
//應(yīng)用被終止時候調(diào)用該方法并發(fā)出通知UIApplicationWillTerminateNotification,但內(nèi)存清除時除外
@end
作者:星辰_入海
鏈接:https://www.jianshu.com/p/859d11e1e2fd
關(guān)于ViewController更詳細(xì)的說明可參考:viewController詳解
文章備用鏈接:https://www.pianshen.com/article/13491799244/#google_vignette
重點摘錄如下:(流程圖有些沒仔細(xì)描述、推薦看原文)
1. view的生命周期
當(dāng)一個視圖控制器被創(chuàng)建,并在屏幕上顯示的時候。 代碼的執(zhí)行順序
1、 alloc 創(chuàng)建對象,分配空間
2、init (initWithNibName) 初始化對象,初始化數(shù)據(jù)
3、loadView 從nib載入視圖 ,通常這一步不需要去干涉。除非你沒有使用xib文件創(chuàng)建視圖
4、viewDidLoad 載入完成,可以進行自定義數(shù)據(jù)以及動態(tài)創(chuàng)建其他控件
5、viewWillAppear 視圖將出現(xiàn)在屏幕之前,馬上這個視圖就會被展現(xiàn)在屏幕上了
6、viewDidAppear 視圖已在屏幕上渲染完成
當(dāng)一個視圖被移除屏幕并且銷毀的時候的執(zhí)行順序,這個順序差不多和上面的相反
1、viewWillDisappear 視圖將被從屏幕上移除之前執(zhí)行
2、viewDidDisappear 視圖已經(jīng)被從屏幕上移除,用戶看不到這個視圖了
3、dealloc 視圖被銷毀,此處需要對你在init和viewDidLoad中創(chuàng)建的對象進行釋放
關(guān)于viewDidUnload :在發(fā)生內(nèi)存警告的時候如果本視圖不是當(dāng)前屏幕上正在顯示的視圖的話, viewDidUnload將會被執(zhí)行,本視圖的所有子視圖將被銷毀,以釋放內(nèi)存,此時開發(fā)者需要手動對viewLoad、viewDidLoad中創(chuàng)建 的對象釋放內(nèi)存。 因為當(dāng)這個視圖再次顯示在屏幕上的時候,viewLoad、viewDidLoad 再次被調(diào)用,以便再次構(gòu)造視圖。
2. view的加載過程
3. view卸載過程圖
推薦看:ViewController生命周期實例
3. 應(yīng)用程序狀態(tài)以及不同場景下的變化
應(yīng)用程序可能所處的狀態(tài):
不同場景下狀態(tài)的變化:
應(yīng)用啟動場景
描述:當(dāng)用戶第一次啟動程序時候,或者終止后再次啟動
(1)Not running --> Inactive
(2)Inactive --> Active
應(yīng)用退出場景
描述:分為兩種可能:1.可以在后臺運行或者掛起;2.不可以在后臺運行和掛起
Step1:
(1)Active --> Inactive
(2)Inactive --> Background
(3)Background --> Suspended
Step2:
(1)Active --> Inactive
(2)Inactive --> Background
(3)Background --> Suspended
(4)Suspended --> Not running
應(yīng)用掛起重新運行場景
(1)Suspended --> Background
(2)Background --> Inactive
(3)Inactive --> Active
應(yīng)用終止?fàn)顟B(tài)
內(nèi)存清除后應(yīng)用程序終止,可能是強制清除內(nèi)存,還可以是使用者手動清除
Background --> Suspended --> Not running
作者:星辰_入海
鏈接:https://www.jianshu.com/p/859d11e1e2fd
4.IOS開發(fā)多線程
參考資料:IOS開發(fā)多線程講解(一)–結(jié)合斯坦福ios7開發(fā)(十)
爬過的坑:
5.UITableviewCell復(fù)用機制
參考資料:UITableviewCell復(fù)用機制
爬過的坑
6.類方法和實例方法調(diào)用
7. 屬性strong和copy的區(qū)別
8.小概念:nib segue kvc kvo
nib:NIB是Non-interactive Interface Builder的縮寫,是一種可視化的界面設(shè)計工具。它可以讓你通過拖拽控件來設(shè)計界面,而無需編寫代碼。NIB文件通常包含多個窗口、視圖和控制器等元素,這些元素可以相互連接并設(shè)置屬性。
segue:
KVC是Key-Value Coding的縮寫,即鍵值編碼。它是一種動態(tài)獲取對象屬性值的方法。KVC可以通過字符串來訪問對象的屬性,例如:object.valueForKey(“name”)。
KVO是Key-Value Observing的縮寫,即鍵值觀察。它是一種動態(tài)監(jiān)聽對象屬性變化的方法。KVO可以通過添加觀察者來實現(xiàn),當(dāng)被觀察對象的屬性發(fā)生變化時,觀察者會收到通知并作出相應(yīng)處理。
下面是一個使用KVC和KVO的代碼實例:
// 創(chuàng)建一個Person類
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end
@implementation Person
@end
// 創(chuàng)建一個Person對象并設(shè)置name屬性
Person *person = [[Person alloc] init];
person.name = @"Tom";
// 使用KVC獲取name屬性值
NSString *name = [person valueForKey:@"name"];
NSLog(@"name is %@", name);
// 使用KVO監(jiān)聽name屬性變化
[[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]];
// 修改name屬性值
person.name = @"Jerry";
// 手動發(fā)送name屬性變化的通知
[[person didChangeValueForKeyPath:@"name" notification:nil];
9. weak strong 循環(huán)引用
什么是循環(huán)引用:
循環(huán)引用是指兩個對象相互強引用了對方,即retain了對方,從而導(dǎo)致兩個對象都無法被釋放,引發(fā)了內(nèi)存泄漏現(xiàn)象。
在Objective-C中,循環(huán)引用通常發(fā)生在兩個對象之間,其中一個對象持有另一個對象的強引用,而另一個對象也持有第一個對象的強引用。這種情況下,即使第一個對象被釋放了,第二個對象也不會被釋放,因為它們之間存在循環(huán)引用。這種情況可能會導(dǎo)致內(nèi)存泄漏和其他問題。
循環(huán)引用實例:
@interface Person : NSObject
@property (nonatomic, strong) Person *friend;
@end
@implementation Person
@synthesize friend = _friend;
@end
Person *person1 = [[Person alloc] init];
Person *person2 = [[Person alloc] init];
// person1持有了person2的強引用,而person2也持有了person1的強引用
person1.friend = person2;
person2.friend = person1;
[person1 release]; // 釋放person1對象
在這個例子中,Person類有一個屬性friend,它是一個指向其他Person對象的指針。當(dāng)創(chuàng)建兩個Person對象時,它們相互持有對方的強引用,形成了循環(huán)引用。當(dāng)其中一個對象被釋放時,由于它持有另一個對象的強引用,所以另一個對象也無法被釋放,從而引發(fā)了內(nèi)存泄漏問題。文章來源:http://www.zghlxwxcb.cn/news/detail-694254.html
為了避免造成循環(huán)引用,代理一般需使用弱引用
例子:文章來源地址http://www.zghlxwxcb.cn/news/detail-694254.html
#import <UIKit/UIKit.h>
//新建一個協(xié)議,協(xié)議的名稱一般是由:"類名+Delegate"
@protocol ViewControllerBDelegate<NSObject>
//代理方必須實現(xiàn)的方法
@required
//代理方可選實現(xiàn)的方法
@optional
- (void)ViewControllerBsendValue:(NSString *)value;
@end
@interface ViewControllerB : UIViewController
//委托代理人,為了避免造成循環(huán)引用,代理一般需使用弱引用
@property(weak,nonatomic) id<ViewControllerBDelegate> delegate;
//id是一個通用的數(shù)據(jù)類型,表示任何對象。在這個例子中,id<ViewControllerBDelegate>表示一個遵循ViewControllerBDelegate協(xié)議的對象的通用指針。
//這行代碼定義了一個名為delegate的屬性,其類型為ViewControllerBDelegate的弱引用。這意味著這個屬性可以指向任何遵循ViewControllerBDelegate協(xié)議的對象,但是這個對象并不會增加delegate的引用計數(shù)。因此,當(dāng)delegate所指向的對象被釋放時,它不會影響ViewControllerB對象的內(nèi)存管理。
@end
代碼實戰(zhàn)篇
2.
//
// AppDelegate.m
// ExampleCode
//
//
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 第一個頁面
ViewController *viewController = [[ViewController alloc] init];
//UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
// 初始化并顯示第一個頁面
self.window = [[UIWindow alloc] init];
self.window.backgroundColor = [UIColor whiteColor];
self.window.frame = [[UIScreen mainScreen] bounds];
//獲取手機寬高
// CGSize size_screen = self.window.frame.size;
// CGFloat scale_screen = [UIScreen mainScreen].scale; //屏幕縮放比
// NSLog(@"the width of screen is:%f",size_screen.width*scale_screen); //1170 像素分辨率(px)
// NSLog(@"the height of screen is:%f",size_screen.height*scale_screen); //2532
// NSLog(@"the width of screen is:%f",size_screen.width); //390
// NSLog(@"the height of screen is:%f",size_screen.height); //844
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
工具篇
2.
小tips
- 如何使用Podfile
到了這里,關(guān)于iOS練手項目知識點匯總的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!