Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 有什么理由我可以';不能在UIView类外部初始化CALayer?_Iphone_Uiview_Calayer - Fatal编程技术网

Iphone 有什么理由我可以';不能在UIView类外部初始化CALayer?

Iphone 有什么理由我可以';不能在UIView类外部初始化CALayer?,iphone,uiview,calayer,Iphone,Uiview,Calayer,我一直在尝试在我正在开发的iPhone应用程序中将CALayers作为“精灵”使用。从我所读到的来看,这似乎是正确的做法 当我在UIView类中设置图层时,我能够使图层显示在屏幕上: NSLog(@“GameView initWithCoder”) 但是,当我尝试在UIView外部初始化CALayer时,我的应用程序崩溃: - (void)loadImage:(NSString*)fileName { NSLog(@"GamePiece loadImage"); NSArray* fil

我一直在尝试在我正在开发的iPhone应用程序中将CALayers作为“精灵”使用。从我所读到的来看,这似乎是正确的做法

当我在UIView类中设置图层时,我能够使图层显示在屏幕上: NSLog(@“GameView initWithCoder”)

但是,当我尝试在UIView外部初始化CALayer时,我的应用程序崩溃:

- (void)loadImage:(NSString*)fileName
{
  NSLog(@"GamePiece loadImage");
  NSArray* fileNameParts = [fileName componentsSeparatedByString:@"."];
  imageName = [[fileNameParts objectAtIndex:0] retain];
  NSString* ext = [fileNameParts objectAtIndex:1];

  NSString* imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:ext];
  image = [[UIImage alloc] initWithContentsOfFile:imagePath];

  layer = [CALayer layer];
  [layer setContents:(id)[image CGImage]];

  [layer setBounds:CGRectMake(0.0f, 0.0f, 32.0f, 32.0f)];
  [layer setPosition:CGPointMake(50.0f, 50.0f)];
  [layer setName:imageName];

  [fileNameParts release], fileNameParts = nil;
  [ext release], ext = nil;
}

很明显我做错了什么,但我不知道那会是什么。我已经阅读了《核心动画编程指南》和《iPhone应用程序编程指南》,但他们似乎并没有讨论如何初始化CALayer,只是顺便说一下

我只需要朝正确的方向轻轻推一下。在编写iPhone时,我对所学的其他知识都有了相当好的理解。我只是在图形、图层和动画方面遇到了一些问题


提前谢谢

您不拥有从
方法获得的层,因此您必须拥有所有权。在您的方法返回后的某个时间,层正在被释放,这将导致崩溃。要解决这个问题:

layer = [[CALayer layer] retain]; // now we explicitly take ownership of this layer
此外,不要忘记释放图层,因为您现在拥有它:

// in your dealloc method
[layer release];

您应该查看,以了解有关何时拥有对象以及您在内存管理方面的职责的更多详细信息。

Jason,非常感谢您的回复!然而,你的回答似乎对我问题的结果没有任何影响

实际上,答案“是”与内存管理有关的东西。不是层,而是调用ComponentSeparatedByString:后从NSArray获得的名称。如果我不发布NSArray,代码工作正常。因此,我需要在数组中创建NSString的副本,而不是使用数组中的对象

我不得不说,我没有像你建议的那样阅读Cocoa的内存管理编程指南。然而,我读过另外几本书,其中谈到了Cocoa中创建的对象的标准及其保留计数。我有一个公平的理解,但显然,还不如需要的好

我确实怀疑应该将字符串从数组中复制出来,但当它在UIView中工作时,我只是认为它是正确的。问题是,我并没有把它放在我的游戏物件里面


谢谢你至少让我看到了正确的方向!我对这个密码真是束手无策

要想做你想做的事,下面是你如何更改代码的方法。在
loadImage:
中,使用此行添加加载到
earth
层中的
UIImage

self.contents=image.CGImage

CALayers
有一个
contents
属性,您可以将该属性设置为
CGImage
,而无需麻烦地使用核心图形调用将图像绘制到图层的上下文中

然后在父级
UIView
子类中,您可以将
earth
添加到视图层次结构中,如下所示:

[self.layer addSublayer:earth]

请注意,
earth
本身就是一个
CALayer
,其内容是一个图像,因此我直接将其添加为一个子层。我总是忘记做的另一件事是设置层的
frame
属性。否则,其宽度和高度将为零,因此不会显示

在代码中创建了图层,但从未将图层添加到视图层次结构中。如果视图(类UIView)及其子视图存在树。树的根是[UIWindow mainwindow](注意UIWindow是
UIView
的一个子类。每个
UIView
都有一个
属性,类型为
CALayer
,它实际上保存了它的可见内容。
UIView
只是
CALayer
的一个包装器,用于添加触摸处理能力等功能

这里您缺少的一个重要思想是,要想在屏幕上看到任何东西,它必须是这个视图树的一部分,以UIWindow作为其根,并且所有视图都必须可见(即,将其
隐藏
属性设置为
)在顶层窗口和相关层之间。只有这样,层才会在屏幕上可见。因此,在代码中的某个地方,您需要通过调用
addSublayer:
将层添加为已可见部分的子层

在您的例子中,我假设地球是一个
CALayer
的实例,您在
加载映像:
方法中所做的是创建一个新的
CALayer
(调用
[CALayer layer]
)在
earth
层中,但您从未将该新层添加到任何内容中,因此它从未可见。您所做的是尝试将
earth
层添加到我假设的
UIView
层中,该层仍然没有任何内容

[[self layer]addSublayer:[earth layer]]


这一行的一个问题是,您似乎认为
地球
的一个属性。实际上
CALayer
的一个类方法,这是一个工厂方法,用于创建
CALayer
的新实例。这是令人困惑的,因为
[self layer]
实际上正在访问
UIView
实例的层属性。(我假设
self
引用
UIView
子类的实例。)

事实上,即使你很幸运,这个图层仍然是个问题。如果它是ivar,你必须保留它。至于文件名,我错过了。你实际上不必保留或复制它。只是不要发布它:)基本上,您只在功能期间使用的东西不需要主动管理,除非您创建了它们(alloc/copy/new)。你想留下来的东西需要积极管理(因此,如果你没有分配/复制/新建你自己)
layer = [[CALayer layer] retain]; // now we explicitly take ownership of this layer
// in your dealloc method
[layer release];