iOS開發之如何在用戶刪除應用后保持一些數據


在開發過程中我們有時候在用戶刪除時候保存一些信息在用戶下次安裝應用時候使用,這個時候我們可以使用剪切版UIPasteboard的FindUIPasteboard和鑰匙串keychain的使用

剪切版
剪切版主要分為以下兩種
UIPasteboardNameGeneral和UIPasteboardNameFind
兩種都是系統級的可以在應用刪除后仍然保留數據

開發中我們常常使用UIPasteboard的Find UIPasteboard來保存一些用戶刪除應用后需要保留的數據如UUID,用戶名,密碼等
下面是一個保存uuid到UIPasteboard的代碼
創建UDID

+ (NSString*) _uuidCreateNewUDID {
NSString* _openUDID = nil;

CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef cfstring = CFUUIDCreateString(kCFAllocatorDefault, uuid);
const char *cStr = CFStringGetCStringPtr(cfstring, CFStringGetFastestEncoding(cfstring));
unsigned char result[16];
CC_MD5(cStr, (unsigned int)strlen(cStr), result);
CFRelease(uuid);

_openUDID = [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15],
(unsigned int)(arc4random() % NSUIntegerMax)];

CFRelease(cfstring);

return _openUDID;
}

保存UDID到剪切板

NSString *openudid = [self _uuidCreateNewUDID];
NSString *checkOpenUDID = [openudid stringByAppendingFormat:kOpenUDIDAdd, nil];

//先把UDID存入字典
NSMutableDictionary *localDict = [NSMutableDictionary dictionaryWithCapacity:2];
[localDict setObject:openudid forKey:kOpenUDIDKey];
[localDict setObject:[checkOpenUDID md5] forKey:kCheckOpenUDIDKey];

// 同步數據到剪切板
UIPasteboard *slotPB = [UIPasteboard pasteboardWithName:kOpenUDIDPB create:YES];
// 設置為永久保存
[slotPB setPersistent:YES];
//把字典存入剪切版
[slotPB setData:[NSKeyedArchiver archivedDataWithRootObject:localDict] forPasteboardType:kOpenUDIDDict];

注意:在用戶使用產品過程中我們發現,當用戶在隱私里面關閉限制廣告跟蹤,然后用戶刪除應用的同時,剪切版的數據會被清空(也有可能因為硬盤容量緊張也回清除)

鑰匙串keychain
iOS的keychain服務提供了一種安全的保存私密信息(密碼,序列號,證書等)的方式。每個ios程序都有一個獨立的keychain存儲。從ios 3.0開始,跨程序分享keychain變得可行。
下面就使用keychain來實現存取用戶名和密碼。
蘋果已經有現成的類封裝好了keychain,KeychainItemWrapper.h和KeychainItemWrapper.m文件,可以在GenericKeychain實例里找到。
但是這里我只需要存取用戶名和密碼,就不用蘋果提供的類了,自己寫個簡單的類來實現就好。

KeychainManager.h

#import <Foundation/Foundation.h>

@interface KeychainManager : NSObject
+(KeychainManager*)default;
//根據字典存儲對象到鑰匙串
- (void)save:(NSString *)service data:(id)data;
//根據字典讀取鑰匙串里的對象
- (id)load:(NSString *)service;
//刪除鑰匙串里的數據
- (void)delete:(NSString *)service;
@end

KeychainManager.m

#import "KeychainManager.h"

@implementation KeychainManager
+(KeychainManager*)default
{
static KeychainManager *keychainManager = nil;
if(keychainManager == nil)
{
keychainManager = [[KeychainManager alloc] init];
}
return keychainManager;
}
- (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword,(id)kSecClass,
service, (id)kSecAttrService,
service, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
nil];
}

- (void)save:(NSString *)service data:(id)data {
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Delete old item before add new item
SecItemDelete((CFDictionaryRef)keychainQuery);
//Add new object to search dictionary(Attention:the data format)
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
//Add item to keychain with the search dictionary
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

- (id)load:(NSString *)service {
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Configure the search setting
//Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
} @catch (NSException *e) {
NSLog(@"Unarchive of %@ failed: %@", service, e);
} @finally {
}
}
if (keyData)
CFRelease(keyData);
return ret;
}

- (void)delete:(NSString *)service {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
}
@end

在app delegate的使用

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
KeychainManager *manager = [KeychainManager default];

NSString *data = [manager load:@"myName"];
if (data == nil) {
NSLog(@"Save");
NSString *dataString = @"我是誰";
[manager save:@"myName" data:dataString];
}
NSLog(@"data = %@",data);

return YES;
}

