iOS - 删除所有子视图后重新添加子视图

时间:2017-02-21 17:47:41

标签: ios objective-c iphone uiview uigesturerecognizer

我正在制作一个球程序,您可以在长按手势上向超级视图添加球UIView子视图。点击视图会将其从superview中删除。

添加所有视图效果很好,重新添加视图效果很好,因为超级视图中至少有一个视图。但是,一旦删除了所有子视图,长按应该会再次重新添加第一个子视图,而是关闭程序。

我在其中一个主题中只获得了一条发布消息,让我相信这是一个alloc / dealloc问题,但ARC禁止我明确发布视图,我相信[removeFromSuperview]无论如何都会这样做。

我不确定我错过了什么。在点击之后,感兴趣的特定方法是tapped:createBall:已用于所有子视图。

ViewController.m

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

@property (nonatomic, strong) UILongPressGestureRecognizer *longPressRecog;
@property (nonatomic, strong) UIPanGestureRecognizer *panRecog;
@property (nonatomic, strong) UITapGestureRecognizer *tapRecog;
@property (nonatomic, strong) UIDynamicAnimator *anim;
@property (nonatomic, strong) NSTimer* timer;
@property (nonatomic, strong) UIView *orangeBall, *blueBall;
@property (nonatomic) CGPoint ballCenter;
@property (nonatomic, strong) NSMutableArray* ballsArray;
@property (nonatomic, assign) CGRect originalBounds;

@property (nonatomic) UIAttachmentBehavior *attachmentBehavior;
@property (nonatomic) UIPushBehavior *pushBehavior;
@property (nonatomic) UIDynamicItemBehavior *ballPhysics;
@property (nonatomic) UICollisionBehavior *collisionBehavior;

-(void)physics;
-(void)createBall;

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    // Prepare to handle Long Press to create ball object
    self.longPressRecog = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    self.longPressRecog.minimumPressDuration = 0.8f;
    [self.longPressRecog setDelegate:self];

    [self.view addGestureRecognizer:self.longPressRecog];
}

// Handles Long Presses and creates a ball within the view
- (void)longPress:(UILongPressGestureRecognizer *)sender {
    if ([sender isEqual:self.longPressRecog]) {
        if (sender.state == UIGestureRecognizerStateEnded) {
            [self createBall];
        }
    }
}

// Set Ball Attributes
- (void)setOrangeBall {
    if (self.viewLoaded) {
        // Load ball view to screen
        self.orangeBall = [[UIView alloc] initWithFrame:CGRectMake(100.0, 100.0, 50.0, 50.0)];
        self.orangeBall.layer.cornerRadius = 25.0;
        self.orangeBall.backgroundColor = [UIColor orangeColor];
        self.orangeBall.layer.borderColor = [UIColor orangeColor].CGColor;
        self.orangeBall.layer.borderWidth = 0.0;
        [self.view addSubview:self.orangeBall];
    } else {

    }
}

- (void)setBlueBall {
    // Load ball view to screen
    self.blueBall = [[UIView alloc] initWithFrame:CGRectMake(160.0, 160.0, 50.0, 50.0)];
    self.blueBall.layer.cornerRadius = 25.0;
    self.blueBall.backgroundColor = [UIColor blueColor];
    self.blueBall.layer.borderColor = [UIColor blueColor].CGColor;
    self.blueBall.layer.borderWidth = 0.0;
    [self.view addSubview:self.blueBall];
}


// Create Balls
- (void)createBall {
    if (![_orangeBall superview] && ![_blueBall superview]) {
        [self setOrangeBall];
    } else if ([_orangeBall superview] && ![_blueBall superview]) {
        [self setBlueBall];
    } else {
        // NOTHING
    }

    // Begin animations
    self.anim = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    // Init Physics
    [self physics];
}

// Gravity
- (void)physics {

    //Add ball objects to NSMutableArray. Needed in order to add behaviors to all ball objects.
    self.ballsArray = [NSMutableArray arrayWithObjects:self.orangeBall, self.blueBall, nil];

    //Tapping Behavior
    _tapRecog.delegate = self;
    for (UIView *ball in _ballsArray) {
        ball.userInteractionEnabled = YES;
        _tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
        [_tapRecog setNumberOfTapsRequired:2];
        [ball addGestureRecognizer:_tapRecog];
    }
}

- (void)tapped:(UITapGestureRecognizer *)recognizer {
    //Delete tapped ball
    [recognizer.view willRemoveSubview:recognizer.view];
    [recognizer.view removeFromSuperview];
}


@end

这是我从线程错误中找到的所有内容:

