IOS的第一个项目,要弄一个离线版,要读存数据库,当然选择了CoreDate
随之出现了一点问题,
1.在大量使用GCD和block以后发现程序会卡死在executefetchrequest执行
网上搜了一搜,发现问题了,原来在线程中NSManagedObjectContext会创建一些私有方法。跨线程使用时候就会出问题。
解决办法就是多个线程执行时候创建多个NSManagedObjectContext管理。关联到NSPersistentStoreCoordinator
(这个地方,反复想了想,可能是我的用法用错了,NSManagedObjectContext的创建仅仅在多线程里使用,别的用默认的即可)
2.那好,既然发现了问题那就解决呗,多个线程执行时候创建多个NSManagedObjectContext管理,而我们的项目,没有上下拉刷新,而是采取在进入页面的时候从服务器同步数据,然后放入本地数据库,取出数据,页面reload,这样每点击一个页面就有一个多线程,那就是N个NSManagedObjectContext,那内存是蹭蹭的上涨,在ipod上闪退现象严重
无奈啊,这两天突然间想到了一个办法,那就是模拟JDBC连接池,只是一个初步的思想,把想法说一下
在程序打开的时候,就创建一个NSMutableArray,然后初始化N个NSManagedObjectContext,并且放入NSMutableArray,然后在查询,保存时候,查询NSMutableArray有没有可用的NSManagedObjectContext,如果有则取出,如果没有则等待,在如果有的情况下,开始操作,在操作完毕,大概是在excuteFecthRequest时候和save之后 将NSManagedObjectContext再次放入NSMutableArray,首先要保证NSMutableArray线程安全,加上单例设计模式?这些仅仅是想法,还未实现
3.大致上实现了一个连接池
#import <Foundation/Foundation.h> @interface ContextPool : NSObject @property (nonatomic,strong) NSMutableArray *contextArray; @property (nonatomic,assign) int maxCon; + (instancetype)shareInstance; - (void)initPool:(int)count; - (NSManagedObjectContext *)getContext; - (void)free:(NSManagedObjectContext *)context; - (NSManagedObjectContext *)createContext; @end
#import "ContextPool.h" //最大连接数 static int inUsing = 0; static ContextPool *instance = nil; @implementation ContextPool + (instancetype)shareInstance { if (instance == nil) { @synchronized (self) { if (instance == nil) { instance = [[self alloc] init]; } } } return instance; } /** * 初始化连接池 * */ - (void)initPool:(int)count{ self.maxCon = count; self.contextArray = [[NSMutableArray alloc]init]; for (int i=0; i<self.maxCon; i++) { [self.contextArray addObject:[self createContext]]; } } /** * 创建context */ - (NSManagedObjectContext *)createContext { NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType]; newContext.persistentStoreCoordinator = [[CoreDataManager instance]persistentStoreCoordinator]; return newContext; } /** * 从池子里获取context */ - (NSManagedObjectContext *)getContext { NSManagedObjectContext *context = nil; if (context == nil) { @synchronized (self) { if(context == nil) if (self.contextArray.count > 0) { context = [self.contextArray objectAtIndex:0]; [self.contextArray removeObjectAtIndex:0]; NSLog(@"被取走了一个context,还剩%i",[self.contextArray count]); if (context == nil) { //如果context为nil 则表示context失效了 重新充初始化一个放入 [self.contextArray addObject:[self createContext]]; context = [self getContext]; } else { inUsing++; NSLog(@"连接池的context已经被使用了:%i个",inUsing); } } else { // NSLog(@"连接池的资源已经用完了,创建一个新的context"); } if(self.maxCon==0||self.maxCon<inUsing) { context=nil;//达到最大连接数,暂时不能获得连接了。 } } } return context; } /** * 自动增加一个context */ - (void)incrementContext { [self.contextArray addObject:[self createContext]]; } /** * 释放context 并不是真正的释放,而是将context再次放入 */ - (void)free:(NSManagedObjectContext *)context { NSLog(@"%@",context); if ([self.contextArray containsObject:context]) { return; } NSLog(@"收回之前的使用的个数%i",inUsing); [self.contextArray addObject:context]; inUsing--; NSLog(@"收回之后的使用的个数%i",inUsing); NSLog(@"哈哈,收回了一个资源,现在可以使用的连接数为:%i",[self.contextArray count]); } //释放全部 - (void)freeAll{ } @end