2017-02-21 37 views
0

Я делаю программу для мяча, в которой вы добавляете шар UIView subview в супервизор на жесте Long Press. Нажатие на просмотр удаляет его из супервизора.iOS - Повторное добавление subview после удаления всех подземелий

Добавление всех представлений отлично работает и повторное добавление просмотров отлично работает, так как в супервизоре есть как минимум один вид. Однако, как только все подпункты будут удалены, длинное нажатие, как предполагается, снова добавит первое подвью, но вместо этого программа выключается.

Я получаю только одно сообщение о выпуске в одном из потоков, что заставляет меня думать, что это проблема 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> 
+0

Если вы хотите, чтобы люди читали ваш вопрос, пожалуйста, не оставляйте ненужный код (например, 'updateView',' didReceiveMemoryWarning'). Выяснение минимального количества кода, для которого происходит ваша проблема, также может помочь вам отследить основную причину. Остается ли проблема, если вы удалите метод «физика» или метод «ballDragged» (или их части)? Если нет, не включайте их. –

+0

Улучшено, но действительно ли настройка цвета шарика и т. Д. Влияет на поведение? Если нет, удалите эти методы. Удалите все свойства, которые не связаны с проблемой. Продолжайте движение, пока не получите минимальный код, который показывает проблему. Возможно, вам будет полезно создать новый временный проект для изучения этого. –

ответ

1

Когда вы дважды нажмите на «мяч», вы извлекаете эту точку зрения из его supiewiew:

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

Однако этот «шарик» все еще остается ц. При следующем длинном нажатии ваш код пропускает создание шаров (потому что они оба существуют), но в методе создания шара вы добавляете их в основной вид. Когда ваш код переходит в физический метод, вы пытаетесь добавить поведение столкновения в представление, которое не находится в иерархии.

Вы должны либо удалить свои «шары» (установить их на нуль), когда вы удалите их из своих супервизоров, либо повторно добавьте их в виде подпунктов в следующий раз.

Это один из способов, хотя и не самые лучшие ...

- (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; 
    } 
} 
+0

Спасибо. Я на самом деле пытался использовать '_orangeBall = nil', но без условий if, и это не помогло, но это отлично поработало. Мой код требует много рефакторинга, но моя главная цель - это функциональность прямо сейчас. Еще новичок в Objective-C. Спасибо за помощь! –