将 sqlite 数据库与 iCloud 同步
Posted
技术标签:
【中文标题】将 sqlite 数据库与 iCloud 同步【英文标题】:Syncing sqlite database with iCloud 【发布时间】:2012-03-31 05:42:35 【问题描述】:我有我的 sqlite 数据库。现在我想与 icloud 同步。我读过博客说不支持与 icloud 同步的 sqlite。要么选择核心数据,要么“做核心数据所做的事情”。
现在我不可能去获取核心数据。所以就像第二个选项“做一些类似于 CoreData 如何同步 sqlite DBs 的事情:将“事务日志”发送到 iCloud 并从中构建每个本地 sqlite 文件。”
请任何人都可以分享sqlite的“事务日志”的任何示例代码,或者可以逐步详细说明我需要做什么?
【问题讨论】:
你能告诉我我们每次都必须创建 XML 吗?或仅使用该 XML 中的更改进行更新?如果只是改变那么请让我知道如何?或者如果创建 XML 那么我认为这将是耗时的操作.. 请建议.. 如果您足够灵活,可以对现有 XML 进行更改,那就太好了。当然,您可以修改现有的。 :) 无需每次都创建 你能告诉我如何对现有的进行更改吗? 我没有对现有的进行任何更改。但我想你需要解决这个问题。就我而言,我每次都在创建 XML,因为需要进行批量更改。如果您有键对值类型数据,那么您也可以使用 plist 文件。 @βhargavḯ 我在您的一个问题中读到您想在您的一个应用程序中使用信用卡。我也需要你的帮助。你完成那个任务了吗?是的,那么……苹果批准了吗? 【参考方案1】:1) 我按照这个链接创建了 xml。你可以从它的github下载相应的api。链接是-http://arashpayan.com/blog/2009/01/14/apxml-nsxmldocument-substitute-for-iphoneipod-touch/
2) 按钮点击:
-(IBAction) btniCloudPressed:(id)sender
// create the document with it’s root element
APDocument *doc = [[APDocument alloc] initWithRootElement:[APElement elementWithName:@"Properties"]];
APElement *rootElement = [doc rootElement]; // retrieves same element we created the line above
NSMutableArray *addrList = [[NSMutableArray alloc] init];
NSString *select_query;
const char *select_stmt;
sqlite3_stmt *compiled_stmt;
if (sqlite3_open([[app getDBPath] UTF8String], &dbconn) == SQLITE_OK)
select_query = [NSString stringWithFormat:@"SELECT * FROM Properties"];
select_stmt = [select_query UTF8String];
if(sqlite3_prepare_v2(dbconn, select_stmt, -1, &compiled_stmt, NULL) == SQLITE_OK)
while(sqlite3_step(compiled_stmt) == SQLITE_ROW)
NSString *addr = [NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,0)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,1)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,2)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,3)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,4)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,5)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,6)]];
addr = [NSString stringWithFormat:@"%@#%@",addr,[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,7)]];
//NSLog(@"%@",addr);
[addrList addObject:addr];
sqlite3_finalize(compiled_stmt);
else
NSLog(@"Error while creating detail view statement. '%s'", sqlite3_errmsg(dbconn));
for(int i =0 ; i < [addrList count]; i++)
NSArray *addr = [[NSArray alloc] initWithArray:[[addrList objectAtIndex:i] componentsSeparatedByString:@"#"]];
APElement *property = [APElement elementWithName:@"Property"];
[property addAttributeNamed:@"id" withValue:[addr objectAtIndex:0]];
[property addAttributeNamed:@"street" withValue:[addr objectAtIndex:1]];
[property addAttributeNamed:@"city" withValue:[addr objectAtIndex:2]];
[property addAttributeNamed:@"state" withValue:[addr objectAtIndex:3]];
[property addAttributeNamed:@"zip" withValue:[addr objectAtIndex:4]];
[property addAttributeNamed:@"status" withValue:[addr objectAtIndex:5]];
[property addAttributeNamed:@"lastupdated" withValue:[addr objectAtIndex:6]];
[property addAttributeNamed:@"deleted" withValue:[addr objectAtIndex:7]];
[rootElement addChild:property];
[property release];
APElement *fullscore = [APElement elementWithName:@"FullScoreReport"];
[property addChild:fullscore];
[fullscore release];
select_query = [NSString stringWithFormat:@"SELECT AnsNo,Answer,AnswerScore,MaxScore,AnsIndex FROM FullScoreReport WHERE Addr_ID = %@",[addr objectAtIndex:0]];
select_stmt = [select_query UTF8String];
if(sqlite3_prepare_v2(dbconn, select_stmt, -1, &compiled_stmt, NULL) == SQLITE_OK)
while(sqlite3_step(compiled_stmt) == SQLITE_ROW)
APElement *answer = [APElement elementWithName:@"Answer"];
[answer addAttributeNamed:@"AnsNo" withValue:[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,0)]]];
[answer addAttributeNamed:@"Answer" withValue:[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,1)]]];
[answer addAttributeNamed:@"AnswerScore" withValue:[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,2)]]];
[answer addAttributeNamed:@"MaxScore" withValue:[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,3)]]];
[answer addAttributeNamed:@"AnsIndex" withValue:[NSString stringWithFormat:@"%@",[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiled_stmt,4)]]];
[fullscore addChild:answer];
[answer release];
sqlite3_finalize(compiled_stmt);
sqlite3_close(dbconn);
NSString *prettyXML = [doc prettyXML];
NSLog(@"\n\n%@",prettyXML);
//***** PARSE XML FILE *****
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Properties.xml" ];
NSData *file = [NSData dataWithBytes:[prettyXML UTF8String] length:strlen([prettyXML UTF8String])];
[file writeToFile:path atomically:YES];
NSString *fileName = [NSString stringWithFormat:@"Properties.xml"];
NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:fileName];
MyDocument *mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
mydoc.xmlContent = prettyXML;
[mydoc saveToURL:[mydoc fileURL]forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
if (success)
NSLog(@"XML: Synced with icloud");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"iCloud Syncing" message:@"Successfully synced with iCloud." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
else
NSLog(@"XML: Syncing FAILED with icloud");
];
3)MyDocument.h 文件
#import <UIKit/UIKit.h>
@interface MyDocument : UIDocument
@property (strong) NSString *xmlContent;
@end
4)MyDocument.m 文件
#import "MyDocument.h"
@implementation MyDocument
@synthesize xmlContent,zipDataContent;
// Called whenever the application reads data from the file system
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError
// NSLog(@"* ---> typename: %@",typeName);
self.xmlContent = [[NSString alloc]
initWithBytes:[contents bytes]
length:[contents length]
encoding:NSUTF8StringEncoding];
[[NSNotificationCenter defaultCenter] postNotificationName:@"noteModified" object:self];
return YES;
// Called whenever the application (auto)saves the content of a note
- (id)contentsForType:(NSString *)typeName error:(NSError **)outError
return [NSData dataWithBytes:[self.xmlContent UTF8String] length:[self.xmlContent length]];
@end
5) 现在在你的应用程序中
- (void)loadData:(NSMetadataQuery *)queryData
for (NSMetadataItem *item in [queryData results])
NSString *filename = [item valueForAttribute:NSMetadataItemDisplayNameKey];
NSNumber *filesize = [item valueForAttribute:NSMetadataItemFSSizeKey];
NSDate *updated = [item valueForAttribute:NSMetadataItemFSContentChangeDateKey];
NSLog(@"%@ (%@ bytes, updated %@) ", filename, filesize, updated);
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
MyDocument *doc = [[MyDocument alloc] initWithFileURL:url];
if([filename isEqualToString:@"Properties"])
[doc openWithCompletionHandler:^(BOOL success)
if (success)
NSLog(@"XML: Success to open from iCloud");
NSData *file = [NSData dataWithContentsOfURL:url];
//NSString *xmlFile = [[NSString alloc] initWithData:file encoding:NSASCIIStringEncoding];
//NSLog(@"%@",xmlFile);
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:file];
[parser setDelegate:self];
[parser parse];
//We hold here until the parser finishes execution
[parser release];
else
NSLog(@"XML: failed to open from iCloud");
];
6) 现在在解析器方法中获取数据并根据需要在数据库中插入/更新。
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)nameSpaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
if ([elementName isEqual:@"Property"])
NSLog(@"Property attributes : %@|%@|%@|%@|%@|%@|%@|%@", [attributeDict objectForKey:@"id"],[attributeDict objectForKey:@"street"], [attributeDict objectForKey:@"city"], [attributeDict objectForKey:@"state"],[attributeDict objectForKey:@"zip"],[attributeDict objectForKey:@"status"],[attributeDict objectForKey:@"lastupdated"],[attributeDict objectForKey:@"deleted"]);
//like this way fetch all data and insert in db
【讨论】:
感谢您的回答。我只是想问一下我可以在 iCloud 上发送图片吗。 是的,我也为图片做过(比如图片文件夹)。我在这个链接上回答了同样的问题***.com/questions/8047217/… 我集成了上面的代码,它现在运行良好,但我想问如果我在我的条目中更改了一些东西,它是如何管理的。 请您详细说明您的陈述好吗?基本上数据库中的条目是在您的最后管理的。现在您只需创建现有更改数据库的 xml 并将其发送到云端。 @Bhargavi 在这里您发送 sqlite 并再次发送文件夹,通过将其转换为 zipfile sp 为什么您不能通过获取路径将 sqlite 放入项目中的文件夹中以同样的方式发送 sqlite ?以上是关于将 sqlite 数据库与 iCloud 同步的主要内容,如果未能解决你的问题,请参考以下文章