0

TestFlight在我的应用程序中发现了一个我无法复制的崩溃,但它发生得足够多,我需要修复它。我认为该错误是unrecognized selector sent to instance 0x34a9e0当我尝试将 locationId 分配给被 GC 消除的对象时引起的。

-[UIViewAnimationState locationId]: unrecognized selector sent to instance 0x34a9e0

0 CoreFoundation 0x371e488f __exceptionPreprocess + 163
1 libobjc.A.dylib 0x34ee9259 objc_exception_throw + 33
2 CoreFoundation 0x371e7a9b -[NSObject doesNotRecognizeSelector:] + 175
3 CoreFoundation 0x371e6915 ___forwarding___ + 301
4 CoreFoundation 0x37141650 _CF_forwarding_prep_0 + 48
5 Skate Spots 0x0000b9b9 -[DetailViewController handlePhotosButtonClick:] (DetailViewController.m:92)
6 CoreFoundation 0x3713e3fd -[NSObject performSelector:withObject:withObject:] + 53
7 UIKit 0x30ed3e07 -[UIApplication sendAction:to:from:forEvent:] + 63
8 UIKit 0x30ed3dc3 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 31
9 UIKit 0x30ed3da1 -[UIControl sendAction:to:forEvent:] + 45
10 UIKit 0x30ed3b11 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 493
11 UIKit 0x30ed4449 -[UIControl touchesEnded:withEvent:] + 477
12 UIKit 0x30ec6b87 _UIGestureRecognizerUpdate + 5223
13 CoreFoundation 0x371b8b1b __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 19
14 CoreFoundation 0x371b6d57 __CFRunLoopDoObservers + 259
15 CoreFoundation 0x371b70b1 __CFRunLoopRun + 761
16 CoreFoundation 0x3713a4a5 CFRunLoopRunSpecific + 301
17 CoreFoundation 0x3713a36d CFRunLoopRunInMode + 105
18 GraphicsServices 0x338f9439 GSEventRunModal + 137
19 UIKit 0x30ee6cd5 UIApplicationMain + 1081
20 Skate Spots 0x0000325f -[Image willSendWithObjectLoader:] (Image.m:83)
21 Skate Spots 0x00002b18 + 0

原始代码:

我假设 autorelease 将在此方法的范围内保留引用。

-(IBAction)handlePhotosButtonClick:(id)sender
{
  PhotosViewController *vc = [[[PhotosViewController alloc] init] autorelease];
  vc.locationID            = _location.locationId;
  [self.navigationController pushViewController:vc animated:YES];
}

我的代码更改:

我猜这将消除原来的错误,但这是正确的做法吗?

-(IBAction)handlePhotosButtonClick:(id)sender
{
  NSLog(@"handlePhotosButtonClick");    
  PhotosViewController *vc = [[[PhotosViewController alloc] init] retain];
  vc.locationID            = _location.locationId;

  [self.navigationController pushViewController:vc animated:YES];
  [vc release];
}

编辑

你们是正确的 _location 没有设置为保留值。

@property (nonatomic, readwrite, assign) RKLocation *location;

4

3 回答 3

1
PhotosViewController *vc = [[[PhotosViewController alloc] init] retain]; // <--- this is over retaining and it's totally wrong, because init method returns an already retained object.

该错误与您_location.locationId有关,它调用了 getter_location并且在某些时候您可能已经释放了它。检查您的代码的生命周期,_location并且最好使用属性而不是实例变量。

于 2012-05-20T18:22:25.687 回答
0

关于您的代码,您的原始代码更接近您想要的。值得注意的是,您的最终代码:

-(IBAction)handlePhotosButtonClick:(id)sender
{
    NSLog(@"handlePhotosButtonClick");    
    PhotosViewController *vc = [[[PhotosViewController alloc] init] retain];
    vc.locationID            = _location.locationId;

    [self.navigationController pushViewController:vc animated:YES];
    [vc release];
}

肯定是错误的,会导致泄漏。它应该是:

-(IBAction)handlePhotosButtonClick:(id)sender
{
    NSLog(@"handlePhotosButtonClick");    
    PhotosViewController *vc = [[PhotosViewController alloc] init];
    vc.locationID            = _location.locationId;

    [self.navigationController pushViewController:vc animated:YES];
    [vc release];
}

这就像您的原始版本一样autorelease,但这更好,因为您通常应该只autorelease在需要延迟时使用release(在这种情况下您不需要)。

您的问题不在于视图控制器的保留计数,而无疑与 locationID 本身有关。你能与我们分享它的声明(在 PhotosViewController 类以及当前类中)吗?它是什么?它是如何宣布的?

于 2012-05-20T18:29:21.937 回答
0
-[UIViewAnimationState locationId]: unrecognized selector sent to instance 0x34a9e0

所以发送的选择器是 locationId (getter),而不是 setLocationId: (setter)。这意味着,不是自动释放的对象(在这种情况下是您的视图控制器)导致错误,因为您设置了它的属性,所以运行时调用 setLocationId: 就可以了。它评估在_location某处被释放的对象,然后另一个对象接管它的指针(在这种特殊情况下它是一个 UIViewAnimationState ),当然它不会响应 locationId getter。尝试修改您的代码,以便在您需要它的属性之前不会释放 _locationId 变量。

于 2012-05-20T18:17:32.243 回答