運行app你會發現Save只有在你第一次運行app時候打印,如果你把app刪除后在運行,也不會清除數據
---------------------
版權聲明:本文為CSDN博主「chris-gardner」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u014410695/article/details/50623591

OS App 升級時文件的保留情況

 

有這樣一個問題,用戶用iOS設備下載了大量的數據,保存在設備本地,如果用戶升級了應用本身,這些文件是否仍然存在。

找了一些官方解釋和Stackflow上的說明

Where You Should Put Your App’s Files

To prevent the syncing and backup processes on iOS devices from taking a long time, be selective about where you place files inside your app’s home directory. Apps that store large files can slow down the process of backing up to iTunes or iCloud. These apps can also consume a large amount of a user's available storage, which may encourage the user to delete the app or disable backup of that app's data to iCloud. With this in mind, you should store app data according to the following guidelines:

  • Put user data in the <Application_Home>/Documents/. User data is any data that cannot be recreated by your app, such as user documents and other user-generated content.

  • Handle support files—files your application downloads or generates and can recreate as needed—in one of two ways:

    • In iOS 5.0 and earlier, put support files in the <Application_Home>/Library/Caches directory to prevent them from being backed up

    • In iOS 5.0.1 and later, put support files in the <Application_Home>/Library/Application Support directory and apply thecom.apple.MobileBackup extended attribute to them. This attribute prevents the files from being backed up to iTunes or iCloud. If you have a large number of support files, you may store them in a custom subdirectory and apply the extended attribute to just the directory.

  • Put data cache files in the <Application_Home>/Library/Caches directory. Examples of files you should put in this directory include (but are not limited to) database cache files and downloadable content, such as that used by magazine, newspaper, and map apps. Your app should be able to gracefully handle situations where cached data is deleted by the system to free up disk space.

  • Put temporary data in the <Application_Home>/tmp directory. Temporary data comprises any data that you do not need to persist for an extended period of time. Remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device.

也就是說,一般從網上下載的那些內容,包括雜志、報紙、視頻什么的,都要放在 <Application_Home> /Library/Caches  目錄下面

<Application_Home>/Library/

This directory is the top-level directory for files that are not user data files. You typically put files in one of several standard subdirectories but you can also create custom subdirectories for files you want backed up but not exposed to the user. You should not use this directory for user data files.

The contents of this directory (with the exception of the Caches subdirectory) are backed up by iTunes.

For additional information about the Library directory, see “The Library Directory Stores App-Specific Files.”

Library目錄下面的內容,也會被被iTunes備份,但是Caches目錄除外,也就是說這些網絡下載內容文件放在這里是不會被備份的,

 

Caches

Use this directory to write any app-specific support files that your app can re-create easily. Your app is generally responsible for managing the contents of this directory and for adding and deleting files as needed.

In iOS 2.2 and later, the contents of this directory are not backed up by iTunes. In addition, iTunes removes files in this directory during a full restoration of the device.

On iOS 5.0 and later, the system may delete the Caches directory on rare occasions when the system is very low on disk space. This will never occur while an app is running. However, you should be aware that iTunes restore is not necessarily the only condition under which the Caches directory can be erased.

上面寫的的比較清楚,Library/Caches目錄下,一般情況下是不會被刪除的,我理解,也包括stackoverflow網友的證明,應用升級的時候也不會被刪除,實際上,應用升級的具體系統操作是這樣的:

 

Files Saved During Application Updates When a user downloads an application update, iTunes installs the update in a new application directory. It then moves the user’s data files from the old installation over to the new application directory before deleting the old installation. Files in the following directories are guaranteed to be preserved during the update process:

  • Application_Home/Documents
  • Application_Home/Library

Although files in other user directories may also be moved over, you should not rely on them being present after an update.

系統先新建一個應用目錄,然后安裝一個新版本應用,然后再把舊版本的應用數據拷貝過來,然后再刪除舊版本的應用安裝目錄。

最后注意一下,Library/Caches目錄下的數據雖然在一般情況下不會被刪除,但是在系統恢復和其他一些罕見的情況下(比如非常底的磁盤空間條件下有可能)會被清除,所以你的程序每次都要檢查一些,這些文件都還在不在了,不在的話只能重新下了。

Application_Home/Library/Caches Use this directory to write any application-specific support files that you want to persist between launches of the application or during application updates. Your application is generally responsible for adding and removing these files. It should also be able to re-create these files as needed because iTunes removes them during a full restoration of the device. In iOS 2.2 and later, the contents of this directory are not backed up by iTunes.

 

參考連接:http://stackoverflow.com/questions/7155964/will-application-home-library-caches-be-clear-on-app-update/7277797#7277797

File System Programming Guide

https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1

 

轉:https://blog.csdn.net/messyhari/article/details/50481356

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM