Saving, Loading, and Application States

Saving, Loading, and Application States

Archiving

Archiving類似JAVA的序列化,可以將對(duì)象保存到硬盤上,也可加載硬盤上的數(shù)據(jù)來(lái)重新創(chuàng)建對(duì)象。

如果一個(gè)類要支持歸檔,需要實(shí)現(xiàn)NSCoding protocol,并實(shí)現(xiàn)encodeWithCoder: initWithCoder:方法.

在BKItem.h中聲明確認(rèn)NSCoding協(xié)議。

@interface BKItem : NSObject <NSCoding>

在BKItem.m中實(shí)現(xiàn)這兩個(gè)方法:

// archived
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.itemName forKey:@"itemName"];
    [aCoder encodeObject:self.serialNumber forKey:@"serialNumber"];
    [aCoder encodeObject:self.dateCreated forKey:@"dateCreated"];
    [aCoder encodeObject:self.itemKey forKey:@"itemKey"];
    
    [aCoder encodeInt:self.valueInDollars forKey:@"valueInDollars"];
}

// unarchived
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    
    if (self) {
        _itemName = [aDecoder decodeObjectForKey:@"itemName"];
        _serialNumber = [aDecoder decodeObjectForKey:@"serialNumber"];
        _dateCreated = [aDecoder decodeObjectForKey:@"dateCreated"];
        _itemKey = [aDecoder decodeObjectForKey:@"itemKey"];
        
        _valueInDollars = [aDecoder decodeIntForKey:@"valueInDollars"];
    }
    return self;
}

Application Sandbox

每個(gè)應(yīng)用都有自己的application sandbox,其他應(yīng)用無(wú)法訪問你的應(yīng)用的sandbox。


Application sandbox
Application sandbox

application sandbox由以下目錄組成:

directory description
application bundle 只讀目錄,包含應(yīng)用的可執(zhí)行文件以及資源文件,如圖片,NIB等
Documents/ 該目錄下的內(nèi)容可以同步到iTunes或iCloud
Library/Caches/ 緩存目錄,緩存后臺(tái)服務(wù)器的資源數(shù)據(jù),即使丟失,也可以從后臺(tái)再次獲取到
Library/Preferences/ application preference,會(huì)同步到iTunes或iCloud.NSUserDefaults處理此目錄數(shù)據(jù)
tmp/ 臨時(shí)目錄,NSTemporaryDirectory指向此目錄

將BKItem保存到Documents目錄,在BKItemStore.m中添加如下方法:

// 返回application sandbox的Documents目錄
- (NSString *)itemArchivePath{
    NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
    NSString *documentDirectory = [documentDirectories firstObject];
    
    return [documentDirectory stringByAppendingPathComponent:@"items.archive"];
}

NSKeyedArchiver and NSKeyedUnarchiver

利用NSKeyedArchiver將數(shù)據(jù)寫到指定路徑。

在BKItemStore.h中聲明方法來(lái)保存數(shù)據(jù)到文件系統(tǒng):

- (BOOL)saveChanges;

在BKItemStore.m中實(shí)現(xiàn)此方法:

- (BOOL)saveChanges{
    NSString *path = [self itemArchivePath];
    
    // 1. 創(chuàng)建NSKeyedArchiver實(shí)例對(duì)象;
    // 2. 調(diào)用privateItems對(duì)象(NSMutableArray)的encodeWithCoder:方法,形參是NSKeyedArchiver實(shí)例;
    // 3. 數(shù)組向其內(nèi)部的每個(gè)BKItem對(duì)象,發(fā)送encodeWithCoder:消息,形參是同樣的NSKeyedArchiver實(shí)例;
    // 4. NSKeyedArchiver寫數(shù)據(jù)到指定路徑上
    return [NSKeyedArchiver archiveRootObject:self.privateItems toFile:path];
}

什么時(shí)候來(lái)調(diào)用此方法呢?
當(dāng)用戶點(diǎn)擊home鍵,會(huì)發(fā)送applicationDidEnterBackground:消息給App Delegate,在該方法中保存數(shù)據(jù)到文件系統(tǒng)。

#import "BKItemStore.h"

@implementation BKAppDelegate
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    BOOL success = [[BKItemStore sharedStore] saveChanges];
    if (success) {
        NSLog(@"Saved all of the BKItems.");
    } else {
        NSLog(@"Could not save any of the BKItems.");
    }
}

在BKItemStore.m的初始化方法中,從歸檔文件中反序列化對(duì)象,調(diào)用NSKeyedUnarchiver的unarchiveObjectWithFile:方法。

- (instancetype)initPrivate{
    self = [super init];
    if(self){
        
        // Unarchive data
        NSString *path = [self itemArchivePath];
        _privateItems = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
        
        if (!_privateItems) {
            _privateItems = [[NSMutableArray alloc] init];
        }
    }
    return self;
}

現(xiàn)在可以動(dòng)態(tài)的創(chuàng)建BKItem,保存到文件系統(tǒng),加載他們。修改BKItemStore.m的createItem方法,不再生成隨機(jī)值:

- (BKItem *)createItem{
    //BKItem *item = [BKItem randomItem];
    BKItem *item = [[BKItem alloc] init];
    
    [self.privateItems addObject:item];
    
    return item;
}

Application States and Transitions

下圖是應(yīng)用的各種狀態(tài),以及狀態(tài)切換時(shí)執(zhí)行的方法。


Application states:

State Visible Receives Events Executes Code
Not Running No No No
Active Yes Yes Yes
Inactive Mostly No Yes
Background No No Yes
Suspended No No No

Writing to the Filesystem with NSData

利用NSData將圖片寫到文件系統(tǒng)。
在BKImageStore.m中添加如下方法,根據(jù)圖片KEY返回圖片路徑:

// 根據(jù)指定的key, 返回圖片的保存路徑
- (NSString *)imagePathForKey:(NSString *)key{
    NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDirectory = [documentDirectories firstObject];
    
    return [documentDirectory stringByAppendingPathComponent:key];
}

保存圖片到文件系統(tǒng):

- (void)setImage:(UIImage *)image forKey:(NSString *)key{
    //[self.dictionary setObject:image forKey:key];
    self.dictionary[key] = image;

    // 保存圖片到文件系統(tǒng)
    NSString *imagePath = [self imagePathForKey:key];
    NSData *data = UIImageJPEGRepresentation(image, 0.5);
    [data writeToFile:imagePath atomically:YES];
}

刪除圖片:

- (void)deleteImageForKey:(NSString *)key{
    if (!key) {
        return;
    }
    [self.dictionary removeObjectForKey:key];
    
    // 刪除文件系統(tǒng)上的圖片
    NSString *imagePath = [self imagePathForKey:key];
    [[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];
}

從文件系統(tǒng)上讀取圖片:

- (UIImage *)imageForKey:(NSString *)key{
    //return [self.dictionary objectForKey:key];
    //return self.dictionary[key];
    
    UIImage *result = self.dictionary[key];
    if (!result) {
        NSString *imagePath = [self imagePathForKey:key];
        
        // Create UIImage object from file
        result = [UIImage imageWithContentsOfFile:imagePath];
        
        if (result) {
            self.dictionary[key] = result;
        } else {
            NSLog(@"Error: unable to find %@", [self imagePathForKey:key]);
        }
    }
    return result;
}

NSNotificationCenter and Low-Memory Warnings

每個(gè)應(yīng)用都有一個(gè)NSNotificationCenter實(shí)例。
當(dāng)一個(gè)對(duì)象發(fā)送notification,notification center會(huì)轉(zhuǎn)會(huì)此notification到其observer。

比如當(dāng)內(nèi)存過低,notification center會(huì)收到UIApplicationDidReceiveMemoryWarningNotification,可以在notification center中添加此notification的observer。

BKImageStore.m中,將其注冊(cè)為UIApplicationDidReceiveMemoryWarningNotification的observer,當(dāng)內(nèi)存過低時(shí),清空?qǐng)D片所占內(nèi)存。

