هل هناك سبب لا أستطيع تهيئة CALayer خارج فئة UIView؟
سؤال
ولقد سعيت لنا CALayers ب "العفاريت" في تطبيق اي فون أعمل على. من ما كانت القراءة، والذي يبدو مثل الشيء الصحيح للقيام به هنا.
عند I إعداد طبقة داخل فئة UIView وأنا قادرة على الحصول على طبقة لتظهر على الشاشة: NSLog (@ "GameView initWithCoder")؛
NSString* imagePath = [[NSBundle mainBundle] pathForResource:@"earth" ofType:@"png"];
earthImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
earthLayer = [CALayer layer];
[earthLayer setContents:(id)[earthImage CGImage]];
[earthLayer setBounds:CGRectMake(0, 0, 32, 32)];
[earthLayer setPosition:CGPointMake(50, 50)];
[earthLayer setName:@"earth"];
[[self layer] addSublayer:earthLayer];
ولكن عندما أحاول تهيئة CALayer خارج UIView، تعطل التطبيق الخاص بي:
- (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;
}
NSLog(@"GameView initWithCoder");
earth = [[GamePiece alloc] init];
[earth loadImage:@"earth.png"];
[[self layer] addSublayer:[earth layer]];
ومن الواضح أنني أفعل شيئا خاطئا هنا، ولكن أنا لا أعرف ما سيكون. لقد قرأت البرمجة الأساسية الرسوم المتحركة دليل وكذلك دليل البرمجة تطبيق اي فون، لكنها في الحقيقة لا يبدو أن الحديث عن كيفية تهيئة CALayer بخلاف بشكل عابر.
وأنا في حاجة الى تنبيه لطيف في الاتجاه الصحيح. لقد تم الحصول على فهم جيد جدا عن كل شيء آخر لقد تعلمت عندما يتعلق الأمر برمجة فون. أنا مجرد وجود بعض القضايا مع الرسومات، الطبقات والرسوم المتحركة.
ويرجع الفضل في ذلك مسبقا!
المحلول
وأنت لا تملك طبقة التي تحصل عليها من طريقة layer
، لذلك عليك أن تأخذ الملكية. في وقت ما بعد إرجاع الأسلوب الخاص بك، ويتم deallocated طبقة والذي يسبب تحطم الخاصة بك. لعلاج هذا:
layer = [[CALayer layer] retain]; // now we explicitly take ownership of this layer
وأيضا، لا ننسى للافراج عن طبقة وبما انك تملك ذلك الآن:
// in your dealloc method
[layer release];
ويجب عليك مراجعة دليل البرمجة إدارة الذاكرة للكاكاو أ > لمزيد من التفاصيل حول عندما كنت تملك الأشياء وما مسؤولياتكم وفيما يتعلق بإدارة الذاكرة.
نصائح أخرى
وجيسون، شكرا جزيلا للرد! ومع ذلك إجابتك لا يبدو أن لديها أي تأثير على نتائج مشكلتي.
والحقيقة أن الإجابة "هي" شيء متعلق إدارة الذاكرة. لا لطبقة، ولكن اسم حصلت عليه من NSArray بعد استدعاء componentsSeparatedByString :. إذا كنت لا افراج عن NSArray، رمز يعمل بشكل جيد. لذلك أنا بحاجة لجعل نسخة من NSString داخل مجموعة بدلا من استخدام الكائن في صفيف.
ويجب أن أقول أنني لم أقرأ دليل البرمجة إدارة الذاكرة لالكاكاو كما اشرتم. ومع ذلك، لقد قرأت العديد من الكتب الأخرى التي تحدثت عن المعيار المستخدم في الكاكاو للكائنات التي تم إنشاؤها والاحتفاظ التهم بهم. لدي فهم عادلة، ولكن على ما يبدو، ليست جيدة حسب الحاجة حتى الان.
وأنا حقا كان الشك بأنني يجب نسخ سلسلة من مجموعة، ولكن عندما عملت في UIView، وأنا مجرد افتراض أنه كان محقا. المشكلة كانت، وأنا لم يحافظ عليه مثل أنا داخل الكائن GamePiece بلدي.
وشكرا لك على الأقل الحصول على لي أن ننظر في الاتجاه الصحيح! كنت حقا في الذكاء مع نهاية هذا الرمز.
لتفعل ما تريد، وهنا هو كيف يمكن تغيير التعليمات البرمجية. في loadImage:
استخدام هذا الخط لإضافة UIImage
الذي قمت بتحميله في طبقة earth
:
وself.contents = image.CGImage؛
اقتباس فقرة> وCALayers
تحتوي على خاصية contents
التي يمكنك تعيين إلى CGImage
بدلا من المرور عبر عناء باستخدام الأساسية الرسومات يدعو لرسم الصورة في سياقها الطبقة.
وبعد ذلك في فئة فرعية UIView
الأم يمكنك إضافة earth
إلى التسلسل الهرمي عرض مثل هذا:
[self.layer addSublayer: الأرض]؛
اقتباس فقرة> لاحظ أن earth
هو في حد ذاته CALayer
مع صورة كما محتوياته ذلك أود أن أضيف مباشرة كما طبقة فرعية. يتم تعيين الشيء الآخر أنا دائما ننسى أن تفعل خاصية frame
الطبقة. خلاف ذلك العرض والارتفاع سوف يكون صفرا وذلك لن تظهر.
في التعليمات البرمجية قمت بإنشاء طبقة لكن أبدا أضاف طبقة الخاصة بك إلى التسلسل الهرمي الرأي. هناك شجرة إذا آراء (الطبقة UIView) وsubviews بهم. جذر الشجرة [UIWindow mainwindow] (لاحظ أن UIWindow هو فئة فرعية من UIView
. كل UIView
له خاصية layer
من نوع CALayer
الذي يحمل في الواقع محتواه مرئية. UIView
هو مجرد التفاف حول CALayer
لإضافة أشياء مثل قدرة التعامل مع اللمس .
والفكرة الهامة التي مفقودة هنا هي أن أي شيء لتكون مرئية على الشاشة يجب أن يكون جزءا من هذه الشجرة وجهات النظر مع UIWindow كجذر وجميع وجهات النظر يجب أن تكون واضحة (أي لديهم ممتلكات hidden
بهم مجموعة لNO
) بين النافذة المستوى الأعلى والطبقة في السؤال. عندها فقط سوف تكون طبقة مرئية على الشاشة. حتى في مكان ما في التعليمات البرمجية تحتاج إلى إضافة طبقة ك الطبقة الفرعية من شيء واضح بالفعل من خلال الدعوة addSublayer:
.
في قضيتك، أفترض earth
هو مثيل CALayer
وما قمتم به داخل طريقة loadImage:
هو خلق CALayer
جديدة (مع دعوة [CALayer layer]
) داخل طبقة earth
ولكن بعد ذلك أبدا أضاف أن الجديد طبقة إلى أي شيء لذلك لم تصبح مرئية. ما لم بدلا من ذلك محاولة إضافة طبقة earth
، الذي لا يزال ليس لديها أي محتوى، ما أفترض هو طبقة من UIView
ل
[[طبقة النفس] addSublayer: [طبقة الأرض]].
اقتباس فقرة> ومشكلة واحدة مع هذا الخط هو يبدو أنك يكون التفكير layer
هو خاصية من earth
. في الواقع هو layer
طريقة فئة من CALayer
الذي هو وسيلة مصنع لإنشاء مثيلات جديدة من CALayer
. هذا هو مربكا لأن [self layer]
الواقع والوصول إلى الملكية طبقة من مثيل UIView
. (أفترض self
يشير إلى مثيل فئة فرعية UIView
).