애니메이션을 기반으로하는 응용 프로그램이 있습니다. 가장 효과적인 애니메이션 프로세서 (지연이 적고 메모리 관리가 가장 효율적)를 시도하고 검색 한 후 놀라운 PNGAnimator (http://www.modejong.com/iPhone/)를 발견했습니다. 웃긴 점은 크기 때문에 JPEG를 사용하고 있지만 문제가되지 않는다는 것입니다.UIViewController 코드를 UIView로 변환
문제는 클래스 자체가 UIViewController의 하위 클래스이며,이를 rootViewController에 추가하면 새 뷰 컨트롤러가 겹치기 때문에 모든 인터페이스 요소 (버튼 ...)가 그 아래에 숨겨집니다.
그 이유는 어떻게 든 코드를 UIView의 하위 클래스로 변환하고 싶습니다. (그래서 단추를 추가 할 수 있습니다.) 코드를 직접 변환하려고 시도했지만 응용 프로그램이 애니메이션 호출시 충돌합니다. 코드에서 UIView로 변경해야하는 내용을 알려주십시오.
예를 들어 .h 파일에서 UIView로 변경 한 다음 .m 파일에서 자체 self.view 참조를 변경하려고했습니다. 그런 다음 내 루트보기 컨트롤러에서 하위보기로 추가하지만 그 표시되지 및 충돌 중 하나를. 여기
//
// ImageAnimatorViewController.h
// PNGAnimatorDemo
//
// Created by Moses DeJong on 2/5/09.
//
#import <UIKit/UIKit.h>
#define ImageAnimator15FPS (1.0/15)
#define ImageAnimator12FPS (1.0/12)
#define ImageAnimator25FPS (1.0/24)
#define ImageAnimator18FPS (1.0/18)
#define ImageAnimatorDidStartNotification @"ImageAnimatorDidStartNotification"
#define ImageAnimatorDidStopNotification @"ImageAnimatorDidStopNotification"
@class AVAudioPlayer;
@interface ImageAnimatorViewController : UIViewController {
@public
NSArray *animationURLs;
NSTimeInterval animationFrameDuration;
NSInteger animationNumFrames;
NSInteger animationRepeatCount;
UIImageOrientation animationOrientation;
NSURL *animationAudioURL;
AVAudioPlayer *avAudioPlayer;
@private
UIImageView *imageView;
NSArray *animationData;
NSTimer *animationTimer;
NSInteger animationStep;
NSTimeInterval animationDuration;
NSTimeInterval lastReportedTime;
}
// public properties
@property (nonatomic, copy) NSArray *animationURLs;
@property (nonatomic, assign) NSTimeInterval animationFrameDuration;
@property (nonatomic, readonly) NSInteger animationNumFrames;
@property (nonatomic, assign) NSInteger animationRepeatCount;
@property (nonatomic, assign) UIImageOrientation animationOrientation;
@property (nonatomic, retain) NSURL *animationAudioURL;
@property (nonatomic, retain) AVAudioPlayer *avAudioPlayer;
@property (nonatomic, assign) CGRect viewCGRect;
// private properties
@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, copy) NSArray *animationData;
@property (nonatomic, retain) NSTimer *animationTimer;
@property (nonatomic, assign) NSInteger animationStep;
@property (nonatomic, assign) NSTimeInterval animationDuration;
+ (ImageAnimatorViewController*) imageAnimatorViewController;
- (void) startAnimating;
- (void) stopAnimating;
- (BOOL) isAnimating;
- (void) animationShowFrame: (NSInteger) frame;
+ (NSArray*) arrayWithNumberedNames:(NSString*)filenamePrefix
rangeStart:(NSInteger)rangeStart
rangeEnd:(NSInteger)rangeEnd
suffixFormat:(NSString*)suffixFormat;
+ (NSArray*) arrayWithResourcePrefixedURLs:(NSArray*)inNumberedNames;
@end
그리고하는 .m 파일 :
//
// ImageAnimatorViewController.m
// PNGAnimatorDemo
//
// Created by Moses DeJong on 2/5/09.
//
#import "ImageAnimatorViewController.h"
#import <QuartzCore/QuartzCore.h>
#import <AVFoundation/AVAudioPlayer.h>
@implementation ImageAnimatorViewController
@synthesize animationURLs, animationFrameDuration, animationNumFrames, animationRepeatCount,
imageView, animationData, animationTimer, animationStep, animationDuration, animationOrientation, viewCGRect;
@synthesize animationAudioURL, avAudioPlayer;
- (void)dealloc {
// This object can't be deallocated while animating, this could
// only happen if user code incorrectly dropped the last ref.
NSAssert([self isAnimating] == FALSE, @"dealloc while still animating");
self.animationURLs = nil;
self.imageView = nil;
self.animationData = nil;
self.animationTimer = nil;
[super dealloc];
}
+ (ImageAnimatorViewController*) imageAnimatorViewController
{
return [[[ImageAnimatorViewController alloc] init] autorelease];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
UIView *myView = [[UIView alloc] initWithFrame:viewCGRect];
[myView autorelease];
self.view = myView;
/*UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
[myView autorelease];
self.view = myView;
// FIXME: Additional Supported Orientations
if (animationOrientation == UIImageOrientationUp) {
// No-op
} else if (animationOrientation == UIImageOrientationLeft) {
// 90 deg CCW
//[self rotateToLandscape];
} else if (animationOrientation == UIImageOrientationRight) {
// 90 deg CW
//[self rotateToLandscapeRight];
} else {
NSAssert(FALSE,@"Unsupported animationOrientation");
}
*/
// Foreground animation images
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:self.view.frame];
[myImageView autorelease];
self.imageView = myImageView;
// Animation data should have already been loaded into memory as a result of
// setting the animationURLs property
NSAssert(animationURLs, @"animationURLs was not defined");
NSAssert([animationURLs count] > 1, @"animationURLs must include at least 2 urls");
NSAssert(animationFrameDuration, @"animationFrameDuration was not defined");
// Load animationData by reading from animationURLs
NSMutableDictionary *dataDict = [NSMutableDictionary dictionaryWithCapacity:[animationURLs count]];
NSMutableArray *muArray = [NSMutableArray arrayWithCapacity:[animationURLs count]];
for (NSURL* aURL in animationURLs) {
NSString *urlKey = aURL.path;
NSData *dataForKey = [dataDict objectForKey:urlKey];
if (dataForKey == nil) {
dataForKey = [NSData dataWithContentsOfURL:aURL];
NSAssert(dataForKey, @"dataForKey");
[dataDict setObject:dataForKey forKey:urlKey];
}
[muArray addObject:dataForKey];
}
self.animationData = [NSArray arrayWithArray:muArray];
int numFrames = [animationURLs count];
float duration = animationFrameDuration * numFrames;
self->animationNumFrames = numFrames;
self.animationDuration = duration;
[self.view addSubview:imageView];
// Display first frame of image animation
self.animationStep = 0;
[self animationShowFrame: animationStep];
self.animationStep = animationStep + 1;
if (animationAudioURL != nil) {
AVAudioPlayer *avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:animationAudioURL
error:nil];
[avPlayer autorelease];
NSAssert(avPlayer, @"AVAudioPlayer could not be allocated");
self.avAudioPlayer = avPlayer;
[avAudioPlayer prepareToPlay];
}
}
// Create an array of file/resource names with the given filename prefix,
// the file names will have an integer appended in the range indicated
// by the rangeStart and rangeEnd arguments. The suffixFormat argument
// is a format string like "%02i.png", it must format an integer value
// into a string that is appended to the file/resource string.
//
// For example: [createNumberedNames:@"Image" rangeStart:1 rangeEnd:3 rangeFormat:@"%02i.png"]
//
// returns: {"Image01.png", "Image02.png", "Image03.png"}
+ (NSArray*) arrayWithNumberedNames:(NSString*)filenamePrefix
rangeStart:(NSInteger)rangeStart
rangeEnd:(NSInteger)rangeEnd
suffixFormat:(NSString*)suffixFormat
{
NSMutableArray *numberedNames = [[NSMutableArray alloc] initWithCapacity:40];
for (int i = rangeStart; i <= rangeEnd; i++) {
NSString *suffix = [NSString stringWithFormat:suffixFormat, i];
NSString *filename = [NSString stringWithFormat:@"%@%@", filenamePrefix, suffix];
[numberedNames addObject:filename];
}
NSArray *newArray = [NSArray arrayWithArray:numberedNames];
[numberedNames release];
return newArray;
}
// Given an array of resource names (as returned by arrayWithNumberedNames)
// create a new array that contains these resource names prefixed as
// resource paths and wrapped in a NSURL object.
+ (NSArray*) arrayWithResourcePrefixedURLs:(NSArray*)inNumberedNames
{
NSMutableArray *URLs = [[NSMutableArray alloc] initWithCapacity:[inNumberedNames count]];
NSBundle* appBundle = [NSBundle mainBundle];
for (NSString* path in inNumberedNames) {
NSString* resPath = [appBundle pathForResource:path ofType:nil];
NSURL* aURL = [NSURL fileURLWithPath:resPath];
[URLs addObject:aURL];
}
NSArray *newArray = [NSArray arrayWithArray:URLs];
[URLs release];
return newArray;
}
// Invoke this method to start the animation
- (void) startAnimating
{
self.animationTimer = [NSTimer timerWithTimeInterval: animationFrameDuration
target: self
selector: @selector(animationTimerCallback:)
userInfo: NULL
repeats: TRUE];
[[NSRunLoop currentRunLoop] addTimer: animationTimer forMode: NSDefaultRunLoopMode];
animationStep = 0;
if (avAudioPlayer != nil)
[avAudioPlayer play];
// Send notification to object(s) that regestered interest in a start action
[[NSNotificationCenter defaultCenter]
postNotificationName:ImageAnimatorDidStartNotification
object:self];
}
// Invoke this method to stop the animation, note that this method must not
// invoke other methods and it must cancel any pending callbacks since
// it could be invoked in a low-memory situation or when the object
// is being deallocated. Invoking this method will not generate a
// animation stopped notification, that callback is only invoked when
// the animation reaches the end normally.
- (void) stopAnimating
{
if (![self isAnimating])
return;
[animationTimer invalidate];
self.animationTimer = nil;
animationStep = animationNumFrames - 1;
[self animationShowFrame: animationStep];
if (avAudioPlayer != nil) {
[avAudioPlayer stop];
avAudioPlayer.currentTime = 0.0;
self->lastReportedTime = 0.0;
}
// Send notification to object(s) that regestered interest in a stop action
[[NSNotificationCenter defaultCenter]
postNotificationName:ImageAnimatorDidStopNotification
object:self];
}
- (BOOL) isAnimating
{
return (animationTimer != nil);
}
// Invoked at framerate interval to implement the animation
- (void) animationTimerCallback: (NSTimer *)timer {
if (![self isAnimating])
return;
NSTimeInterval currentTime;
NSUInteger frameNow;
if (avAudioPlayer == nil) {
self.animationStep += 1;
// currentTime = animationStep * animationFrameDuration;
frameNow = animationStep;
} else {
currentTime = avAudioPlayer.currentTime;
frameNow = (NSInteger) (currentTime/animationFrameDuration);
}
// Limit the range of frameNow to [0, SIZE-1]
if (frameNow == 0) {
frameNow = 0;
} else if (frameNow >= animationNumFrames) {
frameNow = animationNumFrames - 1;
}
[self animationShowFrame: frameNow];
// animationStep = frameNow + 1;
if (animationStep >= animationNumFrames) {
[self stopAnimating];
// Continue to loop animation until loop counter reaches 0
if (animationRepeatCount > 0) {
self.animationRepeatCount = animationRepeatCount - 1;
[self startAnimating];
}
}
}
// Display the given animation frame, in the range [1 to N]
// where N is the largest frame number.
- (void) animationShowFrame: (NSInteger) frame {
if ((frame >= animationNumFrames) || (frame < 0))
return;
NSData *data = [animationData objectAtIndex:frame];
UIImage *img = [UIImage imageWithData:data];
imageView.image = img;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.animationRepeatCount = 0;
[self stopAnimating];
}
@end
어떤 조언을 주셔서 대단히 감사합니다
다음은 .H 파일입니다!
감사에서 호출되지 않습니다 유의하십시오. 좋아, 나는 그것을 수동으로 부르려고 노력할 것이다. –
그래서 수동으로 호출하려고 시도했는데이 줄에서 어설 션이 실패하면 응용 프로그램이 중단됩니다. \t NSAssert (animationURLs, @ "animationURLs not defined"); . 어떻게해야합니까? –
그건 꽤 명확한 오류입니다. 그것은 특정 요소에 의존하고, 당신은 그 요소를 정의하지 않았습니다. 'animationURLS'과'animationFrameDuration'을 설정해야합니다. – Dima