iOS常用的幾種數據存儲方式

来源:http://www.cnblogs.com/liuwenqiang/archive/2016/06/01/5548188.html
-Advertisement-
Play Games

之前由於剛入行不久,對數據持久化不是很瞭解,尤其是用資料庫存儲大量數據的操作。經過摸索就在此總結一下,方便以後查閱 下麵就簡單介紹一下: 1.NSUserDefaults 感覺最常用的小量數據,屬性,例如,賬號,密碼之類的;適合存儲輕量級的本地數據 (個人認為這種比較簡單) NSUserDefaul ...


之前由於剛入行不久,對數據持久化不是很瞭解,尤其是用資料庫存儲大量數據的操作。經過摸索就在此總結一下,方便以後查閱

下麵就簡單介紹一下:

1.NSUserDefaults

感覺最常用的小量數據,屬性,例如,賬號,密碼之類的;適合存儲輕量級的本地數據 (個人認為這種比較簡單)

NSUserDefaults支持的數據格式有:NSNumberIntegerFloatDouble),NSStringNSDateNSArrayNSDictionaryBOOL類型

直接看代碼比較容易理解:

 //    測試數據
    NSArray *myArray = [NSArray arrayWithObjects:@"hello", @"world", nil];
    NSDictionary *myDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"enuo", @"20", nil] forKeys:[NSArray arrayWithObjects:@"name", @"age", nil]];
    //    存入
    [[NSUserDefaults standardUserDefaults] setObject:myArray forKey:@"arry"];
    [[NSUserDefaults standardUserDefaults] setObject:myDictionary forKey:@"dict"];
    
    //這裡建議同步存儲到磁碟中,但是不是必須的
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    //    讀取
    NSArray *arr= [[NSUserDefaults standardUserDefaults] objectForKey:@"arry"];
    NSDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:@"dict"];
    NSLog(@"------%@----\n-----%@------",arr,dict);
    
    
    // 清除數據
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"keyName"];

建議:[NSUserDefaults standardUserDefaults] 可以在項目中定義一個全局的巨集,這樣使用起來更便捷。


2.歸檔

 

目的是為了長時間存放有組織的數據集

(1)簡單的歸檔方式 但是只能存儲單個對象。

 //    (1)歸檔
    NSArray *array = [NSArray arrayWithObjects:@1,@2,@3, nil];
    NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
    BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];
    
    NSLog(@"%d",success);
    NSLog(@"%@",filePath);
    
    //    (2)反歸檔
    NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
    id OUTarray = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"%@",OUTarray);
    

 

(2)可以將多個對象歸檔成一個文件。

 //    (1)歸檔
    NSMutableArray *arrayArchiver = [NSMutableArray arrayWithObjects:@"BigDragon",@"BigBiao",@"BigBaby", nil];
    NSMutableData *data = [NSMutableData data];
    
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    //編碼
    [archiver encodeObject:arrayArchiver forKey:@"array"];
    [archiver encodeObject:@"Jason‘s friends" forKey:@"name"];
    
    //編碼完成之後,對象已經存儲到data之中。
    [archiver finishEncoding];
    
    NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
    BOOL successtwo = [data writeToFile:filePathtwo atomically:YES];
    NSLog(@"------%d",successtwo);
    
    
    //    (2)反歸檔
    
    NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
    //讀取歸檔數據
    NSData *dataUnarchiver = [[NSData alloc] initWithContentsOfFile:filePathtwo];
    
    //創建解歸檔對象,進行反歸檔
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataUnarchiver];
    
    //反歸檔
    NSArray *arrayUnarchiver = [unarchiver decodeObjectForKey:@"array"];
    NSLog(@"----%@",arrayUnarchiver);
    
    NSString *nameUnarchiver = [unarchiver decodeObjectForKey:@"name"];
    NSLog(@"-----%@",nameUnarchiver);

 

(3)使用工具類(感覺如果使用歸檔,一般使用工具類,相對來說便捷一點)

下麵就先建個工具類;Person類

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject<NSCoding>  //需要遵守NSCoding協議

