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 1 dan, 7 sati
  • Miki9890: Poz! ima li smisla skinuti 26.6.1 na iPhoneu 13 mini radi spotlight indexinga? Da li je to samo za siri Ai kojeg ionako neću imati i hoće li indexirati opet kad prijeđem na 27? trenutno sam na 18-ici
  • Piko: ja bi drugi .... da li rade ?
  • Riba: Pogotovo ako je zracno hladjen.
  • Riba: Mene zanima jedan!
  • IkoIko: Pozdrav zanima li ikog dva powermaca g5?
  • Yonkis: Nisam ovo znao, Apple koristi Google za svoj iCloud [link]
  • marioart: ko zeli iz njemacke uzimati, preporucujem alternate.de - pocetni model je 976€
  • ZoPaj: iducan.hr ima sve konfiguracije, mini i studio, nije preogromna razlika u odnosu na nedavno poskupljeno
  • jura22: Točno, ispravak 1.049eur. Onda i nije neka velika razlika.
  • Yonkis: Nema đabe ni u starog Applea
  • Pongy75: Evo, osnovni model Minija u iStyle je 1.159€ - skoro pa duplo nego nekada osnovni model minija. Tu se gubi svaki smisao povoljnog Mac računala.
  • Pongy75: i u švabiji, koliko je kod nas?!!
  • marioart: @jura to je sa edu popustom, cijena bez popusta je 1049€
  • jura22: Osnovni Mini M6 je 929€. [link]‑core-cpu-12‑core-gpu-16-gb-arbeitsspeicher-256gb-speicher
  • matijazx: - nadživio je svog oca za 10 godina.
  • dpasaric: Jazz legenda!
  • smayoo: RIP Stjepan Jimmy Stanić
  • Pongy75: Ma nek si znaš kaj…
  • matijazx: -- u ovlaštenom Apple storeu, vidio cijene za preoreder.....M6 mini 16GB-cca 1200 eura, 24GB-cca 1700 eura
  • Pongy75: Obično bude koliko dolara toliko u eurima nekih 10%
  • dpasaric: Javim kada dobijemo cijene za Hrvatsku...
  • dpasaric: Sitgli novi M5 Mac mini i M5 Ultra Mac Studio!
  • IkoIko: Sretan rođendan Smayo :)
  • ping: sretan rođendan dragi Smayoo
  • IkoIko: Pozdrav, molio bih malu pomoć od forumaša koji su pristali model postolja s filtrom za Mac studio. Kojih je dimenzija gumena brtva koja ide na okvir? Ili imate baš određen model koji se kupi na brtva.hr? Hvala i isprike na smetnji
  • smayoo: :*
  • drlovric: Sve najbolje. Cestitke!
  • Pongy75: SRETAN ROĐENDAN!!!
  • Gjuroo: Sretan rođoš, Samyoota! :kiss: :heart:
  • smayoo: Hvala od srca! :)
  • Kloba: Nema me puno, ali čitam pa eto - Smayoo sretan ti rođendan - da ti se ostvare sve želje!
  • smayoo: Hvala! :)
  • dpasaric: Smayoo sretan rođendan! :)
  • CoffeePod: Hvala puno!
  • Bertone: Pretplati se na ovu temu [link] i naruči gajbu strpljenja :D
  • CoffeePod: [link]
  • CoffeePod: Ima li tko iskustva sa kuycon monitorima?
  • miomika: nebi niti ja preporučio RAM servis....bez da se ITKO ljuti.
  • cariblanco: Ja sam našao stari filter u boji, dok još nije bilo kolor-tv, ako netko ima crno-bijeli, ja mu taj filter poklanjam :)
  • zvone: Ljudi imam neke screen protectore za 12 pro i par caseova. Zena ima novi mob a ostali stari dodaci. Ako netko zeli pokupiti na podrucju Zagreba.
  • drlovric: Ja koristim FluidVoice diktiram vise od 70% mailove, kao i text poruka.
  • smayoo: :D
  • Bertone: Ma znam kako diktiranje funkcionira ali iskreno se ne sjećam kada sam zadnji put čuo tišinu :(
  • smayoo: To naravno da ne funkcionira ako više ljudi priča u glas ili ako ti radio svira dok pričaš.
  • Bertone: Ma to sa diktiranjem je pušiona, nevezano za poruke nekidan vozim mamu doma i trebam nešto ženu pa je pokušam nazvati no auto ponavlja da ne razumije,... na kraju sam morao reći mami da malo zašuti :D
  • smayoo: Ne smiješ diktirati kako normalno pričaš. Kad se priča usporeno i jasno razdvaoja riječi, točnost je ≥90%
  • smayoo: :-D
  • Bertone: Znam, zato često i dobijem haiku od poruka :D
  • smayoo: Diktiraj poruke u vožnji. Radi sve bolje.
  • Yonkis: Bertone, ne mogu, vozim. :)

Za vikanje moraš biti prijavljen.

Prijava

Novo na Jabučnjaku

Teme

Poruke

Oglasi

Anketa

Koji Mac koristite?

Page Speed 0.49 Seconds

Provided by iJoomla SEO