• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Was gibt es Schöneres als den Mai draußen in der Natur mit allen Sinnen zu genießen? Lasst uns teilhaben an Euren Erlebnissen und macht mit beim Thema des Monats Da blüht uns was! ---> Klick

Anfängerfrage bei Obj-C

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Hallo liebes Forum :)

Ich habe Ende letzter Woche von einem Kumpel sehr günstig ein älteres MacBook gekauft und dies nun endlich mal ans Startschuss angesehen, um in die iOS App-Entwicklung einzusteigen. Um mich mit Objective-C und Xcode vertraut zu machen, habe ich angefangen ein super anfängertaugliches Video2Brain zu schauen. Kann es jedem der einsteigen möchte nur empfehlen! "Video2Brain Apps mit iOS5 entwicklen". Dort wird glücklicherweise bereits Xcode 4.2 mit iOS5.1 verwendet, somit gibt es auch bereits "Automatic Reference Counting" was gerade mir als Anfänger viel Arbeit erspart. Bin also nun seit rund drei Tagen abends nach der Arbeit ein bisschen am "lernen".

Nun zu meiner Frage:

In refreshWeather stehen unten die beiden Icon Ausgaben. Die Stringausgabe funktioniert, beim Objekt kommt nur "(null)".. Ich weiß aber nicht wieso. Hab schon alles mögliche ausprobiert. Ich bin sogar so rückständig gewesen und habe alle Properties der Klasse "Wettertag" durch manuelle getter und setter ersetzt, sprich viel Schreibarbeit. Leider ohne Erfolg. Innerhalb von XMLParser kann ich das Objekt problemlos verwenden, außerhalb davon ist es aber leer (der Speicherbereich ist aber zugewiesen). Per Breakpoint habe ich auch nicht rausfinden können was das Problem ist. Vermutlich habe ich einfach noch zu wenig Ahnung davon und brauche einen guten Denkanstoß.

Ich werde euch mal alle Klassen auflisten. Mir geht es darum, dass ich das erzeugte Objekt außerhalb von XMLParser weiterverwenden kann, um beispielsweise auf dem View ein Bild damit darzustellen o.ä.


wettertag.h:



#import <Foundation/Foundation.h>


@interface Wettertag : NSObject

@property (nonatomic, retain) NSString *city;
@property (nonatomic, retain) NSString *condition;
@property (nonatomic, retain) NSString *temp;
@property (nonatomic, retain) NSString *humidity;
@property (nonatomic, retain) NSString *icon;
@property (nonatomic, retain) NSString *wind;


@end





wettertag.m:



#import "Wettertag.h"


@implementation Wettertag
@synthesize city = _city, condition = _condition, temp = _temp, humidity = _humidity, icon = _icon, wind = _wind;


@end





xmlparser.h:



#import <Foundation/Foundation.h>


@classWettertag, AppDelegate;


@interface XMLParser : NSObject <NSXMLParserDelegate>

@property (nonatomic, retain) Wettertag *wettertag;
@property (nonatomic, retain) AppDelegate *appDelegate;
@property (nonatomic, retain) NSMutableString *curElement;

-(id) initXMLParser;


@end



xmlparser.m



#import "XMLParser.h"
#import "Wettertag.h"


@implementation XMLParser
@synthesize appDelegate, curElement, wettertag;


- (id) initXMLParser {
self = [super init];
appDelegate = (AppDelegate *)[[UIApplicationsharedApplication] delegate];
returnself;
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{


wettertag = [[Wettertagalloc] init];


if ([elementName isEqualToString:@"icon"]) {
wettertag.icon = [NSString stringWithFormat:@"http://www.google.com%@", [attributeDict objectForKey:@"data"]];


//NSLog(@"icon: %@", wettertag.icon);
curElement = [NSStringstringWithFormat:@"%@", wettertag.icon];
}
}





mainviewcontroller.m (auszug):



- (void)refreshWeather {
NSURL *url = [[NSURLalloc] initWithString:@"http://www.google.com/ig/api?weather=oldenburg&hl=en"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];


XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];


BOOL success = [xmlParser parse];


if(success) {
NSLog(@"XML Parsing erfolgreich");
NSLog(@"icon: %@", parser.curElement);
NSLog(@"icon2: %@", parser.wettertag.icon);
}
else {
NSLog(@"XML Parsing fehlgeschlagen!");
}
}



Vielleich sieht ja jemand den Fehler auf anhieb und kann mir ein bisschen helfen. VIelen Dank schonmal!

Edit: Scheinbar entfernt das Forum überflüssige Leerzeichen, wundert euch also nicht wieso z.B. bei einigen Dingen ein Leerzeichen fehlt. Diese sind vorhanden ;)
 
Zuletzt bearbeitet:

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Ähm, kannst du das genauer erläutern? Bin gerade nicht ganz sicher wie/wo/was :D

Merci!
 

Genforscher

Golden Delicious
Registriert
09.07.12
Beiträge
9
Du greifst direkt auf die Instanzvariable zu:
wettertag = [[Wettertagalloc] init];

gemeint war wohl:
self.wettertag = [[Wettertagalloc] init];

 

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Das ändert leider garnichts. Das Problem ist ja nicht, dass ich garnicht darauf zugreifen kann. In XMLParser.m kann ich Werte problemlos zuweisen und wieder auslesen. Bis zum Verlassen scheint alles vorhanden zu sein. Danach (also schon in MainViewController.m) kann ich auf den Wert des Objekts nicht mehr zugreifen, das Objekt existiert aber noch. Normal sagt man doch bei den Properties mit retain, dass dieses "release" nicht durchgeführt werden soll, oder?
 

