@property (nonatomic, retain) <#type#> <#name#>;
~/Library/Developer/Xcode/UserData/CodeSnippets
这是一个起初看起来很神奇的问题,大意如下:
- 有一个Table,展示多个消息会话,这些消息会话按最新消息时间排序;
- 某种情况下,新收到一条消息,时间展示为最新,但这条消息没有排在最上方。
因为界面上展示的时间是最新的,所以刚开始遇到这个问题的第一反应是看看数据库里面的时间戳是不是正确的,查看后确认时间是最新的没错。
一时陷入了僵局,因为问题很难重现。
所以梳理了下逻辑:
因为无法重现,所以先加上了日志输出信息,观察出了发生该现象的时候,主线程都收到两次刷新通知,正常情况下没有。
主线程为什么会发生两次刷新通知呢?
- 主线程内存上发生了变动;
- 其它线程对持久化层做了写动作,通知到主线程。
所以我就在想主线程在内存上发生了什么变动,找了很久但是没找到什么东西。后来同事一语道破天机,打印出changeValues:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { NSLog(@"didChangeObject %@ from %@ to %@ with %d type, \n change value : %@\n", anObject, indexPath, newIndexPath, type, [anObject changedValues]); }
通过这样的日志信息可以发现主线程在内存中发生了什么变化。
为了验证问题是不是这样引发的,我在一个Demo上进行了模拟和验证(这个Demo是之前一篇博文使用的):
我通过在主线程修改Core Data对象的值(不一定要sortKey),但不保存:
Player *playerObject = [self.fetchedResultsController.fetchedObjects objectAtIndex:i]; playerObject.name = [NSString stringWithFormat:@"name-%d", arc4random() % 10000];
接着在其它线程修改sortKey,引发主线程进行刷新:
- (void)changeSortKeyInOtherContext:(NSManagedObjectID *)objectId { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] init]; NSPersistentStoreCoordinator *sharedPersistentStoreCoordinator = self.cdViewController.persistentStoreCoordinator; [tmpContext setPersistentStoreCoordinator:sharedPersistentStoreCoordinator]; Player *playerObject = (Player *)[tmpContext objectWithID:objectId]; int age = arc4random() % 100; playerObject.age = @(age); int salary = arc4random() % 10000000; playerObject.salary = @(salary); NSError *error = NULL; if (tmpContext && [tmpContext hasChanges] && ![tmpContext save:&error]) { NSLog(@"Error %@, %@", error, [error localizedDescription]); abort(); } [tmpContext release], tmpContext = nil; }); }
这样就可以模拟出问题场景,进而得到验证。
—— Jason Lee @ Hangzhou
1、安装NFS
sudo apt-get install nfs-kernel-server
2、在电脑上创建文件夹作为共享文件夹
sudo mkdir /home/nfs
sudo chmod 777 /home/nfs
3、修改/etc/exports的内容
sudo gedit /etc/exports
将/etc/exports的内容改为:/home/nfs *(sync,rw)
4、重启NFS。
sudo /etc/init.d/nfs-kernel-server restart
5、将电脑与开发板的IP地址设为同一网段,即前三位相同。
ifconfig eth0 192.168.0.XXX
6、重启网络。
sudo /etc/init.d/networking restart
7、在ARM板上挂载。
mount -t nfs :/home/nfs /home/root/nfs -o addr=192.168.0.XXX
上句中:/home/root/nfs为开发板中的挂载目录,addr=XXX为电脑的IP地址