【问题标题】:Strange behaviour on table view with core data具有核心数据的表视图上的奇怪行为
【发布时间】:2013-12-26 08:22:24
【问题描述】:

我正在逐步创建我的第一个 iOS 应用程序。现在我在表格视图控制器上遇到了一个我无法解决的奇怪行为,我一直在寻找几个小时的原因。这是场景:

  1. 使用核心数据的简单 iOS 应用。
  2. 表格视图控制器显示一个核心数据实体对象。
  3. 一个视图控制器 (AddViewController) 可以输入多个属性值。
  4. 一个视图控制器 (EditViewController) 用于更新对象值(在表视图控制器上选择行之后。

为了使问题足够清楚,我将只考虑三个属性,“thingName”、“urgent”和“color”,它们都是字符串属性。每行显示一个字符串 (thingName),一个图像作为颜色属性的图标,另一个图像作为紧急属性的图标。 应用程序进程从一个空白表格开始,按下添加按钮后,应用程序显示 AddViewController 视图,这是一个带有文本字段 (thingName) 的视图,用于将对象标记为紧急/不紧急的开关和一组彩色按钮为对象分配颜色相关性。在引入 thingName,选择对象为紧急或不紧急,并选择其中一个颜色按钮后,用户点击保存按钮,然后点击后退按钮返回到表格视图控制器。一切都按预期工作。将出现一个新行,其中包含作为 cell.text 的 thingName 文本、表示对象被标记为紧急的图标以及来自用户选择的颜色的彩色铅笔。 然后,如果用户想要更改 thingName 文本/紧急或不紧急/颜色,选择对象行,应用程序将显示 editViewController。如果用户更改了文本并且保存后,更新的文本也会显示在 tableview 上,这意味着应用程序已经存储了更改。如果用户将紧急状态从不紧急变为紧急,保存并返回表格视图后,紧急图标按预期出现,但从紧急变为不紧急后,保存并返回表格视图,不应该出现的紧急图标,确实出现了。为了检查这个问题,我在 editviewcontroller 上包含了一个文本字段 (urgentTextField) 以显示紧急属性的内容,并且它会根据开关状态做出很好的响应。这意味着,如果用户将开关设置为不紧急,则urgentTextField 显示“不紧急”,如果用户将开关设置为紧急,则urgentTextField 显示“紧急”。 示例案例:

thingName = @"test";
urgentTextField.text=@"Not urgent";

在这种情况下,该行显示预期的文本“测试”。但图标没有按预期响应,然后显示紧急图标.... 为方便起见,代码如下:

RootViewController(表视图控制器):

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];        

    NSString *colorValue = [[managedObject valueForKey:@"color"] description];
    NSString *isUrgent = [[managedObject valueForKey:@"urgent"]description];

   [[cell textLabel] setText:[[managedObject valueForKey:@"thingName"] description]];
  NSString *myString = [NSString stringWithFormat:@"%@",[[managedObject valueForKey:@"todoYear"] description]];

    //color pencil

    if ([hasColorValue  isEqual:@"Si color"]){
        UIButton *colorButton = [[UIButton alloc]initWithFrame:CGRectMake(308, 5, 10, 40)];
        [colorButton setImage:[UIImage imageNamed:colorValue]forState:UIControlStateNormal];
        [cell addSubview:colorButton];
    }

    //urgent
    if ([isUrgent isEqual:@"Urgent"]){
        UIButton *urgentButton = [[UIButton alloc]initWithFrame:CGRectMake(71, 27, 18, 18)];
        [urgentButton setImage:[UIImage imageNamed:@"urgent-3"]forState:UIControlStateNormal];
        [cell addSubview:urgentButton];
    }

  ../..

这是 EditViewController 的代码:

- (IBAction)SaveButtonAction:(id)sender {

    AppDelegate* appDelegate = [AppDelegate sharedAppDelegate];
    NSManagedObjectContext* context = appDelegate.managedObjectContext;

    [selectedObject setValue:ToDoTextField.text forKey:@"thingName"];
    NSString *valorUrgent = urgentTextField.text;
    [selectedObject setValue:valorUrgent forKey:@"urgent"];

    NSError *error;
    if(! [context save:&error])
    {
        NSLog(@"Whoopw,couldn't save:%@", [error localizedDescription]);
    }
}

- (void)viewDidLoad
{
    colorImagen.image = [UIImage imageNamed:nil];
    [ToDoTextField becomeFirstResponder];

    //recogiendo datos de selectedobject;
    ToDoTextField.text = [[selectedObject valueForKey:@"thingName"]description];
    colorTextField.text = [[selectedObject valueForKey:@"color"]description];
    NSString *imageName = colorTextField.text;
    colorImagen.image = [UIImage imageNamed:imageName];
    NSString *urgentValue = [[selectedObject valueForKey:@"urgent"]description];
    urgentTextField.text = urgentValue;

    if ([urgentValue isEqual:@"Urgent"]){
        [urgentSwitch setOn:YES animated:YES];
        urgentImage.image=[UIImage imageNamed:@"urgent-3"];
    }
    if ([urgentValue isEqual:@"Not urgent"]){
        [urgentSwitch setOn:NO animated:YES];
        urgentImage.image=[UIImage imageNamed:nil];
    }

    [ToDoTextField addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged];

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
}

如果您需要更多信息或代码来检测我无法找到的问题所在,请告诉我。 谢谢

【问题讨论】:

  • 它的描述太长了..让它变得小而简单。
  • 很抱歉,但我想解释一下发生了什么,英语不是我的母语...非常抱歉。
  • 与其对您的项目进行如此长的描述,不如将您的项目上传到 github 可能会更好。
  • 在您的 configureCell 方法中,确保您正在执行 if{urgent do something} else if {not紧急做其他事情}。

标签: ios objective-c core-data


【解决方案1】:

您的问题似乎出在configureCell: 方法中。您没有考虑细胞重用。您正在配置的单元格以前可能需要使用过,并且以前可能处于紧急状态。

您的代码只处理单元格紧急的情况,在这种情况下它会添加一个子视图。这种方法有两个问题:

  1. 重复使用的单元格每次都会添加子视图 - 因此可能会有许多紧急视图叠加在一起。单元格只应添加一次并将其保存在属性中
  2. 当单元紧急时,必须添加代码来配置单元(通常是在if 之后的else)。这将隐藏紧急图标。

【讨论】:

  • 感谢您的回答,我明白您的意思,并且我已经从您的回答中实施了第 2 点,但仅这一点并不能解决我的问题。我需要你的帮助来实施第 1 点。再次感谢您。
  • 我想我会问另一个关于重用单元问题的问题。谢谢。
【解决方案2】:

我注意到代码的第一个问题是您必须在之后添加代码

[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

不是在它之前。它将保证您的视图至少已加载。

其次,从你所有的字符串文字中生成这样的 const 字符串并在任何地方使用它

static NSString * const kUrgentState = @"Urgent";

还有一个更常见的提示:添加 NSLog(...);或者在调试中测试变量的值来定位问题,因为现在代码真的太多了,但仍然不足以找到问题。 找出变量值出错的时刻,然后解决您的问题

【讨论】:

  • 这是有用的建议,但不能回答问题。
  • 我只是想让你更具体地说明你的问题
  • 感谢您的回答,但我会尝试继续遵循@jrturton 的提案表格。
猜你喜欢
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多