@property (nonatomic,strong) NSString *name; //帶歸檔類型
@property (nonatomic,assign) NSInteger age;
@property (nonatomic,strong) NSString *gender;

- (NSString *)description;
@end

Person.m

/**
 該對象對應的類必須提供encodeWithCoder:和initWithCoder:方法。前一個方法告訴系統怎麼對對象進行編碼,而後一個方法則是告訴系統怎麼對對象進行解碼
 */

// 歸檔方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
    [aCoder encodeObject:self.gender forKey:@"gender"];
}
// 反歸檔方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    
    if (self != nil) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
        self.gender = [aDecoder decodeObjectForKey:@"gender"];
    }
    return self;
}

- (NSString *)description
{
    NSString *string = [NSString stringWithFormat:@"%@\n %ld\n %@",self.name,self.age,self.gender];
    return string;
}

 在控制器用的時候:

    Person *person = [[Person alloc]init];
    
    person.name = @"rose";
    person.age = 25;
    person.gender = @"man";
    
    // 歸檔,調用歸檔方法
    NSString *filePath3 = [NSHomeDirectory() stringByAppendingString:@"person.plist"];
    BOOL success3 = [NSKeyedArchiver archiveRootObject:person toFile:filePath3];
    NSLog(@"=====%d",success3);
    
    // 反歸檔,調用反歸檔方法
    Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath3];
    NSLog(@"=======%@",per);

 

3.寫入文件

主要的步驟:

    //第一步:獲得文件即將保存的路徑:(永久保存在磁碟中)
    //    文件存儲的相對目錄
    NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString*path = filePaths.firstObject;
    
    //第二步:生成在該路徑下的文件:
    NSString *FileName=[path stringByAppendingPathComponent:@"flieName"];//fileName就是保存文件的文件名
  
// 第三步:往文件中寫入數據:
NSData *data; [data writeToFile:FileName atomically:YES];//將NSData類型對象data寫入文件,文件名為FileName
// 最後:從文件中讀出數據: NSData *outdata=[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//從FileName中讀取出數據

下麵就簡單的舉幾個例子

#pragma mark--1.字元串寫入
    //    NSString *strfilepath = [path stringByAppendingPathComponent:@"str.text"];
    NSString *strfilepath = [path stringByAppendingString:@"/text.text"];
    NSString *INstr = @"字元串寫入文件";
    [INstr writeToFile:strfilepath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    
    //    讀取文件
    NSString *OUTstr  = [[NSString alloc]initWithContentsOfFile:strfilepath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"----%@-----",OUTstr);
    
    
#pragma mark-2、數組對象寫入文件
    //    構造數組plist文件的存儲路徑
    NSString*arrypath = [path stringByAppendingPathComponent:@"arry.plist"];
    NSArray *INarr = @[@"hahah",@"hehhe",@"heihei"];
    [INarr writeToFile:arrypath atomically:YES];
    
    //    讀取文件
    NSArray *outarr =  [[NSArray  array]initWithContentsOfFile:arrypath];
    NSLog(@"----%@-----",outarr);
    
    
#pragma mark-3、字典對象寫入文件
    NSString*dictpath = [path stringByAppendingPathComponent:@"dict.plist"];
    NSDictionary *dict = @{@"姓名":@"liuwenqiang",@"年齡":@"25",@"職業":@"ios"};
    [dict writeToFile:dictpath atomically:YES];
    
    //    讀取文件
    NSDictionary *OUTdict =  [[NSDictionary  alloc]initWithContentsOfFile:dictpath];
    NSLog(@"----%@-----",OUTdict);
    
    
    
#pragma mark-4、二進位對象寫入文件
    NSString *datapath = [path stringByAppendingPathComponent:@"song.m4a"];
    UIImage *image = [UIImage imageNamed:@"image"];
    NSData *imagedata = UIImageJPEGRepresentation(image, 1);
    [imagedata writeToFile:datapath atomically:YES];
    
    //    讀取文件
    NSData *OUTdata =  [[NSData  alloc]initWithContentsOfFile:datapath];
    NSLog(@"----%@-----",OUTdata);
    

 

4.資料庫

 

對於大型的數據存儲,再使用上面的方法顯然不適用了,該使用資料庫了,我在項目中使用的是第三方的資料庫FMDB,個人感覺比較好用,使用比較順手。

那麼什麼是大型數據,我認為的就是那種像app里的列表之類的,由於列表的數據量相當比較大,如果像我們的應用,列表中還有列表圖的話,那就更大了。

當初在看資料庫之前,總感覺很難理解,不好學,但是慢慢的理解了,也並不是那麼難理解,(下麵的方法是需要在工具類的.h中聲明的,這樣控制器中才能調到)

在操作之前,需要先下載一個FMDB 拉到項目中    附上: FMDB下載地址

先創建一個工具類 fmbdTool

(1)創庫建表 

@implementation FmdbTool

{
    FMDatabase *db;
}
-(NSString*)createFMDBTable:(NSString *)type
{
    NSString *str;
    //1.獲得資料庫文件的路徑
    NSString *doctorpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    
    NSString *filePath =  [doctorpath stringByAppendingPathComponent:@"doctor.sqlite"];
//    NSLog(@"-------路徑----%@-------",filePath);
    //2.獲得資料庫
    db = [FMDatabase databaseWithPath:filePath];
    //3.打開資料庫
    if ([db open]) {
        //4.創表
        BOOL result;
        if ([type isEqualToString:@"doctor"]) {
    
            result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];
            
        }
        
        if (result) {
//            NSLog(@"====建表成功--------type=== %@",type);
            
            str = @"yes";
            
        }else
        {
            NSLog(@"====建表失敗");
            str = @"no";
        }
    }else {
        NSLog(@"faile to create a FMDB");
        str = @"no";
    }
    
    return str;
}

