【问题标题】:iOS - Subview Crashing On ResumeiOS - 恢复时子视图崩溃
【发布时间】:2011-04-21 17:55:17
【问题描述】:

我有几个由导航控制器控制的子视图。其中之一是在简历上崩溃。它是一个通过推进一系列图像和平移手势控制器将模型“旋转”360 度(想想地球)的类。

在我按下那个讨厌的主页按钮之前,一切都很好。当我点击主页按钮时,直到图像在 UIView 上设置,然后它才会崩溃......至少在大多数情况下。有时它会更改一次并在第二次更改时崩溃,显然只是为了让我的生活更有趣。

您可以对此提出任何见解。

提前致谢。

//  RotationController.m
//

#import "RotationController.h"

@implementation RotationController

@synthesize myRotationView;
@synthesize imageName;
@synthesize scheme;
int maxFrame;
int currentX;

- (void)viewDidLoad {
    [super viewDidLoad];

    //self.title = @"Cutaway View";

    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panPiece:)];
    [myRotationView addGestureRecognizer:panGesture];
    [panGesture release];
}

-(void)setup:(int) currentNode{

    if (currentNode <= 2)
    {
        currentX = 0;
        maxFrame = 199;
        scheme = @"Trailer1Rotation_";
        self.title = @"Trailer One Cutaway View";
        [self.myRotationView setImage:[UIImage imageNamed:@"Trailer1Rotation_000.jpg"]];
    }
    else if (currentNode > 2 && currentNode <= 5)
    {
        currentX = 0;
        maxFrame = 199;
        scheme = @"spinTrailer2_00";
        self.title = @"Trailer Two Cutaway View";
        [self.myRotationView setImage:[UIImage imageNamed:@"spinTrailer2_00000.jpg"]];
    }
    else if (currentNode > 5 && currentNode <= 8)
    {
        currentX = 0;
        maxFrame = 199;
        scheme = @"spinTrailer3_00";
        self.title = @"Trailer Three Cutaway View";
        [self.myRotationView setImage:[UIImage imageNamed:@"spinTrailer3_00000.jpg"]];
    }
    else if (currentNode > 8)
    {
        currentX = 0;
        maxFrame = 199;
        scheme = @"spinTrailer4_00";
        self.title = @"Trailer Four Cutaway View";
        [self.myRotationView setImage:[UIImage imageNamed:@"spinTrailer4_00000.jpg"]];
    }
}

-(void)viewWillAppear:(BOOL)animated {

    self.myRotationView.userInteractionEnabled = YES;
}

-(void)applicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"Test - DidEnterBackGround");
}

-(void)applicationWillResignActive
{
    NSLog(@"Test - WillResignActive");
}

- (void)applicationDidBecomeActive
{
    NSLog(@"Test - DidBecomeActive");

    [self.myRotationView setImage:[UIImage imageNamed:@"Trailer1Rotation_000.jpg"]];
}

-(void)panPiece:(UIPanGestureRecognizer *) gesture{

    switch(gesture.state) {
        case UIGestureRecognizerStateChanged: {
            //CGPoint center = gesture.view.center;
            CGPoint translation = [gesture translationInView:gesture.view];

//          center = CGPointMake((center.x + translation.x),
//                               (center.y + translation.y));
//          gesture.view.center = center;
//          [gesture setTranslation:CGPointZero inView:gesture.view];

            NSLog(@"Changed");
            NSLog(@"%f", translation.x);
            NSLog(@"%f", translation.y);

            int changeX = (int)translation.x / 20;

            if (changeX == 0)
                changeX = 1;

            currentX = (int)currentX + (int)changeX;

            while (currentX > 174) {
                currentX = currentX - 174;
            }

            while (currentX < 0) {
                currentX = currentX + 174;
            }

            if (currentX < 10) {
                imageName = [NSString stringWithFormat:@"%@00%i.jpg", scheme, currentX];
                NSLog(@"%@", imageName);
            } else if (currentX < 100) {
                imageName = [NSString stringWithFormat:@"%@0%i.jpg", scheme, currentX];
                NSLog(@"%@", imageName);
            } else {
                imageName = [NSString stringWithFormat:@"%@%i.jpg", scheme, currentX];
                NSLog(@"%@", imageName);
            }

            //NSLog(@"%@", myRotationView.image);
            [self.myRotationView setImage:[[UIImage imageNamed:imageName]autorelease]];
            //NSLog(@"%@", myRotationView.image);
        }
        case UIGestureRecognizerStateBegan: {
            [gesture setTranslation:CGPointZero inView:gesture.view];

            NSLog(@"Began");

            break;
        }
        case UIGestureRecognizerStateEnded: {
            //CGPoint velocity = [gesture velocityInView:self.view];
            //The user lifted their fingers. Optionally use the velocity to contain rotating the globe automatically

            NSLog(@"Ended");

            break;
        }
        default: {
            //Something else happened. Do any cleanup you need to.
            NSLog(@"Something else happened.");
        }
    }
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code.
}
*/

