我正在制作一个球程序,您可以在长按手势上向超级视图添加球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>
答案 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;
}
}