在我的項目中,由於有很多的列表要做數據存儲,因此我在創建庫的方法中加了一個參數type,為每個要存儲的頁面都建一張表,並把所有的表都放到

doctor.sqlite這個庫中。
在創建表的時候,首先要[db open]打開資料庫,該返回數據類型是bool,當為真的時候,再創建表
 result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];
doctordict是個數字類型的數據,就是像後臺返回的下麵數據中,doctorInfoList欄位,所以doctordict的類型是blob 。並且由於該欄位不可能為空,故在建表的時候 NOT NULL 。
列表做了分頁請求,所以在表中把頁碼存儲了,page_ID integer NOT NULL。 datacount是列表總的頁數。


(2)插入數據

//插數據
-(void)addDataInsetTable:(NSArray *)doctorListArry page:(NSInteger)page datacount:(NSString*)datacount type:(NSString *)type
{
    if ([db open]) {
        
        NSString *pagestr = [NSString stringWithFormat:@"%ld",(long)page];
        NSError *err = nil;
        
        NSData *jsonData  = [NSJSONSerialization dataWithJSONObject:doctorListArry options:NSJSONWritingPrettyPrinted error:&err];
        
        NSString *jsonStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
        
        if ([type isEqualToString:@"doctor"]) {
            
            [db executeUpdate:@"INSERT INTO t_doctor (doctordict,page_ID,datacount) VALUES (?,?,?);",jsonStr,pagestr,datacount];
            
        }
            
    }
    [db open];

}

插入數據是也是 先[db open]之後才能插入數據。

通過這個方法可以看出,我直接就可以把後臺返回給我的數據,responseObject[@"doctorInfoList"] 插到表中,

在插入之前,需要先把數組轉成json類型的字元串,我在這裡使用了,JSONKit    JSONKit下載地址

(3).取數據

