Ios 在使用一系列图像制作动画时,我应该考虑iPad4的哪些限制?

Ios 在使用一系列图像制作动画时,我应该考虑iPad4的哪些限制?,ios,ipad,animation,uiimageview,Ios,Ipad,Animation,Uiimageview,我想做的是:我想要一个能显示全屏图像的应用程序,并通过滑动UISlider使图像具有动画效果。更改滑块值将通过创建动画的阵列图像进行排序。此动画是转盘上的单个角色。当滑块更改值时,角色看起来好像正在围绕旋转台旋转 这个项目是一个3D艺术家的作品集。这位艺术家给了我一系列180幅以全屏视网膜分辨率呈现的人物图像。他还向be提供了另外180张非视网膜全屏分辨率的图像。这个想法是,当有人在视网膜iPad上从任何角度观看他的角色时,他们可以使用UI开关在视网膜和非视网膜显示器之间切换。下面的代码在模拟器

我想做的是:我想要一个能显示全屏图像的应用程序,并通过滑动UISlider使图像具有动画效果。更改滑块值将通过创建动画的阵列图像进行排序。此动画是转盘上的单个角色。当滑块更改值时,角色看起来好像正在围绕旋转台旋转

这个项目是一个3D艺术家的作品集。这位艺术家给了我一系列180幅以全屏视网膜分辨率呈现的人物图像。他还向be提供了另外180张非视网膜全屏分辨率的图像。这个想法是,当有人在视网膜iPad上从任何角度观看他的角色时,他们可以使用UI开关在视网膜和非视网膜显示器之间切换。下面的代码在模拟器上运行良好

然而,当在iPad4上运行此代码时,它会工作一段时间,然后我会收到一条内存警告。然后它崩溃了。我假设,对于iPad4来说,如果有人想移动滑块,那么多这样大小的图像显示的速度就太快了

我很好奇在处理这样的图像时应该考虑哪些限制。180张图片太多了吗?合理的数额是多少?有没有更有效的方法来产生我想要的结果?我没有采用猜测和检查的方法来判断有多少图像不会导致崩溃,而是认为有人可能对我的问题有一些有用的见解

@implementation RBViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

_imageDisplay.image = [UIImage imageNamed:@"HyperReal_0.png"];

_arrayRetina = [[NSMutableArray alloc] initWithCapacity:180];
_arrayNormal = [[NSMutableArray alloc] initWithCapacity:180];

for(int i = 0; i < 179; i++)
{
    NSString *myImageString = [[NSString alloc] initWithFormat:@"HyperReal_%i.png", i];
    UIImage *myImageGraphic = [UIImage imageNamed:myImageString];
    [_arrayRetina addObject:myImageGraphic];
}

for(int i = 0; i < 179; i++)
{
 NSString *myImageString = [[NSString alloc] initWithFormat:@"lameHyperReal_%i.png", i];
    UIImage *myImageGraphic = [UIImage imageNamed:myImageString];
    [_arrayNormal addObject:myImageGraphic];
}
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)switchButton:(id)sender {

if (_switchOnForRetina.isOn == YES)
{
    _imageDisplay.image = [_arrayRetina objectAtIndex:_sliderBar.value];
}
else
    _imageDisplay.image = [_arrayNormal objectAtIndex:_sliderBar.value];

}

- (IBAction)changeSlider:(id)sender {

if (_switchOnForRetina.isOn == YES)
{

_imageDisplay.image = [_arrayRetina objectAtIndex:_sliderBar.value];
}
else

_imageDisplay.image = [_arrayNormal objectAtIndex:_sliderBar.value];
}



@end
@实现RBViewController
-(无效)viewDidLoad
{
[超级视图下载];
//加载视图后,通常从nib执行任何其他设置。
_imageDisplay.image=[UIImage ImageName:@“HyperReal_0.png”];
_arrayRetina=[[NSMUTABLARY alloc]INITWITH容量:180];
_arrayNormal=[[NSMutableArray alloc]initWithCapacity:180];
对于(int i=0;i<179;i++)
{
NSString*myImageString=[[NSString alloc]initWithFormat:@“HyperReal_%i.png”,i];
UIImage*myImageGraphic=[UIImage ImageName:myImageString];
[_ArrayRetinaaddObject:myImageGraphic];
}
对于(int i=0;i<179;i++)
{
NSString*myImageString=[[NSString alloc]initWithFormat:@“lameHyperReal_u%i.png”,i];
UIImage*myImageGraphic=[UIImage ImageName:myImageString];
[_ArrayNormaladdObject:myImageGraphic];
}
}
-(无效)未收到记忆警告
{
[超级记忆警告];
//处置所有可以重新创建的资源。
}
-(iAction)开关按钮:(id)发送器{
如果(_switchOnForRetina.isOn==是)
{
_imageDisplay.image=[\u arrayRetina objectAtIndex:\u sliderBar.value];
}
其他的
_imageDisplay.image=[\u arrayNormal objectAtIndex:\u sliderBar.value];
}
-(iAction)更改滑块:(id)发送方{
如果(_switchOnForRetina.isOn==是)
{
_imageDisplay.image=[\u arrayRetina objectAtIndex:\u sliderBar.value];
}
其他的
_imageDisplay.image=[\u arrayNormal objectAtIndex:\u sliderBar.value];
}
@结束

在滑块的连续UIContolEventValueChanged事件期间,您不能实例化要显示的当前图像,而不是一次将所有180个图像加载到一个数组中吗

创建滑块

UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 155, 20)];
slider.continuous = YES;
slider.value = 0.0f;
slider.minimumValue = 0.0f;
slider.minimumValue = 179.0f;
[slider addTarget:self action:@selector(handleContinuousSlider:) forControlEvents:UIControlEventValueChanged];
处理它的持续更改事件