- (void)dealloc {
    [super dealloc];


    NSLog(@"Rotation Controller - DeAlloc");
    [myRotationView release];
    [scheme release];
    [imageName release];
}

@end

回溯:

2011-04-21 14:38:39.442 MCIT[52259:207] Test - DidBecomeActive
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) backtrace
#0  0x01326a78 in objc_msgSend ()
#1  0x0633d540 in ?? ()
#2  0x000138b2 in -[RotationController applicationDidBecomeActive] (self=0x6607dc0, _cmd=0x17540) at /Users/jacob/Documents/iOS Dev/MCIT/Classes/RotationController.m:83
#3  0x00002a1c in -[MCITAppDelegate applicationDidBecomeActive:] (self=0x6603f30, _cmd=0x6e25a7, application=0x6300700) at /Users/jacob/Documents/iOS Dev/MCIT/Classes/MCITAppDelegate.m:100
#4  0x002d2542 in -[UIApplication _setActivated:] ()
#5  0x002dfe18 in -[UIApplication _handleApplicationResumeEvent:] ()
#6  0x002df7d4 in -[UIApplication handleEvent:withNewEvent:] ()
#7  0x002d7202 in -[UIApplication sendEvent:] ()
#8  0x002dc732 in _UIApplicationHandleEvent ()
#9  0x01afaa36 in PurpleEventCallback ()
#10 0x01afaabd in PurpleEventSignalCallback ()
#11 0x011a601f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#12 0x0110428b in __CFRunLoopDoSources0 ()
#13 0x01103786 in __CFRunLoopRun ()
#14 0x01103240 in CFRunLoopRunSpecific ()
#15 0x01103161 in CFRunLoopRunInMode ()
#16 0x01af9268 in GSEventRunModal ()
#17 0x01af932d in GSEventRun ()
#18 0x002e042e in UIApplicationMain ()
#19 0x00001f0e in main (argc=1, argv=0xbffff070) at /Users/jacob/Documents/iOS Dev/MCIT/main.m:14

我在测试代码上的想法在设置图像时失败了。

- (void)applicationDidBecomeActive
{
    NSLog(@"Test - DidBecomeActive");

    [self.myRotationView setImage:[UIImage imageNamed:@"Trailer1Rotation_000.jpg"]];
}

【问题讨论】:

  • 我意识到我可以通过保存 App Delegate 中的值来解决此错误,从而消除 ApplicationWillResignActive 上的旋转子视图并使用保存的值在 ApplicationDidBecomeActive 上读取它...我希望我是缺少一个“更正确”的修复。
  • 您是否有一个我们可以查看的崩溃日志,它可能会给出崩溃的具体原因?
  • 信息性:'程序接收信号:“EXC_BAD_ACCESS”。'
  • 从 gdb 发布完整的回溯会很有帮助。
  • 现在正在尝试 GDB 跟踪...

标签: iphone ipad uiview ios4 uigesturerecognizer


【解决方案1】:

我发现调试这些问题的最简单方法是为您的可执行文件打开 NSZombieEnabled。

在 Xcode 中为您的项目展开“可执行”项,双击它。现在单击左下角的加号 ('+') 图标并添加一个值为 YESNSZombieEnabled 变量。

您应该只在开发期间使用此设置,否则您的应用将永远无法正确释放内存。您不想尝试在启用此设置的情况下交付您的应用。

我通过向我的 UIApplicationDelegate 类添加一些测试代码来检查这一点:

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
  if (getenv("NSZombieEnabled"))
  {
    NSLog(@"WARNING! NSZombieEnabled enabled!");
  }

  if (getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  {
    NSLog(@"WARNING! NSAutoreleaseFreedObjectCheckEnabled enabled!");
  }

【讨论】:

  • 这帮助很大。 "*** -[UIImage isKindOfClass:]: message sent to deallocated instance 0xa428f80" 意味着 UIView 上的 UIImage 以某种方式被释放了...
  • 知道了,因为我在做这个 [self.myRotationView setImage:[[UIImage imageNamed:imageName]autorelease]];当应用程序暂停时,它会释放那些已经显示的图像。
【解决方案2】:

首先,改变你的 dealloc 方法

[super dealloc]

是最后一行,而不是第一行。它应该永远是你在 dealloc 中做的最后一件事。

myRotationView 是在 Nib 中创建的吗?你是在 viewDidUnload 中发布的吗?

最后,整个堆栈跟踪将告诉我们 EXC_BAD_ACCESS 发生在哪一行。

【讨论】:

  • 移动了 [super dealloc] myRotationView 没有与之关联的 nib 并且没有 viewDidUnload 因为我认为它可能导致了问题。
猜你喜欢
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多