是否有可能拥有一个自我更新的 iPhone 应用程序?
我相信答案是否定的,但我不确定。
我有一个数据库驱动的应用程序,它实际上是一个产品目录。我希望数据库位于用户 iPhone 上,以便快速使用目录。但是,数据库中的内容会定期更改。
我可以创建一个推送通知来告诉用户已经准备好数据库更新,但如果应用程序自行更新会更好。
只要您不需要更改应用程序包中的任何内容,这是可能的。只需将您的内容保存到文档目录即可。
当然,您可以更新自己的数据库。
正如fluchtpunkt 回答的那样,iOS 应用程序可以下载新数据,但不能下载新代码。许多 iOS 应用程序(例如众多 Twitter 客户端)主要下载和显示数据。
如果应用程序的界面没有明确说明应用程序正在下载数据,应用程序就会遇到麻烦。应用程序不应该在用户不知情的情况下用完 iPhone 的数据计划分配。让用户知道的范围可以从明确的通知(包括取消下载的选项)到使应用程序的概念完全与下载数据(例如 Twitter 客户端)有关。
如果应用程序与服务器共享任何信息,还必须通知用户。应用程序可能希望发送此类数据以选择性地下载特定数据。例如,该应用程序可以使用位置信息来定制数据库,仅下载设备所在地区可用的项目。如果数据是特定于帐户的,则登录过程可能就足够了。
无法在 iPhone 上加载可执行文件,但值得注意的是您可以动态加载资源包。如果您使用 IB 创建视图,那么您可以创建一个全新的视图,将其放在云上并从应用程序加载它。唯一需要注意的是,您只能更新设计,但不能扩展功能。
要动态加载 XIB,请使用以下initWithNibName
方法,
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
并传入动态加载的包。
在 Mac 上,可以有包含可以动态加载的可执行代码的捆绑包,但在 iPhone 上却不行。有一个NSPrincipalClass
为 Mac 命名的 Plist 配置,但不幸的是还没有为 iPhone 命名。
你可以通过推送通知来做到这一点,除了你可以设置定时器,它会在每次指定的时间下载新数据,但问题是应用程序必须一直打开。在 ios 4 中有本地通知,甚至可以向用户发送通知当应用程序关闭时
我的应用程序使用 SQLite 数据库并对其进行更新。每次启动(或从挂起模式唤醒)时,它都会连接到我的 Web 服务器并检查新数据库。对数据库进行认证,首先只下载一个包含在线数据库MD5和的文件,然后计算手机上数据库的MD5和。仅当总和不同时,才会下载新数据库。这有一个很好的副作用,它可以保持低流量。
计算 MD5 和的示例代码:
#define CHUNK_SIZE 16384
#import <CommonCrypto/CommonDigest.h>
+ (NSString *)md5SumForFileAtPath:(NSString *)path {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
CC_MD5_CTX md5;
CC_MD5_Init(&md5);
BOOL done = NO;
while(!done)
{
NSData* fileData = [handle readDataOfLength:CHUNK_SIZE];
CC_MD5_Update(&md5, [fileData bytes], [fileData length]);
if ([fileData length] == 0) done = YES;
}
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(result, &md5);
NSString *digest = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
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]
];
XLog("Checksum for file %@: %@", path, digest);
return digest;
}
但是,如果数据库不是很大,下载整个数据库只是一个很好的解决方案。此外,我对数据库进行了 gzip 压缩,并在下载后将其解压缩。
#import <zlib.h>
+ (void)gunzipFileAtPath:(NSString *)zippedPath toPath:(NSString *)unzippedPath {
gzFile file = gzopen([zippedPath UTF8String], "rb");
FILE *dest = fopen([unzippedPath UTF8String], "w");
unsigned char buffer[CHUNK_SIZE];
int uncompressedLength;
while (uncompressedLength = gzread(file, buffer, CHUNK_SIZE) ) {
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(@"error writing data");
}
}
fclose(dest);
gzclose(file);
}
只在状态栏中显示网络活动指示器而不使用进度条或其他指示器是完全可以的。如果手机的数据库是最新的,我什至不会通知用户,因为这是不必要的信息,只会分散他的注意力。但是,如果有更新,我会淡入状态栏的覆盖并显示几秒钟的信息。从我的用户的反馈中,我可以看出他们非常欣赏这个解决方案。
不要忘记通过计算 MD5 和来添加密码学。您必须在上传下一次更新时向 Apple 表明这一点。我只需要再回答一个问题,并说我仅将加密用于身份验证。该应用程序被批准没有任何问题。