目錄
1.plist(屬性列表)文件
2.Preference\NSUserDefaults(偏好設(shè)置)
3.NSKetedArchiver(歸檔 - 解歸檔)
4.SQLite 與 FMDB
5.CoreData
6.鑰匙串 Keychain
7.云服務(wù) iCloud
8.YYCache 緩存
9.bbx 司機(jī)端舉例
數(shù)據(jù)存儲(chǔ)緩存基礎(chǔ)知識(shí)
數(shù)據(jù)存儲(chǔ)也叫數(shù)據(jù)緩存也叫數(shù)據(jù)持久化山林。所謂的持久化就是將數(shù)據(jù)保存到硬盤(pán)中焕阿,使得在應(yīng)用程序或機(jī)器重啟后可以繼續(xù)訪(fǎng)問(wèn)之前保存的數(shù)據(jù)狈癞。在 iOS 開(kāi)發(fā)中有很多數(shù)據(jù)持久化的方案枣申,比如 plist、偏好設(shè)置饮亏、歸檔 - 解歸檔耍贾、SQLite、FMDB路幸、CoreData荐开、
Keychain 等。內(nèi)存緩存:也叫網(wǎng)絡(luò)緩存简肴;是 App 在運(yùn)行的時(shí)候用到的晃听,你把他想成單例的存放。即指當(dāng)前程序運(yùn)行空間砰识,內(nèi)存緩存速度快容量小能扒,它是供 cpu 直接讀取,比如我們打開(kāi)一個(gè)程序辫狼,他是運(yùn)行在內(nèi)存中的赫粥,關(guān)閉程序后內(nèi)存又會(huì)釋放。內(nèi)存緩存的數(shù)據(jù)只保留在A(yíng)PP啟動(dòng)時(shí)予借,比如保存一些從服務(wù)端獲取到的數(shù)據(jù),來(lái)緩解服務(wù)器的壓力频蛔,并且節(jié)約了用戶(hù)流量和時(shí)間灵迫,提高了用戶(hù)使用體驗(yàn)。iOS 內(nèi)存分為5個(gè)區(qū):棧區(qū)晦溪,堆區(qū)瀑粥,全局區(qū),常量區(qū)三圆,代碼區(qū)狞换。
硬盤(pán)緩存:也叫本地緩存,還叫磁盤(pán)緩存舟肉;就是存在沙盒修噪。磁盤(pán)存儲(chǔ)又可以分為文件系統(tǒng)存儲(chǔ)和數(shù)據(jù)庫(kù)系統(tǒng)存儲(chǔ)。
相關(guān)鏈接:https://juejin.cn/post/6844903593913352206
1.內(nèi)存分區(qū)
2.內(nèi)存緩存和磁盤(pán)緩存的區(qū)別
緩存分為內(nèi)存緩存和磁盤(pán)緩存兩種路媚。
1.內(nèi)存是指當(dāng)前程序的運(yùn)行空間黄琼,緩存速度快容量小,是臨時(shí)存儲(chǔ)文件用的整慎,供 CPU 直接讀取脏款,比如說(shuō)打開(kāi)一個(gè)程序围苫,他是在內(nèi)存中存儲(chǔ),關(guān)閉程序后內(nèi)存就又回到原來(lái)的空閑空間撤师。內(nèi)存緩存適合存儲(chǔ)一些 app 高頻次使用剂府,并且所占空間不大的文件,比如 NSURLConnection 默認(rèn)會(huì)緩存資源在內(nèi)存剃盾。
2.磁盤(pán)是程序的存儲(chǔ)空間腺占,緩存容量大、讀取速度慢、可持久化。與內(nèi)存不同的是磁盤(pán)是永久存儲(chǔ)東西的平夜,只要里面存放東西全闷,不管運(yùn)行不運(yùn)行 ,他都占用空間挨约,磁盤(pán)緩存是存在 Library/Caches。磁盤(pán)存儲(chǔ)可以存儲(chǔ)一些需要持久化的文件,信息等临扮,簡(jiǎn)單的講就是 app 被殺死以后,文件仍然在教翩。
3.沙盒詳解
沙盒機(jī)制:iOS 為不同數(shù)據(jù)管理對(duì)存儲(chǔ)路徑做了規(guī)范杆勇,即在 iOS 中每個(gè) APP 都擁有自己的沙盒,APP 只能訪(fǎng)問(wèn)對(duì)應(yīng)沙盒中存儲(chǔ)的數(shù)據(jù)饱亿,iOS 是不允許跨越沙盒去訪(fǎng)問(wèn)數(shù)據(jù)的蚜退,所有的數(shù)據(jù)都是保存在該沙盒的三個(gè)子目錄下:Document、Library(Library/Caches彪笼,Library/Preference)钻注、temp。
說(shuō)明:
1.Bundle 和沙盒(sandbox)之間的區(qū)別:Bundle 是應(yīng)用程序在手機(jī)中的安裝路徑配猫。沙盒(sandbox)是專(zhuān)門(mén)來(lái)存儲(chǔ)當(dāng)前APP自己的數(shù)據(jù)的路徑幅恋。
2.Application(應(yīng)用程序包):包含了所有的資源文件和和可執(zhí)行文件,上架前經(jīng)過(guò)數(shù)字簽名泵肄,上架后不可修改捆交。
3.沙盒根目錄獲取:NSString *home = NSHomeDirectory();
相關(guān)鏈接:http://www.reibang.com/p/34cda6a121db
4.緩存做什么腐巢?
我們使用場(chǎng)景比如:離線(xiàn)加載品追,預(yù)加載,本地通訊錄...等系忙,對(duì)非網(wǎng)絡(luò)數(shù)據(jù)诵盼,使用本地?cái)?shù)據(jù)管理的一種,具體使用場(chǎng)景有很多。
5.NSCache
NSCache 是蘋(píng)果提供的一套緩存機(jī)制风宁,用法和 NSMutableDictionary 類(lèi)似洁墙,在
AFNetworking,SDWebImage戒财,Kingfisher 中都有用到热监。它相當(dāng)于字典的安全版本,不會(huì)出現(xiàn)多線(xiàn)程的問(wèn)題饮寞,線(xiàn)程安全的孝扛。說(shuō)明:
1.當(dāng)內(nèi)存不足時(shí) NSCache 會(huì)自動(dòng)釋放內(nèi)存,NSCache 設(shè)置緩存對(duì)象數(shù)量和占用的內(nèi)存大小幽崩,當(dāng)緩存超出了設(shè)置會(huì)自動(dòng)釋放內(nèi)存苦始。
2.NSCache 是 Key-Value 數(shù)據(jù)結(jié)構(gòu),其中 key 是強(qiáng)引用慌申,不實(shí)現(xiàn) NSCoping 協(xié)議陌选,作為 key 的對(duì)象不會(huì)被拷貝。
- 舉例:
@interface NSCacheVC ()<NSCacheDelegate>
@property (nonatomic, strong) NSCache *myCache;
@end
@implementation NSCacheVC
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor purpleColor];
self.myCache = [[NSCache alloc]init];
self.myCache.delegate = self;
for (int i = 0; i<10; i++) {
[self.myCache setObject:[NSString stringWithFormat:@"%d", i] forKey:@(i) cost: 1];
}
for (int i = 0; i<10; i++) {
NSLog(@"NSCache取出---%@", [self.myCache objectForKey:@(i)]);
}
/// 清除緩存
[self.myCache removeAllObjects];
/// 設(shè)置緩存限制
self.myCache.totalCostLimit = 5;
NSLog(@"設(shè)置緩存限制后=================");
for (int i = 0; i<10; i++) {
// 設(shè)置成本數(shù)為1
[self.myCache setObject:[NSString stringWithFormat:@"%d", i] forKey:@(i) cost: 1];
}
for (int i = 0; i<10; i++) {
NSLog(@"NSCache取出---%@", [self.myCache objectForKey:@(i)]);
}
/// 清除緩存
[self.myCache removeAllObjects];
NSLog(@"設(shè)置緩存限制后但未設(shè)置成本數(shù)cost=================");
for (int i = 0; i<10; i++) {
[self.myCache setObject:[NSString stringWithFormat:@"%d", i] forKey:@(i)];
}
for (int i = 0; i<10; i++) {
NSLog(@"NSCache取出---%@", [self.myCache objectForKey:@(i)]);
}
/// 清除緩存
[self.myCache removeAllObjects];
}
// 即將回收對(duì)象的時(shí)候進(jìn)行調(diào)用蹄溉,實(shí)現(xiàn)代理方法之前要遵守NSCacheDelegate協(xié)議咨油。
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{
NSLog(@"NSCache回收---%@", obj);
}
@end
1.plist(屬性列表)文件
plist:是一種明文的輕量級(jí)存儲(chǔ)方式,最常用的格式是 XML 格式柒爵,比如新建一個(gè)項(xiàng)目時(shí)系統(tǒng)會(huì)提供一個(gè) info.plist 文件役电,這種方式的安全性很低,一般使用 plist 文件存儲(chǔ)的數(shù)據(jù)都是不需要加密棉胀,存儲(chǔ)少量法瑟,簡(jiǎn)單的不重要數(shù)據(jù),plist 文件能存儲(chǔ)字典和數(shù)組唁奢,不能存儲(chǔ)自定義對(duì)象瓢谢。
說(shuō)明:
屬性列表是一種 XML 格式的文件,拓展名為 plist 如果是對(duì) NSString驮瞧、NSDictionary、NSArray枯芬、NSData论笔、NSNumber 等類(lèi)型以及他們的可變類(lèi)型等,就可以使用 writeToFile:atomically: 方法直接將對(duì)象寫(xiě)到屬性列表文件中存儲(chǔ)千所,讀取時(shí)使用 arrayWithContentsOfFile:(數(shù)組)狂魔、dictionaryWithContentsOfFile(字典)等方法。
使用場(chǎng)景:
主要是用于不用加密的數(shù)據(jù)存儲(chǔ)淫痰,比如在添加地址中使用的 pickerView 中的 cities.plist 文件最楷。
舉例:
/**
* Plist文件
*/
- (void)setUpPlist {
NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [path stringByAppendingPathComponent:@"Person.plist"];
NSDictionary *dict = @{
@"name" : @"William",
@"age" : @18,
@"height" : @1.75f
};
// 將數(shù)據(jù)寫(xiě)入Plist
[dict writeToFile:filePath atomically:YES];
NSLog(@"%@", filePath);
// 讀取plist中的數(shù)據(jù)
NSDictionary *dicts = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSLog(@"dict = %@",dicts);
NSString *str = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"str = %@", str);
}
plist 文件其他補(bǔ)充:
plist文件是將某些特定的類(lèi),通過(guò)XML文件的方式保存在目錄中,可以被序列化的類(lèi)型只有如下幾種:
NSArray;
NSMutableArray;
NSDictionary;
NSMutableDictionary;
NSData;
NSMutableData;
NSString;
NSMutableString;
NSNumber;
NSDate;
1.獲得文件路徑:
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];
2.存儲(chǔ):
NSArray *array = @[@"123", @"456", @"789"];
[array writeToFile:fileName atomically:YES];
3.讀茸阉铩:
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
NSLog(@"%@", result);
4.注意:
只有以上列出的類(lèi)型才能使用plist文件存儲(chǔ)烈评,不能直接存儲(chǔ)自定義模型對(duì)象,如果要自定義則只能將自定義模型對(duì)象轉(zhuǎn)換為字典存儲(chǔ)犯建。
存儲(chǔ)時(shí)使用 writeToFile: atomically: 方法讲冠,其中 atomically 表示是否需要先寫(xiě)入一個(gè)輔助文件,再把輔助文件拷貝到目標(biāo)文件地址适瓦。這是更安全的寫(xiě)入文件方法竿开,一般都寫(xiě) YES。
讀取時(shí)使用 arrayWithContentsOfFile: 方法玻熙。
plist 只能識(shí)別字典否彩,數(shù)組。
2.Preference\NSUserDefaults(偏好設(shè)置)
很多 iOS 應(yīng)用都支持偏好設(shè)置來(lái)存儲(chǔ)數(shù)據(jù)肌毅,比如保存用戶(hù)名、密碼姑原、字體大小等設(shè)置悬而,iOS 提供了一套標(biāo)準(zhǔn)的解決方案來(lái)為應(yīng)用加入偏好設(shè)置功能,每個(gè)應(yīng)用都有個(gè) NSUserDefaults 實(shí)例锭汛,通過(guò)它來(lái)存取偏好設(shè)置笨奠。注意偏好設(shè)置也不能存儲(chǔ)自定義對(duì)象。
說(shuō)明:
1.偏好設(shè)置是專(zhuān)門(mén)用來(lái)保存應(yīng)用程序的配置信息的唤殴, 一般情況不要在偏好設(shè)置中保存其他數(shù)據(jù)般婆。如果利用系統(tǒng)的偏好設(shè)置來(lái)存儲(chǔ)數(shù)據(jù),默認(rèn)就是存儲(chǔ)在 Preferences 文件夾下面的朵逝,偏好設(shè)置會(huì)將所有的數(shù)據(jù)都保存到同一個(gè)文件中蔚袍。使用偏好設(shè)置對(duì)數(shù)據(jù)進(jìn)行保存之后,它保存到系統(tǒng)的時(shí)間是不確定的配名,會(huì)在將來(lái)某一時(shí)間點(diǎn)自動(dòng)將數(shù)據(jù)保存到 Preferences 文件夾下面啤咽。
2.如果需要即刻將數(shù)據(jù)存儲(chǔ),可以使用 [defaults synchronize]渠脉,因?yàn)?UserDefaults 設(shè)置數(shù)據(jù)時(shí)不是立即寫(xiě)入宇整,而是根據(jù)時(shí)間戳定時(shí)地把緩存中的數(shù)據(jù)寫(xiě)入本地磁盤(pán),所以調(diào)用了 set 方法之后數(shù)據(jù)有可能還沒(méi)有寫(xiě)入磁盤(pán)應(yīng)用程序就終止了芋膘。出現(xiàn)以上問(wèn)題鳞青,可以通過(guò)調(diào)用 synchornize 方法 [defaults synchornize]; 強(qiáng)制寫(xiě)入霸饲。
3.所有的信息都寫(xiě)在一個(gè)文件中,對(duì)比簡(jiǎn)單的 plist 可以保存和讀取基本的數(shù)據(jù)類(lèi)型臂拓,獲取 NSuserDefaults 保存(讀群衤觥)數(shù)據(jù)。
4.對(duì)于NSUerdefaults來(lái)說(shuō) 一般可以用來(lái)保存用戶(hù)的偏好設(shè)置 比如登陸賬號(hào) 密碼這些埃儿。 除此之外還可以用它來(lái)保存圖片器仗, 字符串 , 數(shù)字 和對(duì)象童番。它被保存到項(xiàng)目中的Plists文件里面里精钮。保存圖片 一般用它里面的兩個(gè)方法 圖片保存可以用PNG或者JPG對(duì)應(yīng)的方法 先轉(zhuǎn)換成NSData 再用NSUerdefaults保存 保存的時(shí)候?yàn)榱俗屗R上存下來(lái)要用synchronize 。它還可以用來(lái)在程序間進(jìn)行反向傳值剃斧。
5.注意:偏好設(shè)置是專(zhuān)門(mén)用來(lái)保存應(yīng)用程序的配置信息的轨香,一般不要在偏好設(shè)置中保存其他數(shù)據(jù);如果沒(méi)有調(diào)用synchronize方法幼东,系統(tǒng)會(huì)根據(jù)I/O情況不定時(shí)刻地保存到文件中臂容,所以如果需要立即寫(xiě)入文件的就必須調(diào)用synchronize方法;偏好設(shè)置會(huì)將所有數(shù)據(jù)保存到同一個(gè)文件中根蟹。即preference目錄下的一個(gè)以此應(yīng)用包名來(lái)命名的plist文件脓杉。
使用場(chǎng)景:
用來(lái)保存應(yīng)用程序設(shè)置和屬性、用戶(hù)保存的數(shù)據(jù)简逮。用戶(hù)再次打開(kāi)程序或開(kāi)機(jī)后這些數(shù)據(jù)仍然存在球散,比如保存用戶(hù)名、密碼散庶。
舉例:
3.NSKetedArchiver(歸檔 - 解歸檔)
歸檔:即序列化蕉堰,將一個(gè) OC 對(duì)象轉(zhuǎn)換成 NSData(二進(jìn)制)的操作就叫做對(duì)象的序列化。解歸檔:即反序列化悲龟,將本地的二進(jìn)制數(shù)據(jù)轉(zhuǎn)為一個(gè) OC 對(duì)象的操作就叫做反序列化屋讶。OC 對(duì)象需要通過(guò)遵守 NSCoding 協(xié)議,并且實(shí)現(xiàn)協(xié)議中的兩個(gè)方法须教,才能支持序列化和反序列化操作皿渗。注意歸檔 NSCoding 可以存儲(chǔ)自定義對(duì)象。由于決大多數(shù)支持存儲(chǔ)數(shù)據(jù)的 Foundation 和 Cocoa Touch 類(lèi)都遵循了 NSCoding 協(xié)議轻腺,因此對(duì)于大多數(shù)類(lèi)來(lái)說(shuō)歸檔相對(duì)而言還是比較容易實(shí)現(xiàn)的羹奉。
說(shuō)明:
1.NSKeyedArchiver 如果對(duì)象是 NSString、NSDictionary约计、NSArray、NSData迁筛、NSNumber 等類(lèi)型煤蚌,可以直接用 NSKeyedArchiver 進(jìn)行歸檔和恢復(fù)耕挨。不是所有的對(duì)象都可以直接用這種方法進(jìn)行歸檔,只有遵守了 NSCoding 協(xié)議的對(duì)象才可以尉桩,并且實(shí)現(xiàn)協(xié)議中的兩個(gè)方法筒占。
2.NSCoding 協(xié)議有2個(gè)方法:
2.1 encodeWithCoder: 每次歸檔對(duì)象時(shí)都會(huì)調(diào)用這個(gè)方法。一般在這個(gè)方法里面指定如何歸檔對(duì)象中的每個(gè)實(shí)例變量蜘犁,可以使用 encodeObject:forKey: 方法歸檔實(shí)例變量翰苫。
2.2 initWithCoder: 每次從文件中恢復(fù)(解碼)對(duì)象時(shí)都會(huì)調(diào)用這個(gè)方法。一般在這個(gè)方法里面指定如何解碼文件中的數(shù)據(jù)為對(duì)象的實(shí)例變量这橙,可以使用 decodeObject:forKey 方法解碼實(shí)例變量奏窑。3.如果需要?dú)w檔的類(lèi)是某個(gè)自定義類(lèi)的子類(lèi)時(shí),就需要在歸檔和解檔之前先實(shí)現(xiàn)父類(lèi)的歸檔和解檔方法屈扎。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法埃唯,確保繼承的實(shí)例變量也能被編碼,即也能被歸檔鹰晨,以及也能被解碼墨叛,即也能被恢復(fù)。
4.將各種類(lèi)型的對(duì)象存儲(chǔ)到文件中模蜡,不僅僅是字符串或者字典漠趁,還能實(shí)現(xiàn)對(duì)自定義類(lèi)的對(duì)象進(jìn)行歸檔。
5.NSKeyedArchiver 是一種輕量級(jí)存儲(chǔ)的持久化方案忍疾,數(shù)據(jù)化歸檔時(shí)經(jīng)過(guò)加密處理的闯传,所以安全性遠(yuǎn)高于 plist,數(shù)據(jù)歸檔可以存儲(chǔ)一些復(fù)雜的對(duì)象膝昆,數(shù)據(jù)保存前會(huì)經(jīng)過(guò)二進(jìn)制處理丸边。
6.缺點(diǎn):它的局限是一次性讀取和存儲(chǔ)操作。歸檔的形式來(lái)保存數(shù)據(jù)只能一次性歸檔保存以及一次性解壓荚孵。所以只能針對(duì)小量數(shù)據(jù)妹窖,如果想改動(dòng)數(shù)據(jù)的某一小部分,需要解壓整個(gè)數(shù)據(jù)或者歸檔整個(gè)數(shù)據(jù)收叶。
使用場(chǎng)景:
當(dāng)我們想要存儲(chǔ)一些更加復(fù)雜的自定義數(shù)據(jù)時(shí)蜓萄,如果我們的程序此時(shí)不需要執(zhí)行查詢(xún)數(shù)據(jù)、數(shù)據(jù)遷移等操作澄峰,或者是并非所有的數(shù)據(jù)都有發(fā)雜的關(guān)系圖嫉沽,這時(shí)候數(shù)據(jù)的歸檔方案是最適合的。使用 archive 格式的文件將歸檔的數(shù)據(jù)存儲(chǔ)在沙盒目錄下俏竞,這種格式讀取出來(lái)的是二進(jìn)制绸硕,需要用 NSKeyedUnarchiver 類(lèi)對(duì)該數(shù)據(jù)進(jìn)行解檔堂竟。
舉例:
舉例3:
Student.h
#import
#import "Book.h"
@interface Student : NSObject
@property(nonatomic, copy) NSString *name;//姓名
@property(nonatomic, assign) int age;//年齡
@property(nonatomic, strong) Book *book;//課本
@end
Student.m
#import "Student.h"
static NSString * const kStudentNameKey = @"kStudentNameKey";
static NSString * const kStudentAgeKey = @"kStudentAgeKey";
static NSString * const kBookKey = @"kBookKey";
@implementation Student
/**解檔(反序列化)*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self == [super init]) {
self.name = [aDecoder decodeObjectForKey:kStudentNameKey];
self.age = [aDecoder decodeIntForKey:kStudentAgeKey];
self.book = [aDecoder decodeObjectForKey:kBookKey];
}
return self;
}
/**歸檔(序列化)*/
- (void)encodeWithCoder:(NSCoder *)aCoder {
// 歸檔姓名(字符串對(duì)象)
[aCoder encodeObject:self.name forKey:kStudentNameKey];
// 歸檔年齡(注意:這是基本數(shù)據(jù)類(lèi)型, 如果是其他的類(lèi)型,直接調(diào)用對(duì)應(yīng)類(lèi)型的encode即可)
[aCoder encodeInteger:self.age forKey:kStudentAgeKey];
// 歸檔自定義類(lèi)(Book)對(duì)象
[aCoder encodeObject:self.book forKey:kBookKey];
}
@end
/***************************************/
viewController.m
// 保存
- (IBAction)saveDatas:(id)sender {
// 創(chuàng)建對(duì)象
Student *student = [[Student alloc] init];
student.name = @"Alex";
student.age = 15;
student.book.bookName = @"習(xí)近平中國(guó)特色社會(huì)主義"; // 獲取文件路徑
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [path stringByAppendingPathComponent:@"student.archiver"]; // 將自定義的對(duì)象保存到文件中,調(diào)用的是NSKeyedArchiver的類(lèi)方法
BOOL flag = [NSKeyedArchiver archiveRootObject:student toFile:filePath];
if (flag) {
NSLog(@"如果來(lái)到這里說(shuō)明歸檔成功");
}
}
// 讀取
- (IBAction)readDatas:(id)sender {
// 獲取文件保存的路徑
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [path stringByAppendingPathComponent:@"student.archiver"];
// 打印文件保存的路徑
NSLog(@"%@", filePath);
// 從文件中讀取對(duì)象, 解檔對(duì)象就調(diào)用NSKeyedUnarchiver的一個(gè)類(lèi)方法,unarchiveObjectWithFile: 即可
Student *student = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
if (student) {
// 來(lái)到這里說(shuō)明讀取成功
NSLog(@"%@, %d, %@", student.name, student.age, student.book.bookName);
}
}
舉例4:
舉例5:
舉例6 - NSKeyedArchiver 簡(jiǎn)單使用說(shuō)明:
NSCoding協(xié)議聲明了兩個(gè)方法玻佩,這兩個(gè)方法都是必須實(shí)現(xiàn)的出嘹。一個(gè)用來(lái)說(shuō)明如何將對(duì)象編碼到歸檔中,另一個(gè)說(shuō)明如何進(jìn)行解檔來(lái)獲取一個(gè)新對(duì)象咬崔。
1.遵循NSCoding協(xié)議
@interface Person : NSObject <NSCoding>
2.設(shè)置屬性
@property (strong, nonatomic) UIImage *avatar;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger age;
@end
3.實(shí)現(xiàn)協(xié)議方法
解檔:
- (id)initWithCoder:(NSCoder *)aDecoder {
if ([super init]) {
self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
歸檔:
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.avatar forKey:@"avatar"];
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
特別注意:如果需要?dú)w檔的類(lèi)是某個(gè)自定義類(lèi)的子類(lèi)時(shí)税稼,就需要在歸檔和解檔之前先實(shí)現(xiàn)父類(lèi)的歸檔和解檔方法。即 [super encodeWithCoder:aCoder]
和 [super initWithCoder:aDecoder] 方法;
其他使用說(shuō)明:
需要把對(duì)象歸檔是調(diào)用NSKeyedArchiver的工廠(chǎng)方法 archiveRootObject: toFile: 方法:
NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
Person *person = [[Person alloc] init];
person.avatar = self.avatarView.image;
person.name = self.nameField.text;
person.age = [self.ageField.text integerValue];
[NSKeyedArchiver archiveRootObject:person toFile:file];
需要從文件中解檔對(duì)象就調(diào)用NSKeyedUnarchiver的一個(gè)工廠(chǎng)方法 unarchiveObjectWithFile: 即可:
NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
if (person) {
self.avatarView.image = person.avatar;
self.nameField.text = person.name;
self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];
}
4.SQLite 與 FMDB
- SQLite
SQLite 是嵌入式關(guān)系型數(shù)據(jù)庫(kù)垮斯,是一個(gè)輕量級(jí)跨平臺(tái)的小型數(shù)據(jù)庫(kù)郎仆,是一種基于C語(yǔ)言開(kāi)發(fā)的輕型數(shù)據(jù)庫(kù),其最主要的特點(diǎn)就是輕量級(jí)甚脉、跨平臺(tái)丸升,當(dāng)前很多嵌入式操作系統(tǒng)都將其作為數(shù)據(jù)庫(kù)首選。雖然 SQLite 是一款輕型數(shù)據(jù)庫(kù)牺氨,但是其功能也絕不亞于很多大型關(guān)系數(shù)據(jù)庫(kù)狡耻。SQLite3:操作數(shù)據(jù)比較快、可以局部讀取猴凹、比較小型夷狰,占用的內(nèi)存資源比較少。splite 可移植性比較高郊霎,有著和 MySpl 幾乎相同的數(shù)據(jù)庫(kù)語(yǔ)句沼头,它的處理速度比 Mysql、PostgreSQL 這兩款著名的數(shù)據(jù)庫(kù)都還快书劝,以及無(wú)需服務(wù)器即可使用的優(yōu)點(diǎn)进倍。
1.在 iOS 中需要用 C 語(yǔ)言進(jìn)行對(duì)數(shù)據(jù)庫(kù)的操作、訪(fǎng)問(wèn)(無(wú)法用 oc购对,因?yàn)?libsqlite3 框架基于 C 語(yǔ)言編寫(xiě))猾昆。
2.SQLite 采用動(dòng)態(tài)數(shù)據(jù)類(lèi)型。
3.要使用 SQLite 很簡(jiǎn)單骡苞,如果在 Mac OSX 上使用可以考慮到 SQLite 官方網(wǎng)站下載命令行工具垂蜗,也可以使用類(lèi)似于 SQLiteManager、Navicat for SQLite 等工具解幽。相關(guān)鏈接:https://juejin.cn/post/6844903793327341575
SQLite 常用命令:
啟動(dòng) SQLite:在終端鍵入 sqlite3贴见,提示符變成 sqlite>
.help --- 顯示幫助信息
.quit/.exit --- 退出
.open --- 打開(kāi)指定的數(shù)據(jù)庫(kù)文件
.save --- 將內(nèi)存中的數(shù)據(jù)庫(kù)保存到指定的文件
.databases --- 顯示數(shù)據(jù)庫(kù)的信息
.schema ?TABLE? --- 顯示表結(jié)構(gòu)
.tables ?PATTERN? --- 顯示所有的表
.mode MODE --- 設(shè)置輸出模式
.stats ON|OFF --- 開(kāi)啟或關(guān)閉統(tǒng)計(jì)信息
.dump ?TABLE?--- 以SQL文本格式轉(zhuǎn)存數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)(SQLite)優(yōu)缺點(diǎn):
優(yōu)點(diǎn)
1.該方案可以存儲(chǔ)大量的數(shù)據(jù),存儲(chǔ)和檢索的速度非扯阒辏快片部。
2.能對(duì)數(shù)據(jù)進(jìn)行大量的聚合,這樣比起使用對(duì)象來(lái)講操作要快霜定。缺點(diǎn)
1.它沒(méi)有提供數(shù)據(jù)庫(kù)的創(chuàng)建方式
2.它的底層是基于C語(yǔ)言框架設(shè)計(jì)的档悠,沒(méi)有面向?qū)ο蟮?API捆探,用起來(lái)非常麻煩。
3.發(fā)雜的數(shù)據(jù)模型的數(shù)據(jù)建表站粟,非常麻煩。在實(shí)際開(kāi)發(fā)中我們都是使用的是 FMDB 第三方開(kāi)源的數(shù)據(jù)庫(kù)曾雕,該數(shù)據(jù)庫(kù)是基于 splite 封裝的面向?qū)ο蟮目蚣堋?/strong>
舉例 - 以學(xué)生表為例講解相關(guān)基本知識(shí):
schema TbStudent查看學(xué)生表內(nèi)容
tables列出所有表
header on 顯示表頭
—插入數(shù)據(jù):
insert into TbStudent values(1001,'王大錘','男','重慶萬(wàn)州','1990-1-6');
insert into TbStudent (stuid,stuname) values(1002,'李林’);//部分項(xiàng)
—查詢(xún)所有行所有列
select * from TbStudent;
—?jiǎng)h除數(shù)據(jù)(要加條件奴烙,否則刪除全部;下面同這)
delete from TbStudent where stuid=1004;
—更新數(shù)據(jù)
update TbStudent set stuaddr='四川綿陽(yáng)',stubirth='1993.12.3' where stuid=1002;
(其中1002的沒(méi)有加地址和出生)
--投影操作
select stuname,stusex from TbStudent;
--投影時(shí)別名(as可省剖张,別名用法)
select stuname as 姓名 , stusex as 性別 from Tbstudent;
--數(shù)據(jù)篩選(可加關(guān)系:and or)
select *from TbStudent where stusex='女';
select *from TbStudent where stusex='女' and stuaddr='南京';
select *from TbStudent where stusex='女' or stubirth='1998-1-6';
select *from TbStudent where stubirth between '1985-1-1' and '1990-12-12';
select *from TbStudent where stubirth<'1990-12-1';
--模糊查詢(xún)
select *from TbStudent where stuname like '王%';匹配任意多個(gè)字符
select *from TbStudent where stuname like'%王%';只要名字中有王字
select *from TbStudent where stuname like'王_';匹配精確一個(gè)字符
select *from TbStudent where stuname like'王__';
--排序(默認(rèn)是升序的asc(可是芯鳌);降序desc)[同時(shí)用篩選和排序搔弄,先篩后排]
select *from TbStudent order by stubirth;
select *from TbStudent order by stubirth desc;
select *from TbStudent order by stusex, stubirth desc;//先排性別后排出生
--統(tǒng)計(jì)數(shù)
select count(stusex) 總?cè)藬?shù) from TbStudent;
--分組
select stusex,count(stusex)from TbStudent group by stusex;//男女各多少人
select stuaddr 家庭住址,count(stuaddr)as 總?cè)藬?shù) from TbStudent group by stuaddr order by 總?cè)藬?shù);
--聚合函數(shù)幅虑、分組函數(shù)
count
max
min
avg:平均數(shù)
sum
-----子查詢(xún)(把一個(gè)查詢(xún)的結(jié)果作為另一個(gè)查詢(xún)的一部分來(lái)使用)
select stuname, stubirth from TbStudent where stubirth=(select min (stubirth) from TbStudent);//年齡最大的名字
select min(stubirth) from TbStudent;//選擇出年齡最大
—分頁(yè)查詢(xún)(limit a,b—>a是第幾條,b是從這條開(kāi)始依次查b個(gè))
select * from tbemp order by sal desc limit 10,5;//第10到14
-------連接查詢(xún)(一次查詢(xún)多張表)-----
--->內(nèi)連接
--->外連接 ---> 左外連接(SQLite只支持左;即不管是否滿(mǎn)足連接顾犹,都寫(xiě)出來(lái)倒庵,不滿(mǎn)足的地方補(bǔ)空)、右外連接炫刷、全外連接
//以TbDept表和TbEmp表為例:
(注意:連接兩張表時(shí)如果沒(méi)有連接條件將產(chǎn)生笛卡爾積)
寫(xiě)法1:=
select empno,name,job,dname,dloc from TbEmp, Tbdept where TbEmp.dno =TbDept.deptno;
***
select empno,name,job,dname,dloc from TbEmp as t1, Tbdept as t2 where t1.dno =t2.deptno;
寫(xiě)法2:… inner jion … on
select empno, name, job, dname, dloc from TbEmp, inner join
TbDept on dno = deptno;
***
select empno, name, job, dname, dloc from TbEmp as t1 inner join TbDept as t2 on t1.dno = t2.deptno;
***查詢(xún)薪水超過(guò)其所在部門(mén)平均薪水的員工的姓名擎宝、部門(mén)編號(hào)和工資
SELECT ename,deptno,sal from TbEmp as t1 inner join TbDept as t2 on sal>(SELECT avg(sal)from TbEmp where t1.dno=t2.deptno );
***查詢(xún)部門(mén)中薪水最高的人姓名、工資和所在部門(mén)名稱(chēng)
SELECT ename,sal,dname from TbEmp as t1 inner join TbDept as t2 on sal=(SELECT max(sal) from TbEmp where t1.dno=t2.deptno);
***注意學(xué)會(huì)創(chuàng)建臨時(shí)表
寫(xiě)在前面的是左表浑玛;寫(xiě)在后面的右表
- FMDB
FMDB 是 iOS 平臺(tái)的 SQLite 數(shù)據(jù)庫(kù)框架绍申,F(xiàn)MDB 以 OC 的方式封裝了 SQLite 的 C 語(yǔ)言 API 即基于 SQLite3 封裝的一套 OC 的 API 庫(kù)。因?yàn)?SQLite 的操作都是比較底層的 C 函數(shù)用起來(lái)比較麻煩顾彰,F(xiàn)MDB 對(duì)這些底層的東西進(jìn)行了面向?qū)ο蟮姆庋b极阅,是一個(gè)非常好用的第三方庫(kù),使用時(shí)需要添加蘋(píng)果提供的依賴(lài)庫(kù) libsqlite3.dylib涨享。FMDB的gitHub地址
其優(yōu)點(diǎn):
1.使用起來(lái)更加面向?qū)ο蠼畈∪チ撕芏嗦闊⑷哂嗟腃語(yǔ)言代碼灰伟。
2.對(duì)比蘋(píng)果自帶的 CoreData 框架拆又,更加輕量級(jí)和靈活。
3.提供了多線(xiàn)程安全的數(shù)據(jù)庫(kù)操作方法栏账,有效地防止數(shù)據(jù)混亂帖族。相關(guān)鏈接:
https://juejin.cn/post/6844903805369188359
https://juejin.cn/post/7075274270472945671
FMDB 的核心 API:
FMDatabase:代表數(shù)據(jù)庫(kù)
FMResultSet:代表操作查詢(xún)結(jié)果的游標(biāo)
FMDatabaseAdditions:對(duì) FMDatabase 類(lèi)擴(kuò)展的 Category
FMDatabasePool:數(shù)據(jù)庫(kù)連接池支持類(lèi)
FMDatabaseQueue:數(shù)據(jù)庫(kù)多線(xiàn)程操作支持類(lèi)
FMDB 舉例講解:
2.例子講解
// 創(chuàng)建數(shù)據(jù)庫(kù)
- (void) createDb {
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/test.db"];
NSLog(@"%@", path);
self.db = [[FMDatabase alloc] initWithPath:path];
if([self.db open]) {
[self createTable];
}
else {
NSLog(@"創(chuàng)建數(shù)據(jù)庫(kù)失敗!");
}
}
// 創(chuàng)建表
- (void) createTable {
NSString *sql = @"create table if not exists tb_user (username varchar(20) primary key, password varchar(20) not null, email varchar(50));";
if([self.db executeUpdate:sql]) {
[self insertData];
}
else {
NSLog(@"創(chuàng)建用戶(hù)表失敗!");
}
}
// 插入數(shù)據(jù)
- (void) insertData {
NSString *sql = @"insert into tb_user values (?,?,?);";
if([self.db executeUpdate:sql, @"jackfrued", @"123456", @"jackfrued@126.com"]) {
}
else {
NSLog(@"插入數(shù)據(jù)失敗!");
}
}
// 顯示表中的記錄
- (void) showRecords {
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/test.db"];
self.db = [[FMDatabase alloc] initWithPath:path];
if([self.db open]) {
NSString *sql = @"select * from tb_user";
FMResultSet *rs = [self.db executeQuery:sql];
NSLog(@"%d", rs.next);
while([rs next]) {
NSLog(@"Username: %@", [rs stringForColumn:@"username"]);
NSLog(@"Password: %@", [rs stringForColumn:@"password"]);
NSLog(@"Email: %@", [rs stringForColumn:@"email"]);
}
[self clearData];
}
else {
NSLog(@"創(chuàng)建數(shù)據(jù)庫(kù)失敗!");
}
}
- (void) clearData {
NSString *sql = @"delete from tb_user";
if([self.db executeUpdate:sql]) {
NSLog(@"清理數(shù)據(jù)成功!!!");
}
}
- 數(shù)據(jù)庫(kù)補(bǔ)充說(shuō)明
數(shù)據(jù)庫(kù)概念 (.db):
數(shù)據(jù)的集散地,有效地存儲(chǔ)和管理數(shù)據(jù)挡爵。App如果有大量的數(shù)據(jù)需要進(jìn)行本地存儲(chǔ)就可以考慮使用數(shù)據(jù)庫(kù)技術(shù)竖般,它不僅能夠有效的存儲(chǔ)和管理數(shù)據(jù),更重要的是提供了方便的檢索數(shù)據(jù)的手段茶鹃。簡(jiǎn)單的說(shuō)涣雕,數(shù)據(jù)庫(kù)是實(shí)現(xiàn)數(shù)據(jù)持久化的重要方案艰亮,其他的方案包括:plist文件、archieve歸檔挣郭、NSUserDefaults迄埃、普通文件等。數(shù)據(jù)庫(kù)類(lèi)型:
Oracle:甲骨文數(shù)據(jù)庫(kù)兑障,當(dāng)今牛逼關(guān)系型數(shù)據(jù)庫(kù)
DB2:IBM公司的產(chǎn)品侄非,數(shù)據(jù)倉(cāng)庫(kù)和數(shù)據(jù)挖掘功能非常強(qiáng)大
SQLServer:微軟的產(chǎn)品,適合微軟自己的Windows服務(wù)器環(huán)境
MySQL:開(kāi)源的數(shù)據(jù)庫(kù)產(chǎn)品流译,中小型站點(diǎn)的數(shù)據(jù)庫(kù)服務(wù)器首選關(guān)系型數(shù)據(jù)庫(kù):比如 SQLite逞怨。
數(shù)據(jù)庫(kù)數(shù)據(jù):若只讀取不對(duì)其操作則保存在 Nsbundle,若對(duì)它要維護(hù)修改則放在沙箱中(數(shù)據(jù)要長(zhǎng)久放在 doucument)福澡,創(chuàng)建數(shù)據(jù)庫(kù)放沙箱的 doucument文件叠赦。
關(guān)系型數(shù)據(jù)庫(kù)特點(diǎn):
1.用二維表組織數(shù)據(jù)(行:一條記錄;列:一條字段)革砸,主鍵為能夠唯一標(biāo)識(shí)一條記錄的字段(比如庫(kù)中已有的學(xué)號(hào)除秀,再錄相同的不能錄),添加這個(gè) primary key 表示它是主鍵业岁。外鍵為其他表的主鍵(外來(lái)的主鍵)鳞仙,例如兩張表人與身份證例子,pragma foreign_key = on笔时。
2.結(jié)構(gòu)化查詢(xún)語(yǔ)言(SQL)- SQL分4部分:
DDL:數(shù)據(jù)定義語(yǔ)言create(創(chuàng)建棍好;可以加前綴命名—>如創(chuàng)建學(xué)生表: create Table TBstudent)/drop(刪除)/alter(修改)
DML:操作insert(添加)/delete(刪除)/update(更新)
DQL:查詢(xún)select (重點(diǎn))
DCL:控制grant/revoke1.關(guān)系代數(shù)
2.集合論
3.實(shí)體關(guān)系圖(ER圖),實(shí)體間關(guān)系:一對(duì)一:人與身份證允耿、一對(duì)多:部門(mén)和員工借笙、多對(duì)一:讀者與圖書(shū)
4.事務(wù) ACID,即:Atomic较锡、Consistency业稼、Isolation、Duration蚂蕴;要么全成功低散,要么全失敗骡楼;要么全做熔号,要么全不做,以銀行轉(zhuǎn)賬為例鸟整。
5.CoreData
coreData 是蘋(píng)果官方在 iOS5 之后推出的綜合性數(shù)據(jù)庫(kù)引镊,其使用了對(duì)象關(guān)系映射技術(shù),將對(duì)象轉(zhuǎn)換成數(shù)據(jù),將數(shù)據(jù)存儲(chǔ)在本地的數(shù)據(jù)庫(kù)中弟头。coreData 為了提高效率需要將數(shù)據(jù)存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中吩抓,比如在使用的時(shí)候,最好是將本地的數(shù)據(jù)保存到內(nèi)存中赴恨,這樣的目的是訪(fǎng)問(wèn)速度比較快疹娶。CoreData 本身并不是一個(gè)并發(fā)安全的架構(gòu),所以在多線(xiàn)程中實(shí)現(xiàn) CoreData 會(huì)有問(wèn)題伦连。
Core Data (ORM:可以將關(guān)系模型和對(duì)象模型互轉(zhuǎn))蚓胸,這個(gè)蘋(píng)果原生處理數(shù)據(jù)庫(kù)的非常難用,可選用第三方庫(kù) ObjectRecord 和 MagicalRecord除师。各類(lèi)應(yīng)用開(kāi)發(fā)中只要牽扯到數(shù)據(jù)庫(kù)操作通常都會(huì)用到一個(gè)概念“對(duì)象關(guān)系映射(ORM)iOS 中 ORM 框架首選 Core Data,這是官方推薦的不需要借助第三方框架扔枫。無(wú)論是哪種平臺(tái)汛聚、哪種技術(shù),ORM 框架的作用都是相同的短荐,那就是將關(guān)系數(shù)據(jù)庫(kù)中的表(準(zhǔn)確的說(shuō)是實(shí)體)轉(zhuǎn)換為程序中的對(duì)象倚舀,其本質(zhì)還是對(duì)數(shù)據(jù)庫(kù)的操作(例如 Core Data 中如果存儲(chǔ)類(lèi)型配置為 SQLite 則本質(zhì)還是操作的 SQLite 數(shù)據(jù)庫(kù))。使用 Core Data 進(jìn)行數(shù)據(jù)庫(kù)存取并不需要手動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)忍宋,這個(gè)過(guò)程完全由 Core Data 框架完成痕貌,開(kāi)發(fā)人員面對(duì)的是模型,主要的工作就是把模型創(chuàng)建起來(lái)糠排,具體數(shù)據(jù)庫(kù)如何創(chuàng)建則不用管。
相關(guān)鏈接:
https://juejin.cn/post/7011708888718245925
http://t.zoukankan.com/HJiang-p-7818418.html
6.鑰匙串 Keychain
keychain 存儲(chǔ)在硬盤(pán)上,刪除了應(yīng)用干像,保存的數(shù)據(jù)還在图贸。每個(gè) APP 的 keychain 相對(duì)來(lái)說(shuō)是獨(dú)立的,但是也可以實(shí)現(xiàn) APP 之間 keychain 數(shù)據(jù)的共享乾闰,前提是同一個(gè) TeamID 下落追、且設(shè)置了數(shù)據(jù)共享。
Keychain 是 OS X 和 iOS 都提供一種安全地存儲(chǔ)敏感信息的工具涯肩,比如轿钠,存儲(chǔ)用戶(hù)ID,密碼病苗,私鑰和證書(shū)等疗垛。存儲(chǔ)這些信息可以免除用戶(hù)重復(fù)輸入用戶(hù)名和密碼的過(guò)程。Keychain Services 的安全機(jī)制保證了存儲(chǔ)這些敏感信息不會(huì)被竊取铅乡。簡(jiǎn)單說(shuō)來(lái)继谚,Keychain 就是一個(gè)安全容器。參考 apple 官網(wǎng)介紹
相關(guān)鏈接:
https://juejin.cn/post/6844903921765318669
https://juejin.cn/post/6952697138656575496
https://juejin.cn/post/6903710640817307655
7.云服務(wù) iCloud
iCloud 文檔存儲(chǔ)功能來(lái)滿(mǎn)足應(yīng)用數(shù)據(jù)云存儲(chǔ)的需求,用戶(hù)可以在自己 iCloud 賬號(hào)下的任何設(shè)備訪(fǎng)問(wèn)或修改 App 的這部分?jǐn)?shù)據(jù)花履。iOS iCloud 存儲(chǔ)中芽世,蘋(píng)果提供了三個(gè)功能:Key-value storage、iCloud Documents诡壁、CloudKit济瓢。iCloud 存儲(chǔ)空間就是蘋(píng)果設(shè)備 icloud 云端數(shù)據(jù)存儲(chǔ)的空間,屬于一種云存儲(chǔ)妹卿,一般會(huì)自帶 5GB 的存儲(chǔ)空間旺矾,若用戶(hù)需要更大的存儲(chǔ)空間,是可以選擇購(gòu)買(mǎi)的夺克。
說(shuō)明:
- iCloud 可以在iOS 設(shè)備和 iPadOS 設(shè)備開(kāi)啟箕宙、鎖定并連接到電源時(shí),通過(guò) Wi-Fi 自動(dòng)備份您的設(shè)備铺纽,用戶(hù)可以使用 iCloud 云備份來(lái)恢復(fù) iOS 或 iPadOS 設(shè)備柬帕,或者無(wú)縫設(shè)置新設(shè)備。
2.查看在 iOS 設(shè)備狡门、iPadOS 設(shè)備和 Mac 上打開(kāi)的網(wǎng)站(iCloud 標(biāo)簽頁(yè))陷寝。即使在離線(xiàn)狀態(tài)下,也可以閱讀閱讀列表中的文章其馏。另外也可以在 iOS 設(shè)備凤跑、iPadOS 設(shè)備、Mac 和 Windows 電腦上使用相同的書(shū)簽叛复。請(qǐng)參閱 Safari 瀏覽器中的 iCloud 標(biāo)簽頁(yè)仔引、書(shū)簽和閱讀列表。
相關(guān)鏈接:
https://juejin.cn/post/6844903615723733000
https://baijiahao.baidu.com/s?id=1719371222823021907&wfr=spider&for=pc
8.YYCache 緩存
相關(guān)鏈接:
https://juejin.cn/post/6844903776113917966
https://juejin.cn/post/6885605205380562952
https://juejin.cn/post/6844903694341767182
9.bbx 司機(jī)端舉例
舉例1:新訂單有個(gè)提示語(yǔ)新字
場(chǎng)景1:在任務(wù)列表接到新訂單或者在 App 中收到新訂單推送的時(shí)候褐奥,在任務(wù)列表頁(yè)面訂單 cell 上面會(huì)提示有個(gè)新字肤寝,地圖頁(yè)面氣泡有個(gè)新字,點(diǎn)擊操作改訂單(滑動(dòng)或者打電話(huà)抖僵、導(dǎo)航..)則表示已經(jīng)操作過(guò)不是新訂單了則去掉新字鲤看。這個(gè)通過(guò)判斷訂單 id 來(lái)區(qū)別,可以在訂單列表綁定的數(shù)據(jù)模型里面封裝:通過(guò) id 添加到新訂單列表耍群、判斷是否是新訂單义桂、從新訂單 id 列表中移除指定訂單 id 等方法。
應(yīng)用1 - 判斷是否是新訂單:isNewOrder
應(yīng)用2 - 添加到新訂單列表:addIntoNewOrderList
應(yīng)用3 - 從新訂單 id 列表中移除指定訂單 id :removeFormNewOrderList
舉例2:成都機(jī)場(chǎng)提示
場(chǎng)景2:定位成都的司機(jī),未報(bào)班狀態(tài)下訪(fǎng)問(wèn)首頁(yè)堰酿,新增“成都地區(qū)有新投運(yùn)機(jī)場(chǎng)”相關(guān)提示疾宏。
1.提示內(nèi)容:成都地區(qū)存在新投運(yùn)機(jī)場(chǎng),請(qǐng)您在接到相關(guān)訂單后及時(shí)跟乘客確認(rèn)目的地触创,以免走錯(cuò)機(jī)場(chǎng)坎藐。
2.展示邏輯:優(yōu)化上線(xiàn)后推送給定位為“成都”的司機(jī),司機(jī)非報(bào)班狀態(tài)下可見(jiàn)此提示哼绑,司機(jī)點(diǎn)擊“X”后隱藏不再展示橫幅岩馍。
3.注意2種情況:
第一種是同一部手機(jī)多次登錄同一個(gè)賬號(hào)或者同一部手機(jī)登錄多個(gè)賬號(hào)的時(shí)候,點(diǎn)擊 X 關(guān)閉提示語(yǔ)會(huì)記錄關(guān)閉次數(shù)抖韩,展示的時(shí)候需要判斷當(dāng)前賬號(hào)與關(guān)閉賬號(hào)是否是同一個(gè)賬號(hào)蛀恩。如果關(guān)閉次數(shù)大于0,判斷如果是同一個(gè)賬號(hào)則表示之前展示過(guò)且被關(guān)閉過(guò)則不需要展示茂浮,如果不是同一個(gè)賬號(hào)則表示關(guān)閉的是其他賬號(hào)赦肋,當(dāng)前賬號(hào)沒(méi)有被關(guān)閉過(guò)沒(méi)有關(guān)閉次數(shù)即未展示過(guò)或者展示過(guò)但未被關(guān)閉過(guò),這個(gè)時(shí)候需要展示励稳。
第二種情況是同一個(gè)賬號(hào)被多部手機(jī)登錄的時(shí)候,如果關(guān)閉次數(shù)等于0囱井,即第一次進(jìn)來(lái)頁(yè)面未報(bào)班的時(shí)候都展示驹尼。即使賬號(hào)在 A 手機(jī)登錄展示過(guò)被關(guān)閉過(guò),再在 B 手機(jī)上登錄一樣需要重新走 A 的邏輯庞呕,第一次進(jìn)來(lái)頁(yè)面未報(bào)班的時(shí)候還是需要展示提示語(yǔ)新翎,即這個(gè)緩存以手機(jī)為準(zhǔn),不以賬號(hào)為準(zhǔn)住练。
舉例3:訂單有個(gè)提示標(biāo)簽
場(chǎng)景3:如果是新用戶(hù)即首次下單的用戶(hù)地啰,對(duì)于貨件訂單且訂單備注包含類(lèi)型“手機(jī)數(shù)碼、數(shù)碼產(chǎn)品讲逛、大物件亏吝、其它、其他”等盏混,如果訂單狀態(tài)為上車(chē)了則不展示蔚鸥,如果是還沒(méi)有上車(chē)分2種情況,第一種是之前沒(méi)有展示過(guò)或者展示過(guò)沒(méi)有關(guān)閉則展示许赃,第二種是之前展示過(guò)且被關(guān)閉過(guò)則不展示提示標(biāo)簽止喷。
注意:
1.如果賬號(hào)在手機(jī) A 登錄有展示標(biāo)簽,點(diǎn)擊關(guān)閉后再在手機(jī) B 登錄發(fā)現(xiàn)也會(huì)有標(biāo)簽混聊,即緩存跟手機(jī)有關(guān)跟賬號(hào)沒(méi)有關(guān)系弹谁,兩個(gè)手機(jī)獨(dú)立的,相當(dāng)于各自都是第一次走邏輯互不影響。
2.如果賬號(hào)在手機(jī)上登錄有展示標(biāo)簽预愤,點(diǎn)擊關(guān)閉不展示標(biāo)簽沟于。這個(gè)時(shí)候 App 卸載重新安裝,新裝的 App 相當(dāng)于第一次重新走邏輯會(huì)展示標(biāo)簽鳖粟。