我有一个带有 TableView 的 UIViewController,用于显示“ list ”项目。这个 ViewController 还有一个按钮,可以触发 segue 以模态方式呈现另一个 UIViewController,供用户添加新的 list 项目。
所有 list 项目都存储在 CoreData 中。
新的 CoreData 实体被创建,并由 SecondViewController 存储。在点击触发关闭 SecondViewController 的按钮之前,用户可以添加任意数量的 checklist 项目。由于此 SecondViewController 是模态呈现的,因此我假设它的事件与 FirstUIViewController 根本没有任何关系。
在包含UITableView的FirstViewController中,有一个NSFetchedResultsController再次在CoreData执行获取请求并提供所有数据到 UITableView。 NSFetchedResultsController 的委托(delegate)也指向这个 FirstUIViewController。
问题是,在 SecondViewController 关闭后,UITableView 似乎注意到新的 list 实体的插入,并插入了新的 UITableCell 在 UITableView 中。然而,奇怪的是,这个新插入的行没有显示正确的 cell.textlabel。仅显示标签上没有任何内容的空白 UITableViewCell。
下面是我如何配置 UITableViewCell。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ChecklistCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
ChecklistItem *item = [self.fetch_controller objectAtIndexPath:indexPath];
cell.textLabel.text = item.name;
}
这是我对 NSFetchedResultsControllerDelegate 的看法
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"*** controllerDidChangeObject - NSFetchedResultsChangeInsert");
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
强制 [self.tableView reloadData] 似乎有帮助。我知道这一点是因为我添加了一个按钮来调用此方法,并且相应地刷新和更新了单元格的标签。
因此,我尝试了这个,因为我希望它会在 SecondViewController 关闭后被调用。然而,该方法被调用是因为 Reload Data! 被记录了,但不知何故 tableView 仍然没有正确显示新添加的单元格的标签。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self performFetch];
[self.tableView reloadData];
NSLog(@"Reload Data!");
}
我想知道这里可能出了什么问题。 self.tableView 在 SecondViewController 关闭后不会以某种方式重新加载。有什么建议吗?
好吧,更奇怪的是我在 - (void)viewDidAppear:(BOOL)animated 中尝试了 [self.tableView reloadData]。新的 tableViewCell 仍然没有正确显示它的标签;然而,等了 30 秒后,标签就神奇地弹出了!这是否意味着我的 iPhone/iPhone 模拟器需要时间思考很多?
最佳答案
解释
您的核心数据保存需要时间。如果您正在保存数据,然后立即关闭模态视图 Controller ,则您在 performFetch 函数上遇到了竞争条件。这就是为什么您会看到它在 viewWillAppear 函数中不起作用,但在您按下按钮时起作用。它有时会在 viewDidAppear 中工作,但不能保证。这取决于您是否使用模拟器,以及系统的繁忙程度。
具体建议
由于您是从核心数据中提取数据,因此我建议您使用 NSFetchedResultsController 并实现 NSFetchedResultsControllerDelegate。这些是专门为将 coreData 绑定(bind)到 UITableViewController 而设计的。它监听更改并根据这些更改立即添加、删除或更新行。
更新代码
要正确实现 NSFetchedResultsControllerDelegate,您只需从该网站复制代码:http://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html
一些提示:
cellForRowAtIndexPath 的实现方式稍作更改。创建一个名为 configureCell 的新方法。这是一个陈旧的模式,因此您可以在 Apple 和其他地方的许多示例代码中找到它。 从上面网站的“典型用途”部分复制代码。您不需要实现“用户驱动的更新”。一定要设置
self.fetchedResultsController.delegate = self;
如果您想检查此代码是否正常工作,您可以将断点或 NSLog 放入 controllerWillChangeContent 或 controller:didChangeObject 中。
配置单元格
下面的 configureCell:atIndexPath 方法由 NSFetchedResultsController 委托(delegate)调用。
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Product *product = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = product.name;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Product Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
请在此处查看委托(delegate)实现代码。查看更新对象时如何调用 configureCell。
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
关于ios - 关闭模态呈现的 ViewController 后,UITableViewCell 不反射(reflect)更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14942300/
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。
下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm