【问题标题】:detailViewController crash on dealloc using arc due to property being released由于属性被释放,detailViewController 在使用 arc 的 dealloc 上崩溃
【发布时间】:2013-07-15 22:21:09
【问题描述】:

在导航视图控制器中使用后退按钮时,我遇到了视图控制器崩溃的问题。

在主表视图控制器中,我像这样覆盖了为 segue 做准备:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

/*
 When a row is selected, the segue creates the detail view controller as the destination.
 Set the detail view controller's detail item to the item associated with the selected row.
 */
if ([[segue identifier] isEqualToString:@"getHostedZoneSegue"]) {

    NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
    GetHostedZoneViewController *detailViewController = [segue destinationViewController];
    NSLog(@"setting zone ID");

    detailViewController.zoneID = [hostedZonesListID objectAtIndex:selectedRowIndex.row];

}
}

GetHostedViewController 声明了一个属性 zoneID:

@interface GetHostedZoneViewController : UIViewController 
{
    NSString *zoneID;
}
@property (nonatomic, copy)   NSString *zoneID;

在 viewDidLoad 中,我对框架中的方法执行此调用(对框架的调用发生在 GCD 异步块中,并且框架不使用 ARC):

Route53GetHostedZoneRequest *request = 
[[Route53GetHostedZoneRequest alloc] initWithHostedZoneID:self.zoneID];

框架是这样做的: .h:

@interface Route53GetHostedZoneRequest : AmazonServiceRequestConfig
{
    NSString *hostedZoneID;
}
@property (nonatomic, copy) NSString *hostedZoneID;

.m:

@synthesize hostedZoneID;

-(id)initWithHostedZoneID:(NSString *)theHostedZoneID
{
    if (self = [self init]) {
        hostedZoneID = theHostedZoneID;
    }
    return self;
}

应用程序中的下一次调用是使用上一次调用的结果调用框架中另一个类中的不同方法:

Route53GetHostedZoneResponse *response = [[AmazonClientManager r53] getHostedZone:request];

完成后,请求和响应都被释放(如预期的那样),奇怪的是,当请求被释放时,它也释放了 zoneID。使用我跟踪违规版本的工具:

[hostedZoneID release];

在 Route53GetHostedZoneRequest.m 的 dealloc 方法中。

这会在返回主控制器后释放 GetHostedZoneViewController 时导致僵尸,并导致应用崩溃。

如果我设置

detailViewController.zoneID = @"somestring";

无论我来回多少次,应用程序都不会崩溃。

谁能解释一下为什么会崩溃,或者给我一些关于如何修复它的指示?我真的不明白为什么 [hostedZoneID release] 会释放 zoneID

【问题讨论】:

  • 在我看来,您没有在 viewDidLoad 中初始化您的区域 ID。不清楚,因为你没有向我们展示它是什么。
  • 我相信它是在主视图控制器的 prepareForSegue 中初始化的,这似乎是公认的做法。 @Wain 解决了这个问题……谢谢!

标签: ios objective-c cocoa


【解决方案1】:

Route53GetHostedZoneRequest 你应该有:

- (id)initWithHostedZoneID:(NSString *)theHostedZoneID
{
    if (self = [self init]) {
        self.hostedZoneID = theHostedZoneID;
    }
    return self;
}

因为否则您不会保留实例,因为此代码未使用 ARC。


您的其他问题...

NSString 实例是不可变的,因此当您在属性上指定 copy 时,它实际上并没有被复制,它只是被保留。所以zoneIDhostedZoneID 实际上是同一个实例。

当您使用字符串文字时,它是一种特殊类型的对象,不会真正被保留或释放,因此您可以绕过这个问题。

【讨论】:

  • 是的,做到了!我没有意识到它也需要保留,因为我认为它是 zoneID 的副本。我仍然不明白为什么在 hostsZoneID 为时释放 zoneID...
猜你喜欢
  • 2012-10-11
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2012-02-27
  • 1970-01-01
相关资源
最近更新 更多