- (instancetype)initPrivate{
    self = [super init];
    if (self) {
        _dictionary = [[NSMutableDictionary alloc] init];
        
        // 將BKImageStore注冊(cè)了內(nèi)存過低notification的observer
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(clearCache:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    return self;
}

- (void)clearCache:(NSNotification *)note{
    NSLog(@"flushing %d images out of the cache", [self.dictionary count]);
    [self.dictionary removeAllObjects];
}

NSNotification

除了delegation和target-action pairs,notification是另外一種回調(diào)。不過delegation和target-action paris會(huì)直接發(fā)送消息到delegate和target,notification使用middl-man: NSNotificationCenter。

每個(gè)NSNotification對(duì)象都有name(notification center通過名字查找observer),object(此對(duì)象負(fù)責(zé)發(fā)送notification),可選的userInfo dictionary(包含一些poster想讓observer知道的信息)。

addObserver:selector:name:object:方法的最后一個(gè)參數(shù)如果是nil,表示任何對(duì)象發(fā)送notification,observer都會(huì)收到。如果指定了某個(gè)對(duì)象,則只有當(dāng)此對(duì)象發(fā)送notification時(shí),observer才會(huì)收到notification。

同一個(gè)notification,可以有多個(gè)對(duì)象是其observer,所以當(dāng)有多個(gè)對(duì)象需要響應(yīng)同一個(gè)event時(shí),就需要使用notification。

NSNotificationCenter和push/local notification沒有關(guān)系。

Reading and Writing to the Filesystem

對(duì)于binary data使用NSData,文本使用NSString的兩個(gè)實(shí)例方法writeToFile:atomically:encoding:error: 和initWithContentsOfFile:。除了NSString有這兩個(gè)方法,NSDictionary 和 NSArray也有,不過他們寫到文件系統(tǒng)后生成的是XML文件,而且NSDictionary 和 NSArray中的對(duì)象必須是可序列化的(property list serializable)對(duì)象:NSString, NSNumber, NSDate, NSData, NSArray, and NSDictionary.。

    NSError *err;
    
    NSString *someString = @"Text Data";
    BOOL success = [someString writeToFile:@"/some/path/file" atomically:YES encoding:NSUTF8StringEncoding error:&err];
    
    if (success) {
        NSLog(@"Error writing file: %@", [err localizedDescription]);
    }
    
    NSString *myEssay = [[NSString alloc] initWithContentsOfFile:@"/some/path/file" encoding:NSUTF8StringEncoding error:&err];
    
    if (!myEssay) {
        NSLog(@"Error reading file %@", [err localizedDescription]);
    }

注意上面代碼中的err對(duì)象,開始并沒有創(chuàng)建error對(duì)象,只是聲明了一個(gè)NSError類型的變量,只有當(dāng)錯(cuò)誤發(fā)生時(shí)才需要真正創(chuàng)建錯(cuò)誤對(duì)象。&err表示變量的內(nèi)存地址。

UIAlertView

如果要向用戶顯示錯(cuò)誤提示,可以使用UIAlertView對(duì)象。

    UIAlertView *a = [[UIAlertView alloc] initWithTitle:@"Error" message:[err localizedDescription] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [a show];

The Application Bundle

在Build Phases中查看application bundle。


在app在模擬器上運(yùn)行后,查看~/Library/Application Support/iPhone Simulator/ (version number)/Applications目錄,可以看到application sandbox,點(diǎn)擊 查看包內(nèi)容。


可以讀取application bundle中的文件,但是不能修改和添加文件:

// Get a pointer to the application bundle
NSBundle *applicationBundle = [NSBundle mainBundle];
// Ask for the path to a resource named myImage.png in the bundle
NSString *path = [applicationBundle pathForResource:@"myImage" ofType:@"png"];

本文是對(duì)《iOS Programming The Big Nerd Ranch Guide 4th Edition》第十八章的總結(jié)。


最近又被派到到JAVAEE項(xiàng)目了,而且開始加班,看書的時(shí)間越來(lái)越少了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 在多數(shù)移動(dòng)應(yīng)用中任何時(shí)候都只能有一個(gè)應(yīng)用程序處于活躍狀態(tài),如果其他應(yīng)用此刻發(fā)生了一些用戶感興趣的那么通過通知...
    莫離_焱閱讀 6,719評(píng)論 1 8
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,628評(píng)論 30 472
  • 最近一朋友正準(zhǔn)備跳槽,就從各處搜索整理一些基礎(chǔ),便于朋友復(fù)習(xí),也便于自己復(fù)習(xí)查看. 1. 回答person的ret...
    smile麗語(yǔ)閱讀 1,904評(píng)論 0 7
  • 下面是我最近兩年學(xué)習(xí)OC中的一些基礎(chǔ)知識(shí),對(duì)于學(xué)習(xí)OC基礎(chǔ)知識(shí)的人可能有些幫助,拿出來(lái)分享一下,還是那句話不喜勿噴...
    小小趙紙農(nóng)閱讀 2,829評(píng)論 1 7
  • 日暮西山近,風(fēng)動(dòng)鳥驚心。 寒來(lái)入延髓,落紅飛絮飛。 時(shí)來(lái)夏初定,寂靜無(wú)蟬鳴。 墨上心難敘,一筆一生輕。
    墨月霜花閱讀 250評(píng)論 0 2

友情鏈接更多精彩內(nèi)容