Domanda

Questa è la mia prima volta con IB, ma dopo aver trascorso un paio di giorni intime con esso credo sto cominciando a capirlo. Questo è solo il mio modo di dire che potrei essere vista qualcosa di semplice qui:

Ho creato un UIPickerView e si unì alla sua DataSource e oggetto delegato in IB (entrambe le Classi diverse nel mio caso). Questo permette al selettore di presentarsi quando si esegue l'applicazione, il che è molto incoraggiante quando non ha mostrato fino in qualsiasi corse di prova precedenti. ;) Comunque, quando ho scorrere l'UIPickerView, il programma si blocca, e non riesco a trovare alcuna del mio codice fa riferimento nel backtrace. Dopo un po 'di risoluzione dei problemi, credo di aver ristretto il crollo di due casi distinti, per quanto riguarda il backtrace è interessato:

il valore di ritorno di -pickerView: numberOfRowsInComponent:> il numero di righe visualizzato

  • Arresto anomalo dell'applicazione non appena un movimento è iniziato per selezionare una nuova riga
  • Arresto anomalo dell'applicazione se si tenta di utilizzare -selectRow: inComponent: animato:

backtrace (ignorando principale):

#0  0x955e8688 in objc_msgSend ()
#1  0x0167bea8 in -[UIPickerView table:cellForRow:column:reusing:] ()
#2  0x016773c1 in -[UIPickerView table:cellForRow:column:] ()
#3  0x017fef53 in -[UITable createPreparedCellForRow:column:] ()
#4  0x018077c8 in -[UITable _updateVisibleCellsNow] ()
#5  0x018027cf in -[UITable layoutSubviews] ()
#6  0x03ac42b0 in -[CALayer layoutSublayers] ()
#7  0x03ac406f in CALayerLayoutIfNeeded ()
#8  0x03ac38c6 in CA::Context::commit_transaction ()
#9  0x03ac353a in CA::Transaction::commit ()
#10 0x03acb838 in CA::Transaction::observer_callback ()
#11 0x007b8252 in __CFRunLoopDoObservers ()
#12 0x007b765f in CFRunLoopRunSpecific ()
#13 0x007b6c48 in CFRunLoopRunInMode ()
#14 0x000147ad in GSEventRunModal ()
#15 0x00014872 in GSEventRun ()
#16 0x0168a003 in UIApplicationMain ()

il valore di ritorno di -pickerView: numberOfRowsInComponent:

  • Arresto anomalo dell'applicazione dopo il movimento cessa e viene selezionata la riga
  • L'applicazione non incidente, se si tenta di utilizzare -selectRow: inComponent: animato:

backtrace (ignorando principale):

#0  0x955e8688 in objc_msgSend ()
#1  0x0167700d in -[UIPickerView _sendSelectionChangedForComponent:] ()
#2  0x017f4187 in -[UIScroller _scrollAnimationEnded] ()
#3  0x016f732c in -[UIAnimator stopAnimation:] ()
#4  0x016f7154 in -[UIAnimator(Static) _advance:] ()
#5  0x00017739 in HeartbeatTimerCallback ()
#6  0x007b7ac0 in CFRunLoopRunSpecific ()
#7  0x007b6c48 in CFRunLoopRunInMode ()
#8  0x000147ad in GSEventRunModal ()
#9  0x00014872 in GSEventRun ()
#10 0x0168a003 in UIApplicationMain ()

I miei delegato e origine dati implementazioni seguono:

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return (NSInteger)3;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return (NSInteger)4;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
  //it will probably be better to use the method following when creating the rows, so I can better customize it 
    return @"strings";
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    NSLog(@"selected a row");
}
È stato utile?

Soluzione

Indagato documentazione di Apple un po 'e si è rivelato la mia ipotesi precedente. Da Guida alla programmazione delle risorse :

  

Gli oggetti presenti nel file vengono creati pennino   con un conteggio di trattenere 1 e poi   autoreleased. Come si ricostruisce il   gerarchia di oggetti, però, UIKit   ristabilisce connessioni tra il   oggetti utilizzando il setValue: Forkey:   metodo, che utilizza il disponibile   metodo setter o conserva l'oggetto   predefiniti se nessun metodo setter è   a disposizione. Se si definisce sbocchi per   oggetti Pennino-file, si dovrebbe anche   definire un metodo setter per accedere   quella presa. setter per   sbocchi dovrebbero mantenere i loro valori,   e setter per prese   contenente oggetti di primo livello deve   mantenere i loro valori per impedire loro   dall'essere deallocato. Se non   memorizzare gli oggetti di livello superiore a   punti vendita, si devono mantenere sia la   restituito dalla   loadNibNamed: Proprietario: opzioni: metodo o   gli oggetti all'interno della matrice di   evitare che tali oggetti dall'essere   rilasciato prematuramente.