- (void)handleContinuousSlider:(UISlider *)slider {
    //create a UIImage with file name that makes the current integer value of the slider
    NSString *myImageString = [[NSString alloc] initWithFormat:@"HyperReal_%i.png", slider.value];
    UIImage *myImageGraphic = [UIImage imageNamed:myImageString];

   //I assume this is a UIImageView
   [_imageDisplay setImage:myImageGraphic];

   [myImageGraphic release];
}

您不能在滑块的连续UIContoleEventValueChanged事件期间实例化要显示的当前图像,而不是一次将所有180个图像加载到一个数组中吗

创建滑块

UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 155, 20)];
slider.continuous = YES;
slider.value = 0.0f;
slider.minimumValue = 0.0f;
slider.minimumValue = 179.0f;
[slider addTarget:self action:@selector(handleContinuousSlider:) forControlEvents:UIControlEventValueChanged];
处理它的持续更改事件

- (void)handleContinuousSlider:(UISlider *)slider {
    //create a UIImage with file name that makes the current integer value of the slider
    NSString *myImageString = [[NSString alloc] initWithFormat:@"HyperReal_%i.png", slider.value];
    UIImage *myImageGraphic = [UIImage imageNamed:myImageString];

   //I assume this is a UIImageView
   [_imageDisplay setImage:myImageGraphic];

   [myImageGraphic release];
}

我不太清楚为什么需要在视网膜和非视网膜之间进行编程切换,因为@2x处理得非常好,但我会假设有一个我不熟悉的用例,并将其保留

关于内存使用,我们正在开发一个具有类似功能的应用程序,我们的解决方案是用字符串填充一个数组,该字符串引用所有单个帧的图像名称(或文件路径)。在本例中,您将存储引用
myImageString
,而不是
myImageGraphic

然后,当您拖动滑块时,您会使用如下内容:

- (IBAction)changeSlider:(id)sender
{
    if (_switchOnForRetina.isOn == YES)
        _imageDisplay.image = [UIImage imageNamed:[_arrayRetina objectAtIndex:_sliderBar.value]];
    else
        _imageDisplay.image = [UIImage imageNamed:[_arrayNormal objectAtIndex:_sliderBar.value]];
}
还有一点,我们使用
imageWithContentsOfFile
,这是因为按照的内存使用率较低,不过
imageNamed
的缓存在这种情况下可能会有所帮助

编辑:

正如麦克拉格所指出的,上述方法仅在润色时改变。下面是我正在使用的一个示例,尽管我在UIView上使用
uigestureRecognitizer
向方法发送百分比,而不是依赖滑块

- (void)dragPosition:(float)myPercent
{
    NSInteger index = (self.images.count - 1) * myPercent;
    NSString *imageName = [self.images objectAtIndex:index];
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
    self.image = [UIImage imageWithContentsOfFile:imagePath];
}

希望这有帮助

我不太清楚为什么需要在视网膜和非视网膜之间进行编程切换,因为@2x处理得非常好,但我假设有一个我不熟悉的用例,我就不谈了

关于内存使用,我们正在开发一个具有类似功能的应用程序,我们的解决方案是用字符串填充一个数组,该字符串引用所有单个帧的图像名称(或文件路径)。在本例中,您将存储引用
myImageString
,而不是
myImageGraphic

然后,当您拖动滑块时,您会使用如下内容:

- (IBAction)changeSlider:(id)sender
{
    if (_switchOnForRetina.isOn == YES)
        _imageDisplay.image = [UIImage imageNamed:[_arrayRetina objectAtIndex:_sliderBar.value]];
    else
        _imageDisplay.image = [UIImage imageNamed:[_arrayNormal objectAtIndex:_sliderBar.value]];
}
还有一点,我们使用
imageWithContentsOfFile
,这是因为按照的内存使用率较低,不过
imageNamed
的缓存在这种情况下可能会有所帮助

编辑:

正如麦克拉格所指出的,上述方法仅在润色时改变。下面是我正在使用的一个示例,尽管我在UIView上使用
uigestureRecognitizer
向方法发送百分比,而不是依赖滑块

- (void)dragPosition:(float)myPercent
{
    NSInteger index = (self.images.count - 1) * myPercent;
    NSString *imageName = [self.images objectAtIndex:index];
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpg"];
    self.image = [UIImage imageWithContentsOfFile:imagePath];
}

希望这有帮助

预缓冲内存成本大致如下:

((2048*1536*4+1024*768*4)*180)/1024/1024/1024=2.63671875千兆字节

即使有一些地下优化正在进行,你的iPad也没有足够的内存来安全运行该程序

作为解决崩溃问题的方法,不要预加载所有图像,而只加载所需的图像

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [ self changeSlider: nil ];
}


- (IBAction)changeSlider:(id)sender {

    if (_switchOnForRetina.isOn == YES)
    {
        _imageDisplay.image =   nil;
        NSString*   pResourcePath   =   [ [ NSBundle mainBundle ] pathForResource: [ NSString stringWithFormat: @"HyperReal_%i", ( int )_sliderBar.value ] ofType: @"png" ];
        _imageDisplay.image =   [ UIImage imageWithContentsOfFile: pResourcePath  ];
    }
    else
    {
        _imageDisplay.image =   nil;
        NSString*   pResourcePath   =   [ [ NSBundle mainBundle ] pathForResource: [ NSString stringWithFormat: @"lameHyperReal_%i", ( int )_sliderBar.value ] ofType: @"png" ];
        _imageDisplay.image =   [ UIImage imageWithContentsOfFile: pResourcePath ];
    }
}
贝特