UIKit`UIApplicationMain:
    0x10acd4bc9 <+0>:   pushq  %rbp
    0x10acd4bca <+1>:   movq   %rsp, %rbp
    0x10acd4bcd <+4>:   pushq  %r15
    0x10acd4bcf <+6>:   pushq  %r14
    0x10acd4bd1 <+8>:   pushq  %r13
    0x10acd4bd3 <+10>:  pushq  %r12
    0x10acd4bd5 <+12>:  pushq  %rbx
    0x10acd4bd6 <+13>:  pushq  %rax
    0x10acd4bd7 <+14>:  movq   %rcx, %rbx
    0x10acd4bda <+17>:  movq   %rsi, -0x30(%rbp)
    0x10acd4bde <+21>:  movl   %edi, %r12d
    0x10acd4be1 <+24>:  movq   0xe7f7b8(%rip), %r13      ; (void *)0x0000000109c12cb0: objc_retain
    0x10acd4be8 <+31>:  movq   %rdx, %rdi
    0x10acd4beb <+34>:  callq  *%r13
    0x10acd4bee <+37>:  movq   %rax, %r14
    0x10acd4bf1 <+40>:  movq   %rbx, %rdi
    0x10acd4bf4 <+43>:  callq  *%r13
    0x10acd4bf7 <+46>:  movq   %rax, %r15
    0x10acd4bfa <+49>:  leaq   0x11dab6b(%rip), %r13     ; _UIApplicationLinkedOnVersion
    0x10acd4c01 <+56>:  movl   (%r13), %eax
    0x10acd4c05 <+60>:  testl  %eax, %eax
    0x10acd4c07 <+62>:  jne    0x10acd4c17               ; <+78>
    0x10acd4c09 <+64>:  cmpq   $-0x1, 0x11d4ab7(%rip)    ; WebKitSetIsClassic + 7
    0x10acd4c11 <+72>:  jne    0x10acd4c8a               ; <+193>
    0x10acd4c13 <+74>:  movl   (%r13), %eax
    0x10acd4c17 <+78>:  cmpl   $0x20100, %eax            ; imm = 0x20100 
    0x10acd4c1c <+83>:  jb     0x10acd4c42               ; <+121>
    0x10acd4c1e <+85>:  callq  0x10b8f8a8a               ; symbol stub for: objc_autoreleasePoolPush
    0x10acd4c23 <+90>:  movq   %rax, %r13
    0x10acd4c26 <+93>:  movl   %r12d, %edi
    0x10acd4c29 <+96>:  movq   -0x30(%rbp), %rsi
    0x10acd4c2d <+100>: movq   %r14, %rdx
    0x10acd4c30 <+103>: movq   %r15, %rcx
    0x10acd4c33 <+106>: callq  0x10acd4ca2               ; _UIApplicationMainPreparations
    0x10acd4c38 <+111>: movq   %r13, %rdi
    0x10acd4c3b <+114>: callq  0x10b8f8a84               ; symbol stub for: objc_autoreleasePoolPop
    0x10acd4c40 <+119>: jmp    0x10acd4c54               ; <+139>
    0x10acd4c42 <+121>: movl   %r12d, %edi
    0x10acd4c45 <+124>: movq   -0x30(%rbp), %rsi
    0x10acd4c49 <+128>: movq   %r14, %rdx
    0x10acd4c4c <+131>: movq   %r15, %rcx
    0x10acd4c4f <+134>: callq  0x10acd4ca2               ; _UIApplicationMainPreparations
    0x10acd4c54 <+139>: movq   0x11daa55(%rip), %rdi     ; UIApp
    0x10acd4c5b <+146>: movq   0x11489d6(%rip), %rsi     ; "_run"
    0x10acd4c62 <+153>: callq  *0xe7f728(%rip)           ; (void *)0x0000000109c15ac0: objc_msgSend
    0x10acd4c68 <+159>: movq   0xe7f729(%rip), %rbx      ; (void *)0x0000000109c12d20: objc_release
    0x10acd4c6f <+166>: movq   %r15, %rdi
    0x10acd4c72 <+169>: callq  *%rbx
    0x10acd4c74 <+171>: movq   %r14, %rdi
    0x10acd4c77 <+174>: callq  *%rbx
    0x10acd4c79 <+176>: xorl   %eax, %eax
    0x10acd4c7b <+178>: addq   $0x8, %rsp
    0x10acd4c7f <+182>: popq   %rbx
    0x10acd4c80 <+183>: popq   %r12
    0x10acd4c82 <+185>: popq   %r13
    0x10acd4c84 <+187>: popq   %r14
    0x10acd4c86 <+189>: popq   %r15
    0x10acd4c88 <+191>: popq   %rbp
    0x10acd4c89 <+192>: retq   
    0x10acd4c8a <+193>: leaq   0x11d4a37(%rip), %rdi     ; _UIApplicationLinkedOnVersionOnce
    0x10acd4c91 <+200>: leaq   0xe82d08(%rip), %rsi      ; __block_literal_global.1554
    0x10acd4c98 <+207>: callq  0x10b8f92d6               ; symbol stub for: dispatch_once
    0x10acd4c9d <+212>: jmp    0x10acd4c13               ; <+74>

1 个答案:

答案 0 :(得分:1)

当你点击&#34;球&#34;时,你会从其超级视图中删除该视图:

- (void)tapped:(UITapGestureRecognizer *)recognizer {
    //Delete tapped ball
    [recognizer.view willRemoveSubview:recognizer.view];
    [recognizer.view removeFromSuperview];
}

然而,那&#34;球&#34;还存在。在下一次长按时,您的代码会跳过创建球(因为它们都存在),但是在球创建方法中,您可以将它们添加到主视图中。当您的代码进入物理方法时,您尝试将冲突行为添加到不在层次结构中的视图。

你应该删除你的&#34;球&#34; (将它们设置为nil)从超级视图中删除它们,或者在下一次将它们重新添加为子视图时。

这是一种方式,虽然不是最好的......

- (void)tapped:(UITapGestureRecognizer *)recognizer {
    //Delete tapped ball
    [recognizer.view willRemoveSubview:recognizer.view];
    [recognizer.view removeFromSuperview];

    if (recognizer.view == _blueBall) {
        _blueBall = nil;
    } else if (recognizer.view == _orangeBall) {
        _orangeBall = nil;
    }
}