Forum
Dobrodošao, Gost
Molimo Prijava ili Registracija.    Izgubljena lozinka?
Objective-C pitanjce
Idi na dno Označenih tema: 0
TEMA: Objective-C pitanjce
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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'
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 451
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 32  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
Evo ispravio sam, ali nije bilo do toga krivo sam copy paste. Ali stvarno izgleda katastrofa za čitat.

Najbitnije je dio onaj

- (void) operationGWS_LeasingSoapOperation*)operation completedWithResponseGWS_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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 680
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 102  
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?
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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) operationGWS_LeasingSoapOperation *)operation completedWithResponseGWS_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)initWithBindingGWS_LeasingSoap *)aBinding delegateid<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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 451
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 32  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 680
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 102  
Tko točno u cijeloj ovoj priči poziva [NSURLRequestInternal operation:completedWithResponse:]?
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 680
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 102  
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?
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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.
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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.
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 451
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 32  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 451
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 32  
Cool,

i da sve bude savršeno:

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

   [contr release];

   [super dealloc];
}
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 89
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 5  
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)...
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Poruka: 451
graphgraph

Objective-C pitanjce prije 2 Godina, 2 Mjeseci Karma: 32  
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
| Administrator je onemogućio pisanje neprijavljenim korisnicima.
Idi na vrh

Novo na Jabučnjaku

Komentari

Prijava

Vikalica™

Poruka primljena: pred 9 sati, 56 min
  • smayoo: Samo hrabro, john_st! Sjeti se da uvijek može gore! ;)
  • boriskr: @john_st-želim ti da što prije možeš ležati kako hoćeš: na trbuhu, na glavačke, na oba ramena istovremeno. Puno sreće!
  • john_st: @boris - da, samo jednom. i to šta je najčudnije od svega, na ono na kojem sam operiran :eek: kad se okrenem na lijevi bok imam osjećaj ko da mi iznutrice plešu i dođe mi muka.
  • H2O: nekoliko puta ponovljeno 'clear browsing data' + quit chrome + start chrome izgleda da je izlječilo boljku
  • H2O: Riba, probao sam resetirati safari i obrisati cache, ali u chrome i dalje ne radi. u safariju ide ok, u chrome sve normalno osim na jabučnjakovim stranicama blokirava i izbacuje "Aw, Snap!"
  • Nikola_Kala: da ali ne nadjem ja to xD meni treba ako znas xD gledo sam ali ne nadem a i neda mi se traziti samo me zanima zna li tko !
  • BB: Ima, stavila sam ti tamo link :)
  • Nikola_Kala: ima koga ?
  • boriskr: john_st, samo na jednom?
  • H2O: jučer sam čuo na jednom predavanju da postoji nekakav problem oko virtualbox-a + "ostali OS" kad je Mac u pitanju jer se na Apple strojevima po licenčnim pravima ne smije koristiti non-Apple software. koliko ima u tome istine?
  • DrAle: @BB onda imaš pravo. Nedostaje odgovor za tvoj slučaj.
  • BB: @DrAle: ne slažem se - ne kupujem ništa, a odobri ih onaj tko ih nudi (npr. Cydia, BigBoss itd.). I nije to samo moj slučaj :)
  • DrAle: @BB OK, nisam baš u toku s time, znam da nekada nije bilo tako. BTW imaš odgovor "Da, zbog kupovine neodobrenih aplikacija", tu bi spadao tvoj slučaj. Nisu odobrene, no valjda mogu biti legalne.
  • BB: @DrAle: Jailbreak je legalan, odobravao ga Apple ili ne, a time onda i programi...
  • john_st: jeeeej mogu spavati na boku 8) a i rame popušta :roll:
  • DrAle: @BB da, u stvari je zanimljivo pitanje jesu li besplatni legalni programi legalni ako se skidaju sa kanala kojeg Apple nije odobrio
  • BB: Da, zbog besplatnih LEGALNIH programa :)
  • Riba: Problem sa logiranjem i Safarijem je poznat godinama.
  • Boškardin: :) Reset Safari i Empty Casche
  • amsterdamxx: @cariblanco..i meni Safari stalno trazi ponovo logovanje...na Snou...
  • DrAle: @BB sada me baš zanima koji bi to odgovor bio, a koji nije među ponuđenima?
  • BB: Ova dolje anketa ne nudi odgovor koji bih ja kliknula :(
  • Riba: H2O, probaj Reset Safari i obrisi cache.
  • cariblanco: ok ty
  • smayoo: koristi neku drugu surfalicu umjesto Safarija
  • cariblanco: svaki put kad dođem na forum,moram se logirati...jel to normalno ili ne?
  • cariblanco: pozdrav svima iz vruće costarice
  • H2O: ove tri tockice su razne stranice unutar foruma
  • H2O: i svugdje je »Klikni!«
  • H2O: crveni popis na Console je dugačak, ali na svima isto: Failed to load resource: the server responded with a status of 404 (NOT FOUND)

Moraš biti prijavljen!

Prisutni jabučari

Prijavljeni: CooL, Dr. Beast, jzelko, kufalo, LukaSnow, noviruses, postar, rusty, teebz1978, zabac
Anonimaca: 53

Anketa

Jailbreakate li svoj iOS uređaj?

Apple novosti


3.7087