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 8 sati, 2 minuta
  • 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.
  • Ender: @cavarovobrdo: ... ili barem SSD.
  • cavarovobrdo: Nadam se da će novi CEO odlemiti RAM ;)
  • cavarovobrdo: Muštuluk: John Ternus to become Apple CEO
  • imenso: John Ternus novi CEO
  • CoffeePod: @yonkis jos me macOS 26 nije vidio a tko zna hoce li 27. Sequioa mi je toliko dobra da nemam razloga updejtati, a cijela prica sa Liquid Glass mi je odvratna.
  • Yonkis: The upcoming macOS 27 release will be compatible with Apple silicon Macs only.
  • dpasaric: Možeš uz search naći svaki
  • dpasaric: Pa zadnji intervju je na naslovnici, a ostali raspršeni tijekom godina
  • Ender: @dpasaric: a gde su ti razgovori? mislim gde se mogu naci?
  • Performita: Omogućuje lako postavljanje novih uređaja, sigurnost podataka i poslovni email bez velikog IT odjela. Cilj je da tvrtke rade jednostavnije i sigurnije na Apple uređajima.
  • drlovric: U cemu je fora sa ti Business? Imamo li mi mali smrtnici neku korist od toga ili je to samo za velike tvrtke?
  • Performita: Kalimera, Dobro jutro... ovo za Apple Business rolls zvuči kao izvrsna vijest!!!

Za vikanje moraš biti prijavljen.

Prijava

Novo na Jabučnjaku

Teme

Poruke

Oglasi

Komentari

Anketa

Koji Mac koristite?

Page Speed 0.96 Seconds

Provided by iJoomla SEO