Objective-C pitanjce
(1 korsinik/a gleda/ju temu) (1) Gost

Objective-C pitanjce


13.11.2009 | 14:33
Može li mi netko pojasniti u čemu je razlika između ova dva primjera i zašto se u jednom slučaju javlja greška, a u drugom ne? Radi se o maloj app za iPhone (ali mislim da je svejedno, da se odnosi i na MacOS X development).

Imam jedan UIViewController, i jednu klasu koja mi služi za SOAP komunikaciju (ovaj primjer radi ok):
//.h file
@interface Hello_SOAPViewController : UIViewController
{
	IBOutlet UITextField *nameInput;
	IBOutlet UILabel *greeting;
}

@property(nonatomic, retain) IBOutlet UITextField *nameInput;
@property(nonatomic, retain) IBOutlet UILabel *greeting;

-(IBAction)pingClick: (id) sender;
@end

//.m file
#import "Hello_SOAPViewController.h"
#import "GWS_LeasingSvc.h"
@implementation Hello_SOAPViewController

@synthesize greeting, nameInput;

-(IBAction)pingClick:(id) sender
{
        GWS_LeasingSoap *soapCall = [[GWS_LeasingSvc GWS_LeasingSoap] retain];
	soapCall.logXMLInOut = YES;
	soapCall.authUsername = @"user";
	soapCall.authPassword = @"pass";
	GWS_LeasingSvc_Ping *cRequest = [[GWS_LeasingSvc_Ping new] autorelease];
	[soapCall PingAsyncUsingParameters:cRequest delegate:self];
        [nameInput resignFirstResponder];
}

- (void) operation:(GWS_LeasingSoapOperation *) operation 
completedWithResponse:(GWS_LeasingSoapResponse *) response
{
	NSArray *responseHeaders = response.headers;
	NSArray *responseBodyParts = response.bodyParts;
	
	for(id header in responseHeaders) {
        ....
	}
	
	for(id bodyPart in responseBodyParts) {
		if ([bodyPart isKindOfClass:[SOAPFault class]]) {
		       greeting.text = ((SOAPFault *)bodyPart).simpleFaultString;
			continue;
		}
				
		if([bodyPart isKindOfClass:[GWS_LeasingSvc_PingResponse class]]) { 
			GWS_LeasingSvc_PingResponse *body = (GWS_LeasingSvc_PingResponse*)bodyPart;
			greeting.text = body.PingResult;
			continue;
		}
	}	
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	// Return YES for supported orientations
	return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning]; 
}

- (void)dealloc 
{
	[super dealloc];
}
@end
13.11.2009 | 14:41
Nastavak:

E sad sam ja dodao još jednu klasu koja bi mi bila između UIViewControllera
i klase koja radi samu SOAP komunikaciju iz razloga što ta klasa ima jedno
50-tak različitih poziva pa da mi to sve nije u UIViewControlleru.

Ovako sam to prepravio:
//.h file
@interface Hello_SOAPViewController : UIViewController
{
IBOutlet UITextField *nameInput;
IBOutlet UILabel *greeting;
}

@property(nonatomic, retain) IBOutlet UITextField *nameInput;
@property(nonatomic, retain) IBOutlet UILabel *greeting;

-(IBAction)pingClick: (id) sender;
@end

//.m file
#import "Hello_SOAPViewController.h"
#import "GWS_Leasing_Delegate.h"
@implementation Hello_SOAPViewController

@synthesize greeting, nameInput;