-(NSArray *)outdata:(NSString *)type
{
    NSArray *dataArr;
    
    NSMutableArray  *aaarr = [[NSMutableArray alloc]init];
    if ([db open]) {
    
        if ([type isEqualToString:@"doctor"]) {
            FMResultSet  *res = [db executeQuery:@"SELECT * FROM t_doctor"];
            
            while (res.next) {
                
                NSString *s = [res stringForColumn:@"doctordict"];
                
                NSArray *aa = [s objectFromJSONString];
                
                [aaarr addObjectsFromArray:aa];
                dataArr = aaarr;
                
            }
            
        }
    }
    
    [db close];

    return dataArr;
}
//取出當前頁數 在該type時
-(NSString *)checkoutpage:(NSString *)type
{
    NSString *str;
    if ([db open]) {
    
            FMResultSet *res = [db executeQuery:@"SELECT * FROM t_activesecond where type = ?",type];
            
            while (res.next)
            {
                str = [res stringForColumn:@"page"];
        }
    }
    [db close];
    
    return str;
}

 

(4).刪除數據

//刪除數據
- (void)deleteData:(NSString *)type
{

    if ([db open]) {
        
        if ([type isEqualToString:@"doctor"]) {
            NSString *deleteSql = [NSString stringWithFormat:@"delete from t_doctor"];
            [db executeUpdate:deleteSql];
            
        }
    }
    
    [db close];
}

我在刪除數據的時候,只刪除了,指定表,並沒有直接把庫刪了,因為所以的表都在這個庫里。

 

 

 

先寫到這吧,如果哪裡說錯了,請指出,謝謝啦。

 

 

 

 

 

 

 

 

 




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • DAYOFWEEK(date) 返回日期date是星期幾(1=星期天,2=星期一,……7=星期六,ODBC標準)mysql> select DAYOFWEEK('1998-02-03'); -> 3 WEEKDAY(date) 返回日期date是星期幾(0=星期一,1=星期二,……6= 星期天)。  ...
  • (1) 選擇最有效率的表名順序(只在基於規則的優化器中有效): Oracle的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。假如有3個以上的表連 ...
  • 簡介 死鎖的本質是一種僵持狀態,是多個主體對於資源的爭用而導致的。理解死鎖首先需要對死鎖所涉及的相關觀念有一個理解。 一些基礎知識 要理解SQL Server中的死鎖,更好的方式是通過類比從更大的面理解死鎖。比如說一個經典的例子就是汽車(主體)對於道路(資源)的徵用,如圖1所示。 圖1.對於死鎖的直 ...
  • 引導工具GRUB詳解 引導工具GRUB詳解 引導工具GRUB詳解 導讀 引導程式是駐留在硬碟第一個扇區(MPR、主引導記錄)的程式。GRUB是一個功能強大的多系統引導程式,專門處理Linux與其它操作系統共存的問題。下麵就由我介紹一下grub.conf文件里的具體內容及其含義。 使用一下命令可以查看 ...
  • 人們對決策樹的使用 決策樹常常被應用於數據挖掘之中,是最基礎的演算法之一,幾乎每一個學習過數據挖掘的朋友都知道決策樹。但還原決策樹本來的用途,它被用於一些決策或決定時,還是比較實用和直觀的。其樹型結構指導人們進行在面對某個決策時,先關註其中幾個最重要的方向,這幾方向定下來後,再細分下去。近年來泳道路, ...
  • 公司產品中一直是採用 flash 實現文件上傳功能,但用戶的需求多了以後遇到了越來越多難以解決的問題,最後試著用碩正提供的freeform、小型頁面控制項來解決。 碩正文件上傳的實現途徑有3、4種,由於公司產品發佈的需要,就選擇了其中的 httpPost 方案,其它的象 ftp、Http put儘管也 ...
  • MSDN中的描述: Visual Studio 項目對程式的發佈和調試版本分別有單獨的配置。顧名思義,生成調試版本的目的是用於調試,而生成發佈版本的目的是用於版本的最終分發。 如果在 Visual Studio 中創建程式,Visual Studio 將自動創建這些配置並設置適當的預設選項和其他設置 ...
  • 概述 當方法返回類型或屬性類型為集合時,有些開發者會千篇一律地使用IList集合。然而IList具有集合的所有操作,這意味著調用者不僅可以讀取集合信息,還能夠修改集合。業務需求本來只是為調用者提供一個可讀的集合,例如數據的查詢和展示,但當方法返回IList時,無疑隱式地開放了集合可寫的許可權。此時,我... ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...