- 浏览: 223596 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
15197442045:
求demo,谢谢
IOS 后台执行代码(voip socket) -
15197442045:
我用了你这种方式,还是不能后台运行~~~~~
IOS 后台执行代码(voip socket) -
wlpych:
这个m_socket,从哪获得啊,什么方法?用的pjsip。求 ...
IOS 后台执行代码(voip socket)
1: 主线程修改了数据库的某一条记录,但是子线程没有发生变化,反过来一样的问题。这种情况一般是发生在app有多个NSManagedObjectContext,两个线程分别对其进行了读写操作。
2: 有时候程序会莫名其妙的crash掉,这个有很多原因:
a: 有时候是因为两个线程同时读写数据库中的同一条记录。
b: 有时候根本找不到是哪里的原因。
这两种情况一般是发生在app只有一个NSManagedObjectContext,两个线程都对其进行了读写操作。
在实际的开发当中,我遇到了各种各样的问题,如果是多线程操作数据库的话,个人建议:
1: 最好一个线程对应一个NSManagedObjectContext。如果只有一个NSManagedObjectContext,并且多个线程对其进行操作,回出现许多不清不楚的问题。
2:在每一个线程对应一个NSManagedObjectContext的时候,尽量一个线程只读写与其对应的context。在其完成操作的时候通知另外的线程去修改其对应的context。在apple的api中有NSManagedObjectContextDidSaveNotification, 它可以帮助你通知修改其它的contexts。
eg: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:childThreadManagedObjectContext];
- (NSManagedObjectContext*)childThreadContext
{
if (childThreadManagedObjectContext != nil)
{
return childThreadManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
childThreadManagedObjectContext = [[NSManagedObjectContext alloc] init];
[childThreadManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
else
{
DLog(@"create child thread managed object context failed!");
}
[childThreadManagedObjectContext setStalenessInterval:0.0];
[childThreadManagedObjectContext setMergePolicy:NSOverwriteMergePolicy];
//////init entity description.
pChildThreadEntityDec = [NSEntityDescription entityForName:@"student" inManagedObjectContext:childThreadManagedObjectContext];
if (pChildThreadEntityDec == nil)
{
DLog(@"error init entity description!");
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:childThreadManagedObjectContext];
return childThreadManagedObjectContext;
}
- (void)mergeOnMainThread:(NSNotification *)aNotification
{
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:aNotification];
}
- (void)mergeContextChangesForNotification:(NSNotification *)aNotification
{
[self performSelectorOnMainThread:@selector(mergeOnMainThread:) withObject:aNotification waitUntilDone:YES];
}
上面的代码只是简单利用NSManagedObjectContextDidSaveNotification,当子线程修改了数据库以后,通知主线程去修改其对应的context。当然childThreadManagedObjectContext的创建是在创建子线程的时候进行的。
- (void)startChildThread
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
if ([[manageDatabase sharedInstance] childThreadContext] == nil)
{
DLog(@"create child thread context failed.");
}
[NSTimer scheduledTimerWithTimeInterval:10000.0 target:self selector:@selector(printCurrentData) userInfo:nil repeats: YES];
[runLoop run];
[pool release];
}
注:实际上在什么时候创建都可以,只要保证在第一次用的之前创建好就可以了。上面是childThreadManagedObjectContext发生改变时,通知主context修改,所以在修改数据库时,一般都是修改childThreadManagedObjectContext。
eg:
- (void)saveDatabase:(student*)inObject withAge:(NSNumber *)inAge
{
if (inObject==nil || inAge==nil)
{
return;
}
NSError* pError;
if (self.age != nil)
{
[self.age release];
self.age = nil;
}
self.age = [[NSNumber alloc] initWithInt:[inAge intValue]];
if ([NSThread currentThread] == [NSThread mainThread])
{
[self performSelector:@selector(saveWithChildThread:) onThread:[dataBaseAppDelegate shareDelegate].viewController.pShowController.pChildThread withObject:inObject waitUntilDone:NO];
}
else
{
inObject.stuAge = inAge;
if (![childThreadManagedObjectContext save:&pError])
{
NSLog(@"save failed: %@, %@", pError, [pError userInfo]);
}
}
}
- (void)saveWithChildThread:(student*)inStudent
{
NSError* pError;
NSManagedObjectID* tempObjectID = [inStudent objectID];
student* tempStudet = (student*)[childThreadManagedObjectContext objectWithID:tempObjectID];
tempStudet.stuAge = age;
if (![childThreadManagedObjectContext save:&pError])
{
NSLog(@"save failed: %@, %@", pError, [pError userInfo]);
}
}
这里修改数据库都是通过saveWithChildThread去修改的。当然上面 if ([NSThread currentThread] == [NSThread mainThread]),如果时在主线程也可以直接调用saveWithChildThread,而不用放到子线程修改,这里只是为了统一。每个context只在其对应的线程中修改。
2: 有时候程序会莫名其妙的crash掉,这个有很多原因:
a: 有时候是因为两个线程同时读写数据库中的同一条记录。
b: 有时候根本找不到是哪里的原因。
这两种情况一般是发生在app只有一个NSManagedObjectContext,两个线程都对其进行了读写操作。
在实际的开发当中,我遇到了各种各样的问题,如果是多线程操作数据库的话,个人建议:
1: 最好一个线程对应一个NSManagedObjectContext。如果只有一个NSManagedObjectContext,并且多个线程对其进行操作,回出现许多不清不楚的问题。
2:在每一个线程对应一个NSManagedObjectContext的时候,尽量一个线程只读写与其对应的context。在其完成操作的时候通知另外的线程去修改其对应的context。在apple的api中有NSManagedObjectContextDidSaveNotification, 它可以帮助你通知修改其它的contexts。
eg: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:childThreadManagedObjectContext];
- (NSManagedObjectContext*)childThreadContext
{
if (childThreadManagedObjectContext != nil)
{
return childThreadManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
childThreadManagedObjectContext = [[NSManagedObjectContext alloc] init];
[childThreadManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
else
{
DLog(@"create child thread managed object context failed!");
}
[childThreadManagedObjectContext setStalenessInterval:0.0];
[childThreadManagedObjectContext setMergePolicy:NSOverwriteMergePolicy];
//////init entity description.
pChildThreadEntityDec = [NSEntityDescription entityForName:@"student" inManagedObjectContext:childThreadManagedObjectContext];
if (pChildThreadEntityDec == nil)
{
DLog(@"error init entity description!");
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextDidSaveNotification object:childThreadManagedObjectContext];
return childThreadManagedObjectContext;
}
- (void)mergeOnMainThread:(NSNotification *)aNotification
{
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:aNotification];
}
- (void)mergeContextChangesForNotification:(NSNotification *)aNotification
{
[self performSelectorOnMainThread:@selector(mergeOnMainThread:) withObject:aNotification waitUntilDone:YES];
}
上面的代码只是简单利用NSManagedObjectContextDidSaveNotification,当子线程修改了数据库以后,通知主线程去修改其对应的context。当然childThreadManagedObjectContext的创建是在创建子线程的时候进行的。
- (void)startChildThread
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
if ([[manageDatabase sharedInstance] childThreadContext] == nil)
{
DLog(@"create child thread context failed.");
}
[NSTimer scheduledTimerWithTimeInterval:10000.0 target:self selector:@selector(printCurrentData) userInfo:nil repeats: YES];
[runLoop run];
[pool release];
}
注:实际上在什么时候创建都可以,只要保证在第一次用的之前创建好就可以了。上面是childThreadManagedObjectContext发生改变时,通知主context修改,所以在修改数据库时,一般都是修改childThreadManagedObjectContext。
eg:
- (void)saveDatabase:(student*)inObject withAge:(NSNumber *)inAge
{
if (inObject==nil || inAge==nil)
{
return;
}
NSError* pError;
if (self.age != nil)
{
[self.age release];
self.age = nil;
}
self.age = [[NSNumber alloc] initWithInt:[inAge intValue]];
if ([NSThread currentThread] == [NSThread mainThread])
{
[self performSelector:@selector(saveWithChildThread:) onThread:[dataBaseAppDelegate shareDelegate].viewController.pShowController.pChildThread withObject:inObject waitUntilDone:NO];
}
else
{
inObject.stuAge = inAge;
if (![childThreadManagedObjectContext save:&pError])
{
NSLog(@"save failed: %@, %@", pError, [pError userInfo]);
}
}
}
- (void)saveWithChildThread:(student*)inStudent
{
NSError* pError;
NSManagedObjectID* tempObjectID = [inStudent objectID];
student* tempStudet = (student*)[childThreadManagedObjectContext objectWithID:tempObjectID];
tempStudet.stuAge = age;
if (![childThreadManagedObjectContext save:&pError])
{
NSLog(@"save failed: %@, %@", pError, [pError userInfo]);
}
}
这里修改数据库都是通过saveWithChildThread去修改的。当然上面 if ([NSThread currentThread] == [NSThread mainThread]),如果时在主线程也可以直接调用saveWithChildThread,而不用放到子线程修改,这里只是为了统一。每个context只在其对应的线程中修改。
发表评论
-
UIWebView清空缓存
2016-07-25 10:03 511- (void)clearAllUIWebViewData { ... -
iOS显示FPS值的工具FHHFPSIndicator
2016-07-04 13:56 0转载:http://www.cocoachina.com/io ... -
响应者链及相关机制总结
2016-06-30 14:25 510转载:http://www.cocoachina.com/i ... -
KVO&KVC的再次认知
2015-02-02 16:01 706KVO模型中,有两种通知观察者的方式,自动通知和手动通知。顾名 ... -
代码重构的理解(持续更新)
2015-01-13 17:27 585代码重构的理解和思考。 1:何时进行重构?当重复出现的时候,你 ... -
深入浅出Cocoa之Framework(转)
2015-01-06 17:49 0Framework 简介 转自 http://www.coc ... -
iOS静态库和动态库
2014-12-24 17:55 806一、什么是库? 库是共 ... -
svg图片在ios上的使用
2014-12-23 15:22 7381:从UI设计师那里得到的是每个svg图通过网站icomoon ... -
svg图片在ios上的使用
2014-12-23 15:22 32531:从UI设计师那里得到的是每个svg图通过网站icomoon ... -
Xcode设置项之Architectures和Valid Architectures
2014-12-22 10:42 624本文所讲的内容都是围绕iPhone的CPU指令集,现在先说说不 ... -
Xcode中Build Settings更改编译后能发现的问题
2014-12-17 13:36 7431:for循环不加括号 2:枚举赋值时类型不匹配 3:for循 ... -
静态库编译心得
2014-12-16 11:16 522我们编译静态库时一般会生成模拟器,真机两个包的.a文件 这二个 ... -
xcode编译选项整理
2014-12-11 19:15 0LINK_WITH_STANDARD_LIBRARIES = ... -
根据dsym解析crash_log
2014-12-01 14:15 9341:拷贝symbolicatecrash到/bin目录下 su ... -
autolayout心得
2014-10-28 13:30 687一:实现方案在以前就已经确定了下面几个点: 1 使 ... -
Objective-C的消息传递机制[转]
2014-07-31 20:34 677一直想写一篇类似的。 直接转载了 http://www.cnb ... -
iOS开发模拟限速
2012-12-07 17:47 53921. 模拟器网速调整: 限制时输入下面两行,根据需要修改下面的 ... -
iphone中结束电话后返回自己的应用(转载)
2012-04-10 10:30 1200iphone中结束电话后返回自己的应用 大家想不想在 ... -
Info.plist中常用的key简介(转载)
2012-03-15 15:55 942UIRequiresPersistentWiFi 在程序中弹出 ... -
UIScrollView 原理(转载)
2012-03-10 19:46 1166scroll view 原理 在滚动过程当中,其实是在修 ...
相关推荐
在提供的"ThreadedCoreData"源代码中,你可能会找到关于这些概念的实际实现,包括如何初始化和使用后台上下文,如何在多线程中执行CoreData操作,以及如何在操作完成后安全地更新UI。通过研究这些代码,你可以更深入...
在"CoreData数据库操作和版本管理"这个主题中,我们将深入探讨如何利用CoreData进行数据操作以及如何有效地管理数据库的版本。 1. **CoreData基本概念** - **实体(Entity)**:类似于关系数据库中的表,代表一种...
本教程将深入探讨如何在多线程环境下进行Core Data的操作,包括创建(Create)、读取(Read)、更新(Update)和删除(Delete)数据。 1. **Core Data多线程基础** - **Main Queue Context**:主线程上下文,通常...
2. NSPersistentContainer:这是CoreData的新特性,它包含了一个主队列上下文(Main Queue Context)和一个后台队列上下文(Background Queue Context),用于多线程环境下数据的读写。 3. NSManagedObjectContext...
`PCCoredataDemo`的核心特性就是对CoreData的多线程支持,这使得开发者可以在后台线程中执行耗时的数据库操作,而不会阻塞主线程,从而保持UI的流畅性。通常,多线程操作CoreData需要考虑上下文(ManagedObject...
- 当处理大量数据时,为避免阻塞主线程,可以在后台线程执行CoreData操作。 - 保存操作可能会引发错误,确保处理好这些异常情况。 - 优化查询性能,避免过于复杂的NSPredicate和过多的排序。 总之,CoreData为...
5. **Relationships**:利用CoreData的实体关系,可以轻松地处理一对多、一对一或多对多的关系。 6. **Faulting and Uniquing**:CoreData的懒加载机制和唯一性保证,有助于减少内存消耗。 总的来说,CoreData为...
- 检测并解决并发问题:在多线程环境中使用CoreData需要注意的问题。 - CoreDate与SQLite的关系:虽然CoreData不直接使用SQL,但默认情况下它使用SQLite作为其后台存储。 - 错误处理和调试技巧:如何在开发过程中...
然而,随着应用规模的扩大,单线程的CoreData操作可能会成为性能瓶颈。为了解决这个问题,我们可以利用多线程技术来优化数据管理,这就是"QGLCoreDataPlugin"项目所关注的核心内容。 QGLCoreDataPlugin是一个...
CoreData是苹果公司提供的一种强大...在实际项目中,你可能需要处理更复杂的情况,如多线程下的数据管理、批量操作、关系数据的处理等。了解并熟练掌握CoreData的这些基本操作,对于开发Apple平台的应用程序至关重要。
因为CoreData不是线程安全的,所以在多线程环境中使用时,需要特别注意。Demo可能展示了如何在后台线程进行数据操作,并在主线程上更新UI。 10. **错误处理**: 在进行数据操作时,应始终检查并处理可能出现的...
1. **后台操作与多线程**:在iOS应用中,主线程主要负责UI更新,而数据操作通常会消耗较多时间,因此为了保证用户体验,数据的读写工作应该在后台线程进行。CoreData支持在后台上下文中执行操作,这样可以避免阻塞...
在iOS应用开发中,CoreData是一个强大的对象关系映射(ORM)框架,用于管理应用程序...通过合理利用实体属性验证和自定义验证方法,可以构建健壮的数据模型,同时在多线程环境下正确处理数据操作,保证应用的稳定运行。
可以使用后台线程进行复杂的数据操作,并通过通知或代理方法更新UI。 8. **故障点与恢复**: CoreData的故障点和恢复机制允许在不丢失用户数据的情况下处理错误。通过捕获并处理NSPersistentStoreSaveError,可以...
-此外,封装还可以帮助处理并发和错误处理,确保在多线程环境中正确地操作数据。 4. 注释的重要性: -对于初学者来说,良好的注释可以帮助理解代码的意图和工作原理,从而更快地掌握CoreData的使用。 -在封装...
本教程将深入讲解如何使用Swift来简单实现CoreData的数据库操作,包括增、删、改、查以及处理关系表。 ### 一、CoreData基本概念 1. **实体(Entity)**:类似于数据库中的表,是数据模型的基本单位。 2. **属性...
- **CoreData框架**:处理数据库操作时的线程安全问题。 - **CoreFoundation(核心框架)**:提供了底层的线程安全支持。 综上所述,多线程编程是软件开发中一个复杂而重要的主题,它涉及到多方面的技术和设计考虑...
- **PromiseKit+CoreData**:结合PromiseKit,将异步编程带入CoreData,简化了多线程操作。 4. **引入第三方库**: 在Xcode项目中,通常通过CocoaPods或Carthage来管理第三方库。首先,需要在Podfile或Cartfile中...
CoreData中的实体(Entity)类似于数据库中的表,每个实体可以包含多个属性(Attribute),这些属性对应表中的列。实体间可以通过关系(Relationship)进行连接,如同数据库中的外键。关系可以是一对一、一对多或多...