-(IBAction)pingClick:(id) sender
{
        GWS_Leasing_Delegate *gLeasing = [[GWS_Leasing_Delegate alloc] init];
	[gLeasing runPing];
	greeting.text = gLeasing.result;
	[nameInput resignFirstResponder];
	[gLeasing release];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
 {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; 
}


- (void)dealloc 
{
[super dealloc];
}
@end


//.h 
#import <Foundation/Foundation.h>
#import "GWS_LeasingSvc.h"

@interface GWS_Leasing_Delegate: NSObject <GWS_LeasingSoapResponseDelegate>{
	NSMutableString *result;
	GWS_LeasingSoap *soapCall;
}
@property(nonatomic,retain) NSMutableString *result;
@property(nonatomic,retain) GWS_LeasingSoap *soapCall;

-(void)runPing;
@end

//.m file
#import "GWS_Leasing_Delegate.h"
@implementation GWS_Leasing_Delegate 

@synthesize result,soapCall;

-(id) init
{
	self = [super init];
	if (!result) {
		result=[[NSMutableString alloc] init];
	}
	
	if(!soapCall){
		soapCall = [[GWS_LeasingSvc GWS_LeasingSoap] retain];
	}
	return self;
}
-(void) runPing
{
	soapCall.logXMLInOut = YES;
	soapCall.authUsername = @"user";
	soapCall.authPassword = @"pass";
	GWS_LeasingSvc_Ping *cRequest = [[GWS_LeasingSvc_Ping new]autorelease];
	[soapCall PingAsyncUsingParameters:cRequest delegate:self];
		
}

- (void) operation:(GWS_LeasingSoapOperation*)operation 
completedWithResponse:(GWS_LeasingSoapResponse*)response
{
	NSArray *responseHeaders = response.headers;
	NSArray *responseBodyParts = response.bodyParts;
	
	for(id bodyPart in responseBodyParts) {
		if ([bodyPart isKindOfClass:[SOAPFault class]]) {
			
                [result appendString:((SOAPFault *)bodyPart).simpleFaultString];
		continue;
		}
		
		if([bodyPart isKindOfClass:[GWS_LeasingSvc_PingResponse class]]) { 
		GWS_LeasingSvc_PingResponse *body = (GWS_LeasingSvc_PingResponse*)bodyPart;
			
                 [result appendString: body.PingResult];
		continue;
		}
	}
}

-(void)dealloc
{
	[result release];
	[soapCall release];
	[super dealloc];
}
@end



Kad ovako napravim build XCode kaže Succeeded, ali kad pokrenem App
i kliknem taj ping program pukne i javi slijedeće:

2009-11-13 14:05:32.430 NOVASOAP[2943:207]
*** -[NSURLRequestInternal operation:completedWithResponse:]:
unrecognized selector sent to instance 0x227a00
2009-11-13 14:05:32.442 NOVASOAP[2943:207]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[NSURLRequestInternal operation:completedWithResponse:]:
unrecognized selector sent to instance 0x227a00'
13.11.2009 | 17:30
Imaš dva propertija i tri synthesize...

@property(nonatomic, retain) IBOutlet UITextField *nameInput;
@property(nonatomic, retain) IBOutlet UILabel *greeting;

@synthesize greeting, nameInput, responseView;

Nakon toga mi je postalo teško čitati dalje. Jel to Jabučnjak unakazio razmake ili... ?

Igor
13.11.2009 | 17:54
Evo ispravio sam, ali nije bilo do toga krivo sam copy paste. Ali stvarno izgleda katastrofa za čitat.

Najbitnije je dio onaj

- (void) operation:(GWS_LeasingSoapOperation*)operation completedWithResponse:(GWS_LeasingSoapResponse*)response

ako se nalazi u ViewController-u i sama instanca klase koja radi SOAP se nalazi u ViewControlleru onda sve radi
ok. Ako pak to sve prebacim u novu klasu onda počinju problemi.

Lp,
Nenad
13.11.2009 | 20:24
Pričam napamet, ali u prvom primjeru je sporna metoda dio klase koja nasljeđuje UIViewController, a u drugom NSObject. Jel' moguće da metoda koristi "nešto" što je defaultno nasljeđeno u UIViewController, a "ne postoji" na vrhu hijerarhije, u NSObjectu?
13.11.2009 | 23:28
Djipi je napisao:
Pričam napamet, ali u prvom primjeru je sporna metoda dio klase koja nasljeđuje UIViewController, a u drugom NSObject. Jel' moguće da metoda koristi "nešto" što je defaultno nasljeđeno u UIViewController, a "ne postoji" na vrhu hijerarhije, u NSObjectu?


Tražim što bi moglo biti to "nešto" ali nikako da nađem
Kad u XCode-u stistem desni gumb na tu spornu metodu i kliknem jump to definition dobijem:

@class GWS_LeasingSoapResponse;
@class GWS_LeasingSoapOperation;
@protocol GWS_LeasingSoapResponseDelegate <NSObject>
- (void) operation:(GWS_LeasingSoapOperation *)operation completedWithResponse:(GWS_LeasingSoapResponse *)response;
@end


@interface GWS_LeasingSoapOperation : NSOperation {
GWS_LeasingSoap *binding;
GWS_LeasingSoapResponse *response;
id<GWS_LeasingSoapResponseDelegate> delegate;
NSMutableData *responseData;
NSURLConnection *urlConnection;
}
@property (retain) GWS_LeasingSoap *binding;
@property (readonly) GWS_LeasingSoapResponse *response;
@property (nonatomic, assign) id<GWS_LeasingSoapResponseDelegate> delegate;
@property (nonatomic, retain) NSMutableData *responseData;
@property (nonatomic, retain) NSURLConnection *urlConnection;
- (id)initWithBinding:(GWS_LeasingSoap *)aBinding delegate:(id<GWS_LeasingSoapResponseDelegate>)aDelegate;
@end

@interface GWS_LeasingSoapResponse : NSObject {
NSArray *headers;
NSArray *bodyParts;
NSError *error;
}
@property (retain) NSArray *headers;
@property (retain) NSArray *bodyParts;
@property (retain) NSError *error;
@end
13.11.2009 | 23:56
Ovo:
-(IBAction)pingClick:(id) sender
{
   GWS_Leasing_Delegate *gLeasing = [[GWS_Leasing_Delegate alloc] init];
   [gLeasing runPing];
   greeting.text = gLeasing.result;
   [nameInput resignFirstResponder];
   [gLeasing release];                // AJ, MAKNI OVAJ RED!!!
}



Sad kad si postao i ovaj zadnji dio sjetio sam se jedne stvari. Delegati se nikad ne retainaju u klasi koja ih poziva da bi se izbjeglo ciklično dealociranje (ili tako neki izraz). Da se naslutiti iz ovog reda:

@property (nonatomic, assign) id<GWS_LeasingSoapResponseDelegate> delegate;

Probaj pa javi.

Igor
14.11.2009 | 00:01
Tko točno u cijeloj ovoj priči poziva [NSURLRequestInternal operation:completedWithResponse:]?
14.11.2009 | 00:05
I, usput, ako ovo što je IgorD predložio ne pomogne - možeš li s debugerom provjeriti koji se to konkretno "unrecognized selector" prosljeđuje?
14.11.2009 | 00:15
Da skužio sam i ja da treba maknuti onaj [gLeasing release];
Pretpostavljam da je bio problem u tome što je interno gLeasing još uvijek čekao odgovor a ja sam ga release-o. Sad još samo moram smisliti kako naknadno prikazati gLeasing.result u kontroli greeting u mom ViewControlleru. Jer ako napišem:

gLeasing = [[GWS_Leasing_Wrapper alloc] init];
[gLeasing runPing];
greeting.text = gLeasing.result;


Tu je još gLeasing.result prazan još se nije desila ona metoda sa odgovorom web servisa.
14.11.2009 | 00:23
Djipi je napisao:
Tko točno u cijeloj ovoj priči poziva [NSURLRequestInternal operation:completedWithResponse:]?


Prema kodu je to onaj GWS_LeasingSoapOperation jer on ima metode gdje se sa NSURL spaja na web servis. Cijeli ovaj kod sam dobio pomoću jednog programa koji iz WSDL (opis web servisa) generira Objective-C kod tako da nije mojih ruku djelo.
14.11.2009 | 00:24
Da skužio sam i ja da treba maknuti onaj [gLeasing release];


Znači to je,

ok - onda dodaš stvar kao instance varijablu u ViewController i radiš release tek u metodi -dealloc za kontroler. A onda nek ona delegate metoda signalizira kontroleru da je sve gotovo.

Dodaj toj klasi metodu -initWithController: tak da ima interni pointer na njega i onda nek mu signalizira pozivom neke metode da je sve gotovo.

Igor
14.11.2009 | 01:13
Hvala momci!!!

Eto riješih sve probleme

Sad sve izgleda ovako:
#import <UIKit/UIKit.h>
#import "GWS_Leasing_Wrapper.h"

@interface Hello_SOAPViewController : UIViewController
{
	IBOutlet UITextField *nameInput;
	IBOutlet UILabel *greeting;
	GWS_Leasing_Wrapper *gLeasing;
}

@property(nonatomic, retain) IBOutlet UITextField *nameInput;
@property(nonatomic, retain) IBOutlet UILabel *greeting;

-(IBAction)buttonClick: (id) sender;
-(IBAction)pingClick: (id) sender;
-(void)showgLeasingResult;
@end

#import "Hello_SOAPViewController.h"

@implementation Hello_SOAPViewController

@synthesize greeting, nameInput;

-(IBAction)pingClick:(id) sender
{
	gLeasing = [[GWS_Leasing_Wrapper alloc] initWithController:self];
	[gLeasing runPing];
	[nameInput resignFirstResponder];
}

-(void)showgLeasingResult
{
	greeting.text=gLeasing.result;
}
.....
@end


#import <Foundation/Foundation.h>
#import "GWS_LeasingSvc.h"
@class Hello_SOAPViewController;

@interface GWS_Leasing_Wrapper: NSObject <GWS_LeasingSoapResponseDelegate>{
	NSMutableString *result;
	GWS_LeasingSoap *soapCall;
	bool asyncTaskFinished;
	Hello_SOAPViewController *contr;
}
@property(nonatomic,retain) NSMutableString *result;
@property(nonatomic,retain) GWS_LeasingSoap *soapCall;
@property(nonatomic,assign) bool asyncTaskFinished;
@property(nonatomic,retain) Hello_SOAPViewController *contr;

-(void)runPing;
-(bool)didAsyncTaskFinished;
-(id)initWithController:(Hello_SOAPViewController *)controller;
@end


#import "GWS_Leasing_Wrapper.h"
#import "Hello_SOAPViewController.h"

@implementation GWS_Leasing_Wrapper 

@synthesize result,soapCall,asyncTaskFinished, contr;

-(id) initWithController:(Hello_SOAPViewController *)controller
{
	if(self = [super init])
	{
		if (!result) {
		      self.result=[[NSMutableString alloc] init];
		}
	
		if(!soapCall){
		      self.soapCall = [[GWS_LeasingSvc GWS_LeasingSoap] retain];
		}
		self.contr=controller;
	}
	
	return self;
}
-(void) runPing
{
	soapCall.logXMLInOut = YES;
	soapCall.authUsername = @"user";
	soapCall.authPassword = @"pass";
	GWS_LeasingSvc_Ping *cRequest = [[GWS_LeasingSvc_Ping new]autorelease];
	[soapCall PingAsyncUsingParameters:cRequest delegate:self];
		
}

- (void) operation:(GWS_LeasingSoapOperation*)operation 
completedWithResponse:(GWS_LeasingSoapResponse*)response
{
	NSArray *responseHeaders = response.headers;
	NSArray *responseBodyParts = response.bodyParts;
	
	for(id bodyPart in responseBodyParts) {
		if ([bodyPart isKindOfClass:[SOAPFault class]]) {
			[self.result appendString:((SOAPFault *)bodyPart).simpleFaultString];
			continue;
		}
		if([bodyPart isKindOfClass:[GWS_LeasingSvc_PingResponse class]]) { 
			GWS_LeasingSvc_PingResponse *body = (GWS_LeasingSvc_PingResponse*)bodyPart;
			[self.result appendString: body.PingResult];
			
			self.asyncTaskFinished=YES;
			continue;
		}
	}
	[contr showgLeasingResult];
	
}


-(bool)didAsyncTaskFinished
{
	return self.asyncTaskFinished;
}

-(void)dealloc
{
	[result release];
	[soapCall release];
	[super dealloc];
}
@end
14.11.2009 | 02:19
Cool,

i da sve bude savršeno:

-(void)dealloc
{
   [result release];
   [soapCall release];

   [contr release];

   [super dealloc];
}
14.11.2009 | 19:49
IgorD je napisao:
Cool,

i da sve bude savršeno:

-(void)dealloc
{
   [result release];
   [soapCall release];

   [contr release];

   [super dealloc];
}


E vidiš to sa [contr release]; se nisam usudio napraviti jer mene još uvijek hebe to sve pointerisanje. Ja dolazim prvenstveno iz svijeta SQL-a (to radim za pare) i .NET-a gdje tih pointera nema. Mislio sam ako release-am contr da ću i glavni view release-ati. Ako dobro kužim onda contr pokazuje na memorijsku lokaciju na kojoj se nalazi pointer koji pokazuje gdje se nalazi UIViewController i onda ako ja nešto od toga release-am sve ode u klinac.... uf al sam ga skomplicirao....... Sad ću ipak na tvoj savjet to dodati i probati jel šljaka.... Moram ja te knjige ipak počet čitati (makar mi se iskreno ne da)...
14.11.2009 | 22:38
Ovo je alociranje i oslobađanje memorije, ali ne u onom smislu kako je to napravljeno u običnom C-u već je ovdje to malo drukčije.

U standardnom C-u memoriju dobijaš sa malloc(), a oslobađaš sa free(). Maloc ti garantirano vrati novi blok memorije (ili NULL ako nema mjesta) a free() garantirano to onda vrati sistemu i oslobodi za daljnje korištenje.

U Objective-Cu to nije tako iako se možda čini da je. Ovdje se to svodi na "ownership" - često to tako nazivaju pa se ni meni ne da izmišljati novi izraz. Interno postoji "reference count" za neki komad memorije i na početku je on jedan. Ako odmah pozoveš -release, taj ref count se umanji i kad je nula, onda se poziva -dealloc. U suprotnom objekt i dalje postoji. Metoda -release nije nužno i -dealloc.

Ovaj red je napravio retain:

self.contr=controller;

Na kraju je vrijeme da kažeš da ti contr više ne treba sa -release.

Igor
Moderatori: Bertone
  • Stranica:
  • 1

Vikalica™

Zadnja poruka: pred 3 dana, 8 sati
  • smayoo: Riječani i ostali zainteresirani, kavica i ćakula ovu subotu (30.08.) ujutro u 10h u gradskoj kavani Renard
  • drlovric: @vanjus: Barem si imao mogucnost izbora. Odaberes banku koja ima Apple Pay i cao :) biH je doslovce prije tjedan-dva dobila Apple Pay, nije uopce bilo dostupno u drzavi.
  • VanjusOS: pa znam da je Apple pay bio dostupan preko PBZ-a već godinama, ali tek od jučer je to moguće i preko HPB.
  • Yonkis: @smayoo - mogli bi subotu ujutro. Ima li još zainteresiranih, gdje je tino1?
  • Yonkis: @VanjusOS - to misliš kao "napokon" tj sarkastično?
  • smayoo: @yonkis - ja mogu u subotu ujutro. U nedjelju popodne-navečer možda također, ali nisam siguran.
  • VanjusOS: ljudi, tehnološka revolucija! od danas Apple Pay i preko HPB-a!!
  • Yonkis: Jel netko za kakvu kavu ovaj vikend? U Ri mislim :)
  • Yonkis: Glede Tita.. u Splitu: [link]
  • smayoo: @drlovric, nema na čemu, drago mi je. :)
  • mbp2009: Titini kriteriji: onaj koji je bio protiv njega. Kao i kriteriji svakog drugog kriminalca i diktatora :)
  • drlovric: @Smayoo: Isli u plavo bijeli. Sasvim pristojna hrana. Nismo uopce razocarani. Hvala :)
  • jura22: Da, tocno tako. Sakupljao po ulici! Zene, djecu, starce. Po redu. Bez kriterija.
  • smayoo: U samom Osijeku, nažalost, po mom iskustvu ništa nije baš trajno na visokom nivou. Ako bih morao preporučiti bar jedno mjesto, to bi bio "Plavo-bijeli". Klasični restoran, kad vidiš kako su konobari odjeveni, izgleda kao da su još osamdesete, ali hrana je konzistentno vrlo dobra. Ali to je nekakav standardni restoranski jelovnik, nema nekih baš tradicionalno slavonskih jela
  • smayoo: Varga u Bilju, pojeli smo zbilja dobar čobanac prije koju godinu. Još je bolji u Sokaku u Đakovu, kod ergele, ali to ti nije blizu Osijeka
  • drlovric: Sutra sam u Osijeku. Molim lokalce za preporuku za dobru slavonsku hranu.
  • Air: U protivnom je imao vanzemaljsku sreću da je baš smaknuo one koji su mu smetali.
  • Air: @jura22 ja sam nekoj logici siguran da je Tito imao kriterije po kojima je to činio.
  • smayoo: Kako misliš - da je nekog dao smaknuti bez kriterija? Skupljao je nasumično ljude po ulici pa ih vodio na smaknuće?
  • Yonkis: Što je kriterij?
  • jura22: “kriterija”
  • smayoo: Što je krizerij?
  • jura22: Danas se sjecamo svih koje je Tito dao smaknuti bez krizerija.
  • Bertone: e da je ufatiti svu tu struju nekako i pospremiti je za kasnije ;D
  • smayoo: Leleee... :)
  • Yonkis: Evo par slika od jutros, slikano iPadom: [link]
  • mbp2009: Sve ok, pbz radi na beti
  • ZeljkoB: Moze se napraviti downgrade na iOS18.x ako nesto ne radi....
  • mbp2009: Nije problem staviti bankarstvo na betu, samo ako ne radi, onda mi se ne da do banke :D
  • big_mac: Jel radi pbz na 26 beta 7?
  • Riba: Mislim da ovdje mijesamo beta aplikacije sa trojancem.
  • dpasaric: Tako da o tome treba voditi računa kada se igra sa softverima još u razvoju.
  • dpasaric: Da se nešto slučajno dogodi sva odgovornost je na beta korisniku.
  • drlovric: Tako je moj prijatelj prije par godina crackiran password manager pa upao u probleme.
  • drlovric: Stavljati bankarstvo na beta aplikacije ne bih nazvao pametnom zivotnom strategijom :)
  • ZeljkoB: IOS26 dev Beta 6, ZABA, OTP, Revolut, Finax…. Sve radi od potencijalno problematičnih app
  • ZeljkoB: iOS26 public beta 2 - ZABA i OTP rade
  • ZoPaj: a Rolling Stonesi planiraju turneju 2026…
  • ZoPaj: RIP! odlaze legende …
  • Gjuroo: Počivala u miru...
  • smayoo: RIP Gabi Novak
  • VanjusOS: možda nije obrisano zbog "piratstva" već zbog toga što se u vikalici ne bi trebamo objašnjavati nego u temama?
  • drlovric: Svi gledamo nesot piratsko. Apsurd je pricati o tome. Ja Hajduku placam pretplatu i clanarinu, a kradem HDTV od 2e, jer ne postoji nacin da ga legalno kupim :)
  • Zdravac: Eto, malo analogije za kraj!
  • Zdravac: Ali ok, svaki privatnik u svome restoranu može svojevoljno određivati cijene, a na nama je opet volja hoćemo li ići u taj restoran ili ne.
  • Zdravac: Shvatite da NIJE ilegalno instalirati Kodi na AppleTV
  • Zdravac: Pomalo je frustrirajuće kad znaš da nisi napisao apsolutno ništa ilegalno, a svejedno su ti postovi čak i u vikalici pobrisani jer, eto, moderatori smatraju kao "neprikladno" :?
  • VanjusOS: probao sam preko Xcode neki način ali trebam apple develpper acc
  • VanjusOS: da li je netko instalirao KODI na Apple TV 4K?
  • ZeljkoB: Kakvih problema? Ja koristim public beta vreziju i nikakvih problema.

Za vikanje moraš biti prijavljen.

Prijava

Prisutni jabučari

Air, Ender, Riba, skunic, Anonimci (790)

Novo na Jabučnjaku

Teme

Poruke

Oglasi

Anketa

Koji Mac koristite?

Page Speed 1.10 Seconds

Provided by iJoomla SEO