【问题标题】:Property gets nilled财产被取消
【发布时间】:2016-04-07 06:08:41
【问题描述】:

我有一个现有的应用程序,该应用程序自 2010 年以来就在应用程序商店中。由于缺乏空闲时间,我无法将其从 iOS7 之前的版本更新到 iOS7+。这就是我目前正在尝试做的事情(使用最新的 9.2 SDK)。

但是,我遇到了一些奇怪的问题,我什至无法接近某些可能的原因,而且我很迷茫,不知道如何进一步调查。

应用启动时,从核心数据存储中加载一个对象,该对象属于YearSummary类(直接继承NSManagedObject,只有一些简单的属性)。此对象保存在我的根视图控制器的 retain-property 中。
现在奇怪的是,在成功加载对象后,该属性以某种方式重置为nil,并且根视图控制器无法在我的应用程序中显示对象属性。我不知道这是怎么发生的,以及为什么会这样。

我已经用自己的 setter 将其设为非属性,因此我可以跟踪它何时重置为 nil,但没有成功。找不到对象的明显变化。

这大概是我的代码:(应用程序代码比较大,我试着找到重要的部分)

rootviewcontroller.m

-(void)viewDidLoad
{
    YearSummary* thisYear= [SomeClass fetchYear:2016];
    self.currentYear= thisYear;   // retain property

    NSLog(@"Loaded existing Summary (%p) for CURRENT year (%d)", thisYear, 2016);

    [self.tableView reloadData];  // will display stuff from current year in a tableview
    [super viewDidLoad];
}

someclass.m:

+(YearSummary*)fetchYear:(int)year
{
   NSManagedObjectContext* context= [ServiceClass getManagedObjectContext];

   if (!context)
      return false;

   NSFetchRequest* request = [[NSFetchRequest alloc] init];
   NSEntityDescription* entity = [NSEntityDescription entityForName:@"YearSummary" inManagedObjectContext:context];
   NSPredicate* predicate = [NSPredicate predicateWithFormat:@"year == %d, year];
   NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"year" ascending:NO];
   NSArray* sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

   [request setPredicate:predicate];
   [request setEntity:entity];
   [request setSortDescriptors:sortDescriptors];
   [sortDescriptors release];
   [sortDescriptor release];

   NSError* error= nil;
   NSArray* results = [context executeFetchRequest:request error:&error];

   [request release];

   if (!results || ![results count])
   {
      [ServiceClass showErrorMessage:NSLocalizedString(@"Error", nil) withText:NSLocalizedString(@"Failed to load data from storage", nil) andError:error];
      return 0;
   }

   return [results objectAtIndex:0];
}

再次rootviewcontroller.m:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{
   NSLog(@"Tableview header with year year (%d) (%p)", self.currentYear.year.intValue, self.currentYear);

   if (self.currentYear)
      return [NSString stringWithFormat:@"%@ %d", NSLocalizedString(@"Overview", nil), [[self.currentYear year] intValue]];

   NSLog(@"DONT HAVE CURRENT YEAR");

   return @"";
}

这将在应用启动时打印:

2016-01-03 14:51:39.410 MyApp[12103:655470] Loaded existing Summary (0x13f6e0f90) for CURRENT year (2016)
2016-01-03 14:51:40.394 MyApp[12103:655470] Tableview header with year year (2016) (0x13f6e0f90)

但是表头显示一个零字符串作为标题,这让我很困惑,因为根据上面的代码应该 not 是可能的吗??

当我拖动 tableview,重新创建标题时,会打印出来:

2016-01-03 14:51:42.695 MyApp[12103:655470] Tableview header with year year (0) (0x0)
2016-01-03 14:54:13.089 MyApp[12103:655470] DONT HAVE CURRENT YEAR

有人可以指导我找到可能的解决方案,或者给我一些提示,我可以如何追查这种行为的根本原因?

注意:由于这是一个旧应用程序,我没有在我的项目中使用 ARC。

[编辑] 我还添加了一个观察点,如下所示。这是输出:

Watchpoint created: Watchpoint 2: addr = 0x125740fa8 size = 8 state = enabled type = w
    watchpoint spec = 'currentYear'
    new value: 0x0000000000000000

...大约一秒钟后:

Watchpoint 1 hit:
old value: 0x0000000000000000
new value: 0x000000013ccdcf90

【问题讨论】:

  • 您是否尝试过将 watchpoint 放在后备实例变量上?也可以实现更新 ARC,并且值得付出努力。
  • 我添加了观察点,在编辑后的帖子中查看上面的结果。
  • 还要检查打印结果的控制器的地址,而不仅仅是打印的结果。
  • 继上一条评论之后,您是否有可能有两个 rootviewcontroller 实例,其中一个从未显示,因此从不调用 viewDidLoad
  • 关于观察点的重要一点是堆栈跟踪中的内容(即设置属性的内容)?

标签: ios objective-c iphone core-data properties


【解决方案1】:

来自cmets:

当一个对象的属性有一个意外的值,尤其是一个似乎未初始化的值时,通过记录地址或在调试器中查看它来检查该对象是否真的是您所期望的。

(这在视图控制器中的 nil IBOutlets 中尤其常见。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多