Mehrere UIView -Instanz funktioniert nicht
-
18-09-2019 - |
Frage
Ich habe die UIView -Unterklasse in einer Bounce -Klasse mit Beschleunigungsmesser. Diese Bounce -Klasse zeigt ein Bild an und verschiebt es auf dem Bildschirm. Wenn das iPhone -Gerät verschoben wird, springt dieses Bild auf dem Bildschirm.
Wenn ich mehrere Instanz erstelle, funktionieren nur die letzte Instanz richtig:
// in the MainViewController.m
Bounce *heart[100];
for(int i = 0; i < 10; i++) {
rx = (arc4random() % 300) + 10;
ry = (arc4random() % 300) + 10;
NSLog(@"random %d %d", rx, ry);
heart[i] = [[Bounce alloc] initWithPNG:@"Heart.png"
position:CGPointMake(rx, ry) size:CGSizeMake(64, 64)];
heart[i].velocity = CGPointMake(1.0, 1.0);
[self.view addSubview: heart[i]];
}
Dies ist die Bounce -Klasse:
//
// Bounce.h
// iMakeLove
//
// Created by Giovambattista Fazioli on 06/11/09.
// Copyright 2009 Saidmade srl. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface Bounce : UIView <UIAccelerometerDelegate> {
CGPoint position;
CGSize size;
CGPoint velocity;
NSTimer *objTimer;
NSString *pngName;
CGFloat bounce;
CGFloat gravity;
CGPoint acceleratedGravity;
CGPoint lastTouch;
CGPoint currentTouch;
BOOL dragging;
UIAccelerometer *accelerometer;
}
@property CGPoint position;
@property CGSize size;
@property CGPoint velocity;
@property(nonatomic,retain)NSString *pngName;
@property(nonatomic,retain)NSTimer *objTimer;
@property CGFloat bounce;
@property CGFloat gravity;
@property CGPoint acceleratedGravity;
@property CGPoint lastTouch;
@property CGPoint currentTouch;
@property BOOL dragging;
- (id)initWithPNG:(NSString*)imageName position:(CGPoint)p size:(CGSize)s;
- (void)update;
- (void)onTimer;
- (void)startPrevent;
@end
Implementierung:
//
// Bounce.m
// iMakeLove
//
// Created by Giovambattista Fazioli on 06/11/09.
// Copyright 2009 Saidmade srl. All rights reserved.
//
#import "Bounce.h"
@implementation Bounce
@synthesize position, size;
@synthesize objTimer;
@synthesize velocity;
@synthesize pngName;
@synthesize bounce;
@synthesize gravity, acceleratedGravity;
@synthesize lastTouch, currentTouch;
@synthesize dragging;
- (id)initWithPNG:(NSString*)imageName position:(CGPoint)p size:(CGSize)s {
if (self = [super initWithFrame:CGRectMake(p.x, p.y, s.width, s.height)]) {
[self setPngName:imageName];
[self setPosition:p];
[self setSize:s];
[self setBackgroundColor:[UIColor clearColor]];
// Set default gravity and bounce
[self setBounce:-0.9f];
[self setGravity:0.5f];
[self setAcceleratedGravity:CGPointMake(0.0, gravity)];
[self setDragging:NO];
UIImageView *prezzie = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, s.width, s.height)];
prezzie.image = [UIImage imageNamed:imageName];
[self addSubview:prezzie];
[prezzie release];
self.accelerometer = [UIAccelerometer sharedAccelerometer];
self.accelerometer.delegate = self;
}
return self;
}
- (void)startPrevent {
if (objTimer == nil) {
objTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
}
}
- (void)update {
[self setNeedsDisplay];
if(dragging) return;
velocity.x += acceleratedGravity.x;
velocity.y += acceleratedGravity.y;
position.x += velocity.x;
position.y += velocity.y;
if(position.x + size.width >= 320.0) {
position.x = 320.0 - size.width;
velocity.x *= bounce;
} else if(position.x <= 0.0) {
velocity.x *= bounce;
}
if(position.y + size.height >= 480.0) {
position.y = 480.0 - size.height;
velocity.y *= bounce;
} else if(position.y <= 0.0) {
velocity.y *= bounce;
}
self.frame = CGRectMake(position.x, position.y, size.width, size.height);
}
- (void)onTimer {
[self update];
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
/* EVENTS */
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
acceleratedGravity.x = acceleration.x * gravity;
acceleratedGravity.y = -acceleration.y * gravity;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// First, lets check to make sure the timer has been initiated
if (objTimer == nil) {
objTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
}
UITouch *touch = [touches anyObject];
[self setCurrentTouch:[touch locationInView:self]];
CGFloat dx = currentTouch.x - position.x;
CGFloat dy = currentTouch.y - position.y;
CGFloat dist = sqrt(dx * dx + dy * dy);
if(dist < size.width) {
[self setVelocity:CGPointMake(0.0, 0.0)];
[self setDragging:YES];
}
[self setLastTouch:currentTouch];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
[self setCurrentTouch:[touch locationInView:self]];
[self setDragging:YES];
[self setVelocity:CGPointMake(currentTouch.x - lastTouch.x, currentTouch.y - lastTouch.y)];
[self setLastTouch:currentTouch];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self setDragging:NO];
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (void)dealloc {
[super dealloc];
}
@end
Kannst du mir helfen?
Lösung
Das ist, weil self.accelerometer.delegate = self;
ändert die sharedAccelerometer
'S -Delegierter und nur die letzte Zuordnung hat einen Effekt.
Andere Tipps
Ich glaube, dass nur die vorderste Sicht die Beschleunigungsnachrichten erhalten. Möglicherweise möchten Sie, dass die Accelrometer -Nachrichten stattdessen an Ihren ViewController gesendet werden.
Was ich hier tun könnte. (Es ist vielleicht nicht das Beste, was langfristig das Beste ist, aber das unmittelbare Problem behebt) ist Folgendes:
Ich würde beschleunigte Schwerkraft zu einer statischen Variablen machen, die unter allen Fällen von Sprung geteilt wurde. Dies macht für mich zu, weil in der realen Welt (die, die wir simulieren) beschleunigte Schwerkraft für alle Hüpfer gleich wäre. (Ich würde Bounce auch in so etwas wie BouncingView umbenennen). Ich würde über einige Klassenmethoden auf diese Variable zugreifen. Außerdem würde ich das Beschleunigungsmesser gemeinsam genutzt und seine Delegate -Methode, eine Klassenmethode, haben. Setzen Sie dieses Zeug in Ihre Klasse und es sollte funktionieren: (Ich würde es testen, aber mein Entwicklungsgerät ist im Apple Store repariert.) Außerdem gibt es einige Syntaxfehler in dem von Ihnen geposteten Beispielcode.
static CGCGPoint acceleratedGravity;
static UIAccelerometer *accelerometer;
-(void) init {
/* Everything Else */
self.accelerometer = [UIAccelerometer sharedAccelerometer];
self.accelerometer.delegate = self;
/*Everything Else */
}
+(CGPoint) acceleratedGravity {
return acceleratedGravity;
}
+(void) setAcceleratedGravity:(CGPoint) _acceleratedGravity {
acceleratedGravity = _acceleratedGravity;
}
+ (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
acceleratedGravity.x = acceleration.x * gravity;
acceleratedGravity.y = -acceleration.y * gravity;
}