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 16 sati, 38 minuta
  • Performita: Hvala Smayoo, Kako je Davor napisao ispod članka, i ja ebo čitam knjigu i lagano sve prijatelje, osobito one koji nemaju iPhone nagovaram na Signal.
  • smayoo: svima koje znam, to jest. :)
  • smayoo: skinuo i proslijedio link svima koji su još sposobni čitati knjige... :)
  • Performita: Ekipa, idemo sad svi skinuti besplatnu knjigu Guya Kawasakija da mu na administraciji stranice pokaže kako je odjeknulo u Hrvatskoj ;-)
  • dpasaric: Jest sitni sat, ali je published! :) Uživajte!
  • Yonkis: [link]
  • Yonkis: Baš baš sve!
  • Djuro genijalac: Izgleda da je BAŠ sve ovdje
  • Djuro genijalac: [link]
  • Yonkis: Hooorayyyy [link]
  • dpasaric: Radim na tome da nabavim zanimljiv monitor za tehnički review, držite palčeve da upali jer bi moglo biti mnogima zanimljivo. :)
  • Yonkis: Font je drugačiji.
  • Performita: :-)
  • dpasaric: Pogledajte naslovnicu! :)
  • dpasaric: Taaaa-daaaa! :)
  • dpasaric: Javim uskoro... :)
  • dpasaric: Ne, ovdje na Jabučnjaku!
  • Yonkis: dpasaric - Jel' u Kokolu?
  • dpasaric: Spremamo poslasticu za večeras! :)
  • ivan.ocd: Hvala za konkretni model, budem i ja pogledao za takav neki model… imam puno knjiga koje trrba analizirati i tu je onda preslab.
  • drlovric: Moj kolega koristi Cowork sa M5 Pro sa 64GB, i nema tih problema... Ocigledno ti je taj Air preslab za tu specificnu namjenu :/
  • ivan.ocd: Da, prema Claudeu trebao bi M5 Max… neki dan je bilo preko 90GB Rama koje je koristilo… pogledat ću ovo sto si napisao pa javim
  • accom: Activity monitor će ti pokazat CPU / GPU / memory usage. Pretpostavljam, da je naročito GPU pod plafonom, a možda i Memory...
  • accom: A što kaže Claude po tom pitanju?
  • ivan.ocd: Ekipa, molim vas za brzinski savjet: imam MBA s 16GB RAM-a i koristim Claude puno, osobito Cowork. Izgleda da mi tih 16GB nije dovoljno jer svako malo dobijem upozorenje o memoriji, a i grije se ko lud (M5). Trebam li prodati ovaj Mac i gledati neki Pro ili Max s vise memorije ili hlađenja ili ne? Hvala
  • hal9000: OVO: -> [link]
  • hal9000: @yonkis: ma neki kompjuterski virusi... nemam pojma što je to! @smayoo: pa ja bih baš na krstarenje... :D
  • VanjusOS: [link]
  • smayoo: Sad su ti ta krstarenja vrlo povoljna pa nemaš više izgovora. ;)
  • Yonkis: hal9000 misliš o norovirusima? Srećom besparica me opet spasila pa nisam na kruzerima :j
  • hal9000: Danas čujem ekipu kako priča o nekim virus killer-ima. Može mi netko objasniti što je to? :D
  • imjasminh: Prodano kolegi s foruma.
  • imjasminh: 750 eur - [link]
  • Yonkis: Moram priznati da je ovo dobro odrađena aplikacija: [link]
  • imjasminh: Pozdrav svima! Prodajem Apple Watch Ultra 3, 49mm Black Titanium, račun garancija. Nije ni 2 mjeseca star, bacite pogled na oglase: [link]
  • dpasaric: I previše su ih prodali s obzirom na sve... oko 600.000
  • user: pa se nije dobro prodavao
  • user: Apple Vision je očito preskup bio
  • Riba: Bas glupost od hardvera.
  • Yonkis: Ok, i nije to neuspjeh, nešto su naučili iz toga, nadam se.
  • Riba: RIP Apple Vision. - [link]
  • drlovric: Lijepo [link]
  • dpasaric: Kao jako su zabirnuti za tvoju privatnost, a istovremeno s druge strane čini sve da je potkopaju...
  • Yonkis: Ova opcija neće nikada biti dostupna u EU ili...? [link]
  • Yonkis: The iOS 26.4.2, iPadOS 26.4.2, iOS 18.7.8, and iPadOS 18.7.8 updates that Apple released today address a security vulnerability that the FBI recently used to extract Signal message previews from an iPhone even after the app was deleted.
  • drlovric: Ja sam zadnji put cuo nikada da mi neko kaze, jao jest mi spor SSD na Mac :) To samo forsiraju ovi YT recenzenti. Nama normalnim smrtnicima totalno nebitna stavka na modernim M Macovima...
  • Yonkis: Zato jer mac diktira koliko će brzo SSD raditi. Ako radi max onda ce se i trošiti max. Ovako radi laganica pa traje dulje. Ovo pričam iz guzice. Možda ima smisla.
  • ZoPaj: mjerim s blackmagic disk speed test: mac studio m4 1tb disk 6380 mb/s read, 5200 write vanjski tb5 samsung 9100pro 4tb u acasis 80gps 6430 mb/s read, 6000 write znači vanjski brži od ugrađenog mac ssd
  • jura22: Uz TB5 i dobro kućište dobiju se velike brzine prijenosa podataka, ne kao interni SSD (otprilike duplo manje).
  • jura22: RAM se ne da "odlemiti" jer je sastavni dio SoC-a.

Za vikanje moraš biti prijavljen.

Prijava

Novo na Jabučnjaku

Teme

Poruke

Oglasi

Anketa

Koji Mac koristite?

Page Speed 0.59 Seconds

Provided by iJoomla SEO