2012-09-29 2 views
3

애니메이션을 기반으로하는 응용 프로그램이 있습니다. 가장 효과적인 애니메이션 프로세서 (지연이 적고 메모리 관리가 가장 효율적)를 시도하고 검색 한 후 놀라운 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 파일입니다!

답변

2

downvoted받은 이유가 확실하지 않습니다. 귀하의 문제는 UIViewController 서브 클래스가 구현 된 loadView 함수를 가지고 있고 UI를 작성하는 데 의존한다는 것입니다. 뷰 컨트롤러의 경우이 함수는 .xib에서로드되지 않은 경우 뷰를 빌드하기 위해 자동으로 호출됩니다. 당신은 객체를 생성 한 후에 수동으로이 함수를 호출 해 볼 수 있습니다.

shouldAutorotateToInterfaceOrientation 기능도 UIViewController 기능이며, 너무 downvote에 대해, 확인되지 않은 UIView

+0

감사에서 호출되지 않습니다 유의하십시오. 좋아, 나는 그것을 수동으로 부르려고 노력할 것이다. –

+0

그래서 수동으로 호출하려고 시도했는데이 줄에서 어설 션이 실패하면 응용 프로그램이 중단됩니다. \t NSAssert (animationURLs, @ "animationURLs not defined"); . 어떻게해야합니까? –

+0

그건 꽤 명확한 오류입니다. 그것은 특정 요소에 의존하고, 당신은 그 요소를 정의하지 않았습니다. 'animationURLS'과'animationFrameDuration'을 설정해야합니다. – Dima