在解除模态视图

时间:2016-03-15 03:35:12

标签: ios objective-c uiscrollview uiscrollviewdelegate

大家好我已经调试了这个问题很长一段时间但到目前为止没有运气。我在这里迷失了,并且不知道造成这次崩溃的原因以及如何解决它。如果有人能为我提供一些帮助,我将非常感激,非常感谢!

我准备了一个示例项目来展示GitHub here处的问题。

方案如下:

  1. 有两个视图控制器,即根视图和模态视图,每个都有一个自定义滚动视图(类SubScorllView)作为子视图,模态视图有一个用于解除模态的按钮图。

  2. 滚动视图是UIScrollView的子类,每个子类都有相应的委托协议,其类层次结构如下:

  3.   

    的UIScrollView
      ∟SuperScrollView
      .....∟SubScrollView

    App在AppDelegate的didFinishLaunchingWithOptions中以非常简单的方式启动和运行:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.backgroundColor = [UIColor blackColor];
    
        RootViewController * rootVC = [[RootViewController alloc] init];
        self.navVC = [[UINavigationController alloc] initWithRootViewController:rootVC];
        self.navVC.navigationBarHidden = TRUE;
    
        self.window.rootViewController = self.navVC;
        [self.window makeKeyAndVisible];
    
        ModalViewController *modalVC = [[ModalViewController alloc] init];
        [self.navVC presentViewController:modalVC animated:YES completion:nil];
    
        return YES;
    }
    

    视图是从xib文件加载的,滚动视图的委托也在里面设置,并且有一些关于启动和设置滚动视图子类的委托的方法的覆盖。

    当我通过单击模态视图中的“关闭”按钮关闭模态视图时出现问题,单击该按钮时,会发生以下情况:

    - (IBAction)didPressedCloseButton:(id)sender {
    
        self.subScrollView.delegate = nil;
        [self dismissViewControllerAnimated:YES completion:nil];
    
    }
    

    该应用在SuperScrollView中的以下细分受损:

    - (void)setDelegate:(id<SuperScrollViewDelegate>)delegate {
    
        _superScrollViewDelegate = delegate;
    
        // trigger UIScrollView to re-examine delegate for selectors it responds
        super.delegate = nil;
        super.delegate = self;  // app crashes at this line
    }
    

    控制台中显示以下错误消息:

      

    objc [6745]:无法形成对实例(0x7fa803839000)的弱引用   class SubScrollView。这个对象可能是   过度释放,或正在解除分配。

    我不明白为什么应用会崩溃并提供上述错误消息,或者我应该如何解决它。我尝试使用错误消息进行搜索,但似乎该消息主要与其他类(如文本视图)相关,而其他一些消息则通过在解除分配之前将滚动视图的委托设置为nil来解决它,但在我的情况下它不起作用。 / p>

    ==========

    更新:刚刚测试过iOS 8上是否有模拟器,它就不会像在iOS 9上那样崩溃。

3 个答案:

答案 0 :(得分:5)

取消分配SuperScrollView时,会隐式调用setDelegate。在iOS 9中,您无法将委托设置为self,因为self正在被解除分配(不知道为什么这在iOS 8中有效)。要解决此问题,您可以先检查传入的委托参数是否为nil,然后将super.delegate设置为self:

- (void)setDelegate:(id<SuperScrollViewDelegate>)delegate {

    _superScrollViewDelegate = delegate;

    // trigger UIScrollView to re-examine delegate for selectors it responds
    super.delegate = nil;

    if(delegate)
    {
        super.delegate = self;
    }
}

如果由于某种原因你需要支持自我响应UIScrollView委托方法,即使_superScrollViewDelegate为nil,你也可以创建一个参数

@interface SuperScrollView ()

@property (nonatomic, weak) SuperScrollView * weakSelf;

@end

位于文件顶部,并在设置

中设置
- (void)setup {

    super.delegate = self;
    self.weakSelf = self;
}

然后,在setDelegate中,检查weakSelf是不是nil。如果weakSelf为nil,则self正在解除分配,你不应该将它设置为super.delegate:

- (void)setDelegate:(id<SuperScrollViewDelegate>)delegate {

    _superScrollViewDelegate = delegate;

    // trigger UIScrollView to re-examine delegate for selectors it responds
    super.delegate = nil;

    if(self.weakSelf)
    {
        super.delegate = self;
    }
} 

答案 1 :(得分:0)

super.delegate = selfsuper此处为UIScrollViewsuper.delegate的类型为UIScrollViewDelegateself的类型为UIScrollView ,所以你将UIScrollView的委托设置为滚动视图,这没有意义,通常控制器应该是UIScrollView的委托。

当你关闭模态视图控制器时,它正处于释放过程中。 super.delegate = self;,此处self是滚动视图,它是self.view的子视图,属于模态视图控制器。所以self也在解除分配。

答案 2 :(得分:0)

我在 Swift 中遇到了同样的问题,cncool的回答帮助了我。 以下内容(考虑在父类的实例中)解决了我的问题:

deinit {
    self.scrollView.delegate = nil
}