Gibt es einen Grund, warum ich nicht ein CALayer außerhalb einer UIView Klasse initialisieren kann?

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

  •  03-07-2019
  •  | 
  •  

Frage

Ich habe in einer iPhone-Applikation uns CALayers als „Sprites“ versucht, den ich arbeite. Von dem, was ich gelesen habe, dass wie die richtige Sache scheint hier zu tun.

Wenn ich Setup die Schicht in einem UIView Klasse ich in der Lage bin, die Schicht zu erhalten auf dem Bildschirm angezeigt werden:     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];

Allerdings, wenn ich versuche, die CALayer außerhalb des UIView, meine Anwendung abstürzt zu initialisieren:

- (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]];

Klar mache ich etwas falsch hier, aber ich weiß einfach nicht, was das wäre. Ich habe den Core Animation Programming Guide und auch der iPhone Application Programming Guide lesen, aber sie scheinen wirklich nicht darüber zu reden, wie eine CALayer andere als im Vorbeigehen zu initialisieren.

Ich brauche nur einen leichten Schub in der richtigen Richtung. Ich habe immer ein ziemlich gutes Verständnis über alles, was ich gelernt habe, wenn es um die Programmierung des iPhone kommt. Ich habe nur ein paar Probleme mit Grafiken, Ebenen und Animation.

Vielen Dank im Voraus!

War es hilfreich?

Lösung

Sie nicht besitzen die Ebene, die Sie aus dem layer Methode zu erhalten, so dass Sie den Besitz übernehmen. Einige Zeit nach der Methode zurückgibt, wird die Schicht freigegeben wird und dass Ihr Absturz verursacht. Zur Heilung folgt aus:

layer = [[CALayer layer] retain]; // now we explicitly take ownership of this layer

Auch vergessen Sie nicht, die Schicht zu lösen, da Sie es besitzen jetzt:

// in your dealloc method
[layer release];

Sie sollten die Memory Management Programming Guide für Cocoa überprüfen für weitere Details über, wenn Sie Objekte und was Ihre Aufgaben sind in Bezug auf die Speicherverwaltung besitzen.

Andere Tipps

Jason, vielen Dank für die Beantwortung! Aber Ihre Antwort scheint keine Auswirkungen auf das Ergebnis meines Problems zu haben.

Eigentlich ist die Antwort „“ etwas in dem Speicher Management. Nicht die Schicht, aber der Name, den ich aus der NSArray bekam nach componentsSeparatedByString Aufruf :. Wenn ich nicht die NSArray loslassen, funktioniert der Code in Ordnung. Also muß ich innerhalb des Arrays eine Kopie des NSString machen, anstatt das Objekt in dem Array zu verwenden.

Ich muss sagen, dass ich nicht die Memory-Management-Programmierhandbuch für Cocoa gelesen haben, wie Sie vorschlagen. Allerdings habe ich einige andere Buch lesen, die über den Standard gesprochen in Cocoa verwendet für selbst erstellte Objekte und deren behalten zählt. Ich habe ein faires Verständnis, aber anscheinend nicht so gut wie nötig noch.

Ich hatte wirklich den Verdacht, dass ich die Zeichenfolge aus dem Array kopieren soll, aber wenn es in der UIView gearbeitet, ich nahm nur, dass es richtig war. Das Problem war, ich war nicht zu halten es, wie ich in meinem GamePiece Objekt bin.

Vielen Dank für zumindest immer mich in der richtigen Richtung zu schauen! Ich war wirklich auf Latein am Ende mit diesem Code.

Zu tun, was man wollte, ist hier, wie Sie Ihren Code ändern könnte. In loadImage: diese Linie verwenden, um die UIImage Sie in die earth Schicht geladen hinzuzufügen:

  

self.enthaelt = image.CGImage;

CALayers eine contents Eigenschaft haben, die Sie lieber auf einen CGImage einstellen, als sich die Mühe der Verwendung von Core Graphics ruft das Bild in die Ebene des Kontext zu ziehen.

Dann in der Mutter UIView Unterklasse Sie die earth der Ansicht Hierarchie wie folgt hinzufügen:

  

[self.layer addSublayer: Erde];

Beachten Sie, dass earth selbst ein CALayer mit einem Bild als Inhalt, damit ich es direkt als Unterschicht hinzuzufügen. Die andere Sache, die ich tue immer vergessen wird, die Ebene der frame Eigenschaft festgelegt. Andernfalls wird ihre Breite und Höhe Null sein und so wird es nicht zeigen.

In Ihrem Code erstellt man eine Schicht aber hinzugefügt nie Ihre Schicht zu der Ansicht Hierarchie. Es ist ein Baum, wenn Aussicht (Klasse UIView) und deren Subviews. Die Wurzel des Baumes ist [UIWindow Hauptfenster] (beachten Sie, dass UIWindow eine Unterklasse von UIView ist. Jeder UIView eine layer Eigenschaft des Typs CALayer hat, die ihren sichtbaren Inhalt tatsächlich hält. UIView ist nur ein Wrapper um CALayer Dinge wie Touch-Handling Fähigkeit hinzufügen .

Die wichtige Idee, die Sie hier fehlen, ist, dass für alles, was auf dem Bildschirm sichtbar zu sein, es Teil dieses Baumes von Ansichten mit einem UIWindow als Wurzel sein und alle Ansichten müssen sichtbar sein (dh ihre hidden Eigenschaft set) zwischen den Top-Level-Fenstern und der Schicht in Frage NO. Erst dann wird eine Schicht auf dem Bildschirm sichtbar sein. Also irgendwo in Ihrem Code benötigen Sie eine Schicht als Unterschicht von etwas bereits sichtbar durch den Aufruf addSublayer: hinzuzufügen.

In Ihrem Fall, ich gehe davon aus earth ist eine Instanz eines CALayer und was Sie im Innern des loadImage: Verfahren getan haben, ist eine neue CALayer erstellen (mit einem Aufruf an [CALayer layer]) innerhalb der earth Schicht, aber dann kann du nie, dass neue Schicht auf alles, was es wurde so nie sichtbar. Was Sie stattdessen haben wird versucht, die earth Schicht hinzuzufügen, die noch keinen Inhalt hat, zu dem, was ich davon ausgehen, ist eine Schicht, die UIView

  

[[self Schicht] addSublayer: [Erdschicht]];

Ein Problem mit dieser Linie ist, dass Sie scheinen layer zu denken eine Eigenschaft von earth ist. Eigentlich layer ist eine Klassenmethode von CALayer die eine Factory-Methode ist, um neue Instanzen von CALayer zu erstellen. Dies ist verwirrend, weil [self layer] tatsächlich ist die Schicht Eigenschaft einer UIView Instanz zugreifen. (Ich gehe davon aus self bezieht sich auf eine Instanz einer Unterklasse UIView.)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top