UIScrollView 子视图中手势触发异常

Posted

技术标签:

【中文标题】UIScrollView 子视图中手势触发异常【英文标题】:Gesture triggers exception in subview of UIScrollView 【发布时间】:2014-07-15 16:38:08 【问题描述】:

这里是 ios 程序员新手,如果我遗漏了一些简单的东西,非常抱歉,但是...

我有一个名为 LVSTSPMasterViewController 的 UIViewController 类,它的视图是在 IB 中构建的。该视图包含一个 UIScrollView(在 IB 中添加),并且该滚动视图具有 LVSTSPView 类型的子视图。 LVSTSPView 有一个 LVSTSPViewController 类型的控制器。

我想响应 LVSTSPView 中的触摸,所以我在 LVSTSPViewController.m 中添加了手势识别器。当我执行手势(例如,长按)时,代码崩溃,并在 ma​​in.m 中显示消息“EXC_BAD_ACCESS (code=1, address=...)”。

相关代码:

LVSAppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    // Get pointer to app bundle
    NSBundle *appBundle = [NSBundle mainBundle];

    // Get xib file
    LVSTSPMasterViewController *tspmvc = [[LVSTSPMasterViewController alloc] initWithNibName:@"LVSTSPMasterViewController" bundle:appBundle];

    self.window.rootViewController = tspmvc;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;

LVSMasterViewController.m

@interface LVSTSPMasterViewController () <UIScrollViewDelegate>

// IBOutlet declarations

@property (nonatomic, weak) IBOutlet UIScrollView *TSPScrollView;

// Pointers for convenience

@property (strong, nonatomic) LVSTSPView *TSPView;

@end

@implementation LVSTSPMasterViewController
- (void)viewDidLoad

    // Create LVSTSPViewController
    LVSTSPViewController *tspvc = [[LVSTSPViewController alloc] init];

    // Set up pointer to LVSTSPView
    self.TSPView = (LVSTSPView *)tspvc.view;

    // Set frame of LVSTSPView
    self.TSPView.frame = self.TSPScrollView.bounds;

    // Set tspvc's view as subview of TSPScrollView
    [self.TSPScrollView addSubview:tspvc.view];

    // Set up scroll view
    self.TSPScrollView.pagingEnabled = NO;
    self.TSPScrollView.contentSize = self.TSPView.frame.size;
    self.TSPScrollView.minimumZoomScale = 1.0;
    self.TSPScrollView.maximumZoomScale = 3.0;

    // Set scroll view's delegate property
    self.TSPScrollView.delegate = self;

LVSTSPViewController.m

- (void)loadView

    // Create view
    LVSTSPView *view = [[LVSTSPView alloc] initWithFrame:CGRectZero];
    self.view = view;

    // Long-press recognizer
    UILongPressGestureRecognizer *pressRecognizer =
        [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    [self.view addGestureRecognizer:pressRecognizer];


- (void)longPress:(UIGestureRecognizer *)gr

    NSLog(@"longPress:");


另一个注意事项:如果我在 LVSTSPMasterViewController.m 中的viewDidLoad: 中设置手势识别器,就像这样 --

UILongPressGestureRecognizer *pressRecognizer =
    [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.TSPView addGestureRecognizer:pressRecognizer];

--(当然也可以在 LVSTSPMasterViewController.m 中添加longPress:),然后就可以了。但这似乎不是正确的方法,因为 LVSTSPMasterViewController 不是 LVSTSPView 的视图控制器。

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

您的视图控制器 LVSTSPViewController 不会保留在任何地方,或者换句话说,您的主视图控制器需要保留它。 在 LVSMasterViewController.m 中,将您的代码更改为

@implementation LVSTSPMasterViewController

   LVSTSPViewController *tspvc;//creates strong reference to self(LVSTSPMasterViewController)


- (void)viewDidLoad

  [super viewDidLoad];
  // Do any additional setup after loading the view from its nib.
  tspvc = [[LVSTSPViewController alloc] init];

  // Set up pointer to LVSTSPView
  self.TSPView = (LVSTSPView *)tspvc.view;

  // Set frame of LVSTSPView
  self.TSPView.frame = self.TSPScrollView.bounds;

  // Set tspvc's view as subview of TSPScrollView
  [self.TSPScrollView addSubview:tspvc.view];

  // Set up scroll view
  self.TSPScrollView.pagingEnabled = NO;
  self.TSPScrollView.contentSize = self.TSPView.frame.size;
  self.TSPScrollView.minimumZoomScale = 1.0;
  self.TSPScrollView.maximumZoomScale = 3.0;

  // Set scroll view's delegate property
  self.TSPScrollView.delegate = self;

也总是在你的 viewDidLoad 方法中首先调用 [super viewDidLoad]。我建议在苹果文档中阅读更多关于视图和视图控制器的信息。您不一定需要每个视图都有一个视图控制器。这完全取决于您的具体情况。一个视图控制器可以管理多个视图。

【讨论】:

感谢@codingBuddha——这行得通。您在@implementation 之后声明 tspvc 的方式的名称是什么?顺便说一句,我确实需要一个 VC,但谢谢你的提示。至于[super viewDidLoad],我知道但忘记了。 :\ 这不过是在没有属性的情况下定义实例变量。 see this

以上是关于UIScrollView 子视图中手势触发异常的主要内容,如果未能解决你的问题,请参考以下文章

缩放时,UIScrollview 子视图无法识别手势

UIScrollview 子视图在缩放后无法识别平移手势

UIScrollView 并检测其子视图的手势

禁用 UIScrollView 手势

将捏合手势从自定义 UIView 传递到父 UIScrollView

UIScrollView 并取消缩放捏合手势