هل هناك سبب لا أستطيع تهيئة CALayer خارج فئة UIView؟

StackOverflow https://stackoverflow.com/questions/805265

  •  03-07-2019
  •  | 
  •  

سؤال

ولقد سعيت لنا 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).

scroll top