Genforscher

Golden Delicious
Registriert
09.07.12
Beiträge
9
Wenn du direkt auf die Instanzvariablen zugreifst, greift das retain deiner Properties nicht.

-> wettertag.icon = [NSString ...

Nach beenden der Methode wird dein NSString (da du nicht daran festhältst) freigegeben.
 

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Hm, selbst wenn ich es so ändere (s.u.) ändert das nichts. Habe übrigens wegen der Nutzung von ARC von retain auf strong umgestellt.

...
if ([elementName isEqualToString:@"icon"]) {
self.wettertag.icon = [NSString stringWithFormat:@"http://www.google.com%@", [attributeDict objectForKey:@"data"]];
...
 

Genforscher

Golden Delicious
Registriert
09.07.12
Beiträge
9
Dann hilft nur nochmal debuggen und prüfen ob nur die Strings NULL-Werte haben oder ob gar die Objektreferenz (parser.wettertag) den Wert NULL hat.
BTW: wie sieht denn xmlparser.m nach den Anpassungen aktuell aus ?
 

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Ja, die Objektreferenz ist noch vorhanden (hab ich ja bereits geschrieben), allerdings enthält das Objekt an der Stelle keine Werte mehr (die Strings)
 

naich

Pomme d'or
Registriert
22.11.08
Beiträge
3.082
Wenn du direkt auf die Instanzvariablen zugreifst, greift das retain deiner Properties nicht.

-> wettertag.icon = [NSString ...

Nach beenden der Methode wird dein NSString (da du nicht daran festhältst) freigegeben.

Du hast doch getter und setter mit dem synthesize erzeugt, kannst du die dann auch benutzen? Also nicht mit ".", sondern in der Form:
[wettertag setIcon: ...] und als getter [wettertag icon]?
 
Zuletzt bearbeitet:

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
Du hast doch getter und setter mit dem synthesize erzeugt, kannst du die dann auch benutzen? Also nicht mit ".", sondern in der Form:
[wettertag setIcon: ...] und als getter [wettertag icon]?

Ja, natürlich. . und [] sind absolut identisch. Ein Unterschied ist es aber, wenn direkt auf die Instanzvariable zugegriffen wird.

Alex
 

naich

Pomme d'or
Registriert
22.11.08
Beiträge
3.082
OK. Und mit "wettertag.icon = ..." wird trotzdem der setter benutzt, auch wenn man hier icon statt setIcon schreibt? Weil die interne Variable ist ja mit _icon benannt, und sollte so und so normalerweise nicht direkt von außen zugreifbar sein.

(Ich versuche auch nur zu verstehen, wie diese synthesize-Sachen funktionieren, habe damit noch nicht so viel Erfahrung.)
 

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Problem gelöst: Ich Depp habe das Objekt wettertag innerhalb der Methode "didStartElement" initialisiert und folglich wurde dann für jedes Element in der XML Datei ein neues Objekt erzeugt :) Habe dies nun in den Konstruktor verlagert und voilà, schon klappt es :)

Danke an alle die probiert haben die Lösung zu finden :)
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
OK. Und mit "wettertag.icon = ..." wird trotzdem der setter benutzt, auch wenn man hier icon statt setIcon schreibt?
Ja


Weil die interne Variable ist ja mit _icon benannt, und sollte so und so normalerweise nicht direkt von außen zugreifbar sein.
Wenn Du damit meinst, dass die Instanzvariable _icon heisst, und man deshalb nicht unter dem Namen "icon" auf sie zugreifen kann, dann hast Du recht.
Wenn Du damit meinst, dass Du auf _icon aus Deiner Klasse keinen Zugriff hast, dann ist das falsch.

Alex
 

naich

Pomme d'or
Registriert
22.11.08
Beiträge
3.082
Wenn Du damit meinst, dass die Instanzvariable _icon heisst, und man deshalb nicht unter dem Namen "icon" auf sie zugreifen kann, dann hast Du recht.
Danke für die Antwort, genau das mein ich. Dass ich innerhalb der Klasse _icon verwenden kann, ist mir klar.
 

below

Purpurroter Cousinot
Registriert
08.10.06
Beiträge
2.858
Zur Vollständigkeit: Sie könnte auch "icon" (oder "hanswurst") heissen, self.icon = foo geht immer noch über den Setter. Also:
Code:
@interface bar : NSObject {
id icon;
}
@property (retain) id icon;
@end

@implementation bar 
@synthesize icon;

- (void) doFoo {
   self.icon = foobar; // Nutzt setter und ist absolut äquivalent zu:
   [self setIcon:foobar];
   // Dagen ist
   icon = foobar;
   // ein direkter Zugriff auf die iVar
}

Alex
 

Hoax87

Golden Delicious
Registriert
11.07.12
Beiträge
8
Ich habe die Instanzvariablen nur mit _ benannt, damit man den eigentlich korrekten Namen für setter und getter verwenden kann (so wie man den Namen erwartet).

bei obj.icon = ... weiß Obj-C ja, dass es sich um die Setter Methode handelt (wird autom. durch das Property zur Verfügung gestellt), wobei ein NSLog(..., obj.icon) auf die getter Methode zugreift. Für die Setter Methode könnte man auch obj.setIcon nutzen.
Soviel weiß ich nach einigen Tagen Obj-C Erfahrung schon ;)

Mit den Properties ist es ganz angenehm... spart viel Schreibaufwand.