Quindi, gli oggetti di livello superiore vengono creati autoreleased ed è necessario mantenere nel codice. C'è anche descritto metodo consigliato per gestire che:

  

sia per Mac OS X e UIKit, il   metodo consigliato per gestire il   oggetti di alto livello in un file pennino è a   creare sbocchi per loro nel file di   oggetto del proprietario e quindi definire setter   metodi per trattenere e rilasciare quelle   oggetti come necessario. setter danno   si un luogo appropriato per includere   il codice di gestione della memoria, anche in   situazioni in cui utilizza l'applicazione   raccolta dei rifiuti. Un modo semplice per   implementare i metodi setter è quello di   utilizzare la sintassi @property e lasciare che il   compilatore li crea per voi.

Ho provato questo approccio in un codice di esempio - punti vendita definiti per delegato e origine dati oggetti in classe proprietario del file e li collegato in IB. E nel file di classe proprietaria definita una proprietà per quei punti vendita:

@property (nonatomic, retain) NSObject<UIPickerViewDelegate>* myDelegate;
@property (nonatomic, retain) NSObject<UIPickerViewDataSource>* mySource;

Ha funzionato bene.

Altri suggerimenti

Dal tuo ultimo commento può derivarne che il delegato per l'UIPickerView viene eliminato e dopo che i vostri riferimenti picker.delegate a una memoria non valida ...
Possibili soluzioni:

  1. Verificare che l'oggetto delegato sarà valido, mentre si sta utilizzando il tuo raccoglitrice - mantenere da qualche parte e rilasciare quando il selettore viene distrutto (per esempio in vista padre metodo di controllo dealloc del selettore)
  2. Nella proprietà delegato il metodo dealloc set del selettore a zero - deve rimuovere l'incidente, ma sarà anche possibile interrompere la gestione di eventi Picker.

Hai detto delegato e origine dati del tuo pickerView sono classi differenti. Dove stai impostando questi in su? Nella tua XI ter o l'impostazione dei collegamenti programatically? E 'possibile che gli oggetti creati per il delegato e origine dati non vengono mantenute?

Quindi, la prossima volta quando hanno bisogno di essere fatto riferimento, che sono stati rilasciati e si ottiene un'eccezione.

Perché si desidera utilizzare diversi oggetti come delegato e origine dati? Perché non implementare nella tua viewcontroller sé?

Direi senza indagini troppo dettagliata, che si dovrebbe assicurarsi che ogni oggetto in IB è collegato attraverso le proprietà che conservano, al proprietario del file. Questo è il motivo numero uno che ho visto per gli arresti. Non appena qualcosa si riferisce a, o addirittura non indicato, ma non un bambino di proprietario del file, in qualche modo, provoca un incidente. Inizia con nessuna connessione, nessun delegati, oltre a quelli necessari per rendere questa catena. Se questo funziona senza un incidente, fare un collegamento, quindi verificare, quindi ripetere. Scorrendo gli arresti avvengono quasi sempre perché qualcosa è stato autoreleased.

Se avete trovato l'oggetto B senza utilizzare [[B alloc] init] aspetta che sia andato dopo il ricavato del ciclo di esecuzione. (Dopo la prima volta si è in grado di toccare la visualizzazione). La cura è quello di raccontare l'oggetto B per mantenere, in genere dopo aver fatto un riferimento ad esso in un altro oggetto,

-(void)connectTo:(B*)b {
     self.myReference = b
     [B retain];
}

L'altra soluzione a questo è attraverso IB. nelle intestazioni di fare questo:

@interface a : NSObject{
    id<UIPickerViewDelegate> myReferenceToDelegate;
}

@property(nonatomic, retain) IBOutlet id<UIPickerViewDelegate> myReferenceToDelegate

@end

Allora avete bisogno di andare in Interface Builder, e trascinare una connessione da myReferenceToDelegate sul oggetto A all'oggetto B. Una volta fatto questo, fare proprietario assicurarsi di file ha questo tipo di collegamento ad una.

thiese connessioni Interface Builder può essere difficile, perché non dicono molto circa il problema, e non fare tanto quanto si potrebbe cosa dietro le quinte.

Buona fortuna risolvere questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top