2011-08-22 16 views
21

Esecuzione di un test per l'acquisto dell'app in ingresso (prima volta durante gli acquisti in app). Ottengo EXC_BAD_ACCESS sulla terza linea di questo codice:EXC_BAD_ACCESS durante test di acquisto in app

SKPayment *payment = [SKPayment paymentWithProduct:electronicProd]; 
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; 
    [[SKPaymentQueue defaultQueue] addPayment:payment]; 

L'ha l'IBAction per un pulsante. electronicPack è dichiarato nell'intestazione come SKProduct. Ha lanciato alcuni NSlog nei prodottiRisposta didReceiveResponse e quando il prodotto è stato richiesto (in viewDidLoad) e hanno mostrato che stava recuperando correttamente il prodotto e memorizzandolo in electronicPack. Definito ElectronicPack come [[request.products] objectAtIndex: 0] nella pagina didReceiveResponse. Quindi sì Ecco dove sono, non so cosa fare. Qualsiasi aiuto è apprezzato.

UPDATE: Fisso a sinistra casualmente nel codice che è stato l'aggiunta di un osservatore delle transazioni in più lol

+0

Nella definizione electronicProd, hai chiamato il trattenere il messaggio? Ogni evento è racchiuso in un pool di autorelease, se hai istanziato il tuo oggetto con il suo metodo stat statico, l'oggetto verrà rilasciato una volta che il metodo viewDidLoad sarà terminato. – andreamazz

+0

stai chiedendo se mi è piaciuto: electronicPack = [SKProduct alloc] init] ? la risposta è no. Se questo non è quello che stai chiedendo, non sono sicuro di quello che stai dicendo, sono un po 'nuovo in questa partita. lol –

+0

Im non troppo buono con l'intera gestione della memoria, roba di proprietà. e tutto questo. Ho solo programmato per circa un mese e non ho ancora capito bene. Darei un assaggio e vedere se risolve qualcosa EDIT: Implementato il materiale self.elec..etc e nessun cambiamento. ricevendo ancora l'errore –

risposta

9

È necessario mantenere l'oggetto che si sta creando

- (void)viewDidLoad { 
    //... stuff 
    SKProduct* electronicProduct = //... 
    [electronicProduct retain]; 
    //... otherstuff 
} 

viewDidLoad è avvolto dal sistema in una piscina autorelease , paymentWithProduct: restituisce un oggetto autorelease. Al termine di viewDidLoad, tutti gli oggetti autorelease vengono rilasciati, ecco perché si ottiene un accesso di memoria non valido quando si tenta di accedervi in ​​seguito.

39

Ho avuto lo stesso problema, la mia soluzione era quella di chiamare

[[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 

di lasciare l'In-App Store nella mia app. Forse aiuterà qualcuno in futuro.

+1

Hai salvato la mia giornata! Grazie! –

+0

Ohhoo .. Ottimo .. Grazie –

+0

Ha funzionato anche per me, grazie! – JustMe

26

Sembra che il problema sia di provare ad aggiungere un osservatore di transazioni prima di rimuovere quello precedente. Aggiungere il seguente al controller per risolvere questo problema:

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; 
} 

Spero che questo aiuti!

+1

Questa è stata la risposta per me. Ancora valido con Xcode 6.3 e iOS 8.3 – Paul

+2

Eccellente, grazie !! Per me anche questo ha funzionato, usando il codice di Mihael Isaev (sotto) e inserendolo in ViewDidDisappear. – Pieter

2

Ho avuto lo stesso errore, molto semplice da risolvere davvero. Nel mio file di intestazione ho avuto uno SKProduct dichiarato:

@property SKProduct *product; 

ho appena cambiato in:

@property (retain) SKProduct *product; 

e tutto funziona bene. Spero che questo aiuti qualcuno.

+0

sembra risolvere il mio problema. – NSGodMode

11

Mr.T answer è la soluzione migliore!

a Swift Io chiamo questo removeTransactionObserver qui:

deinit { 
    SKPaymentQueue.defaultQueue().removeTransactionObserver(self) 
} 
+0

Dove fai il deinit !? il file appdelegate !? – Learn2Code

0

Ho lo stesso problema, la mia soluzione era quella di chiamare [[SKPaymentQueue defaultQueue] removeTransactionObserver: self];

sul negozio di transazione osservatore finitura/fallito/callback completati

1

Se si sta creando una classe dedicata per SKPaymentTransactionObserver non dimenticare che essa deve essere mantenuta.

ho ottenuto l'errore prima di rendersi conto questo, ecco un esempio in AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 
    var myTransactionObserver: MyTransactionObserver! 


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     // don't 
     let myTransactionObserver = MyTransactionObserver() 

     // do 
     myTransactionObserver = MyTransactionObserver() 

     SKPaymentQueue.default().add(myTransactionObserver) 

     return true 
    } 

    // ... 
} 
Problemi correlati