Iphone 平移手势是否会导致子视图中的崩溃?

Iphone 平移手势是否会导致子视图中的崩溃?,iphone,objective-c,ios,xcode,ipad,Iphone,Objective C,Ios,Xcode,Ipad,我创建了一个项目,作为带有初始ViewController的单视图应用程序;将子ViewController添加到项目中。在两个视图控制器中都添加了带有平移手势的UIImageView。 它在viewController.m中工作, 但是,当它被添加到子视图控制器中,并且子视图作为子视图添加到视图控制器中时,该程序就会因“Exc_bad_access”而崩溃 有人有办法吗 这是我的密码: ViewController.m #import "ViewController.h" #import "S

我创建了一个项目,作为带有初始ViewController的单视图应用程序;将子ViewController添加到项目中。在两个视图控制器中都添加了带有平移手势的UIImageView。
它在viewController.m中工作, 但是,当它被添加到子视图控制器中,并且子视图作为子视图添加到视图控制器中时,该程序就会因“Exc_bad_access”而崩溃

有人有办法吗

这是我的密码:

ViewController.m

#import "ViewController.h"
#import "SubViewController.h"

//#define SUB

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

#ifdef SUB
    SubViewController *sb = [[SubViewController alloc] init];
    [self.view addSubview:sb.view];
#else
    UIImageView* img_ = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"monkey_1.png"]];
    img_.userInteractionEnabled = YES;
    UIPanGestureRecognizer *stampPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [stampPanGesture setMinimumNumberOfTouches:1];
    [stampPanGesture setMaximumNumberOfTouches:1];
    [img_ addGestureRecognizer:stampPanGesture];
    img_.center = self.view.center;
    [self.view addSubview:img_];
#endif
}


- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

}
#import "SubViewController.h"
@interface SubViewController ()

@end

@implementation SubViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


    UIImageView* img_ = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"monkey_1.png"]];
    img_.userInteractionEnabled = YES;
    UIPanGestureRecognizer *stampPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [stampPanGesture setMinimumNumberOfTouches:1];
    [stampPanGesture setMaximumNumberOfTouches:1];
    [img_ addGestureRecognizer:stampPanGesture];
    img_.center = self.view.center;
    [self.view addSubview:img_];
}


- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

}
SubViewController.m

#import "ViewController.h"
#import "SubViewController.h"

//#define SUB

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

#ifdef SUB
    SubViewController *sb = [[SubViewController alloc] init];
    [self.view addSubview:sb.view];
#else
    UIImageView* img_ = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"monkey_1.png"]];
    img_.userInteractionEnabled = YES;
    UIPanGestureRecognizer *stampPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [stampPanGesture setMinimumNumberOfTouches:1];
    [stampPanGesture setMaximumNumberOfTouches:1];
    [img_ addGestureRecognizer:stampPanGesture];
    img_.center = self.view.center;
    [self.view addSubview:img_];
#endif
}


- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

}
#import "SubViewController.h"
@interface SubViewController ()

@end

@implementation SubViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


    UIImageView* img_ = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"monkey_1.png"]];
    img_.userInteractionEnabled = YES;
    UIPanGestureRecognizer *stampPanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [stampPanGesture setMinimumNumberOfTouches:1];
    [stampPanGesture setMaximumNumberOfTouches:1];
    [img_ addGestureRecognizer:stampPanGesture];
    img_.center = self.view.center;
    [self.view addSubview:img_];
}


- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

}

假设这是ARC代码,问题是您正在创建子视图的视图控制器,捕获它的视图,但随后让控制器本身超出范围并被释放

直接的解决方法是将
SubViewController*sb
作为主视图控制器类的实例变量,这样它就不会超出范围,也不会在您身后被释放

问题是,虽然这可能会修复崩溃,但更大的问题是,您确实不应该获取视图控制器的视图并将其添加为子视图,而应该对控制器本身不做任何操作。例如,如果您这样做,各种事情可能无法正常工作(例如,旋转事件将永远不会到达您的子视图;iOS需要与视图控制器通信的任何内容都可能不会被您的子视图控制器接收到;我不知道在这个世界上,
didReceiveMemoryWarning
情况会发生什么,等等)。简言之,苹果建议不要这样做,并鼓励您保持视图层次结构和视图控制器层次结构的同步

因此,如果您正在转换到一个新视图,您确实应该通过
pushViewController
presentViewController
来完成。在不太可能的情况下,这实际上是一个子视图(例如,先前视图的部分将保留在屏幕上,而子视图将只占据屏幕的一部分),您可以使用。有关安全壳的更多信息,请参见。但这对你所要做的无疑是过分的。推送/呈现子视图可能是合乎逻辑的解决方案