ios ARC tabel de acces rău

pentru vizualizarea mea de masă am următorul lucru (parafrazat)

.h

@interface OptionsView : UIView 

@property (nonatomic, retain) NSArray *dataSource;

.m

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {

        ...

        self.dataSource = [NSArray arrayWithObjects:options, sections, sponsor,  nil];
    }
    return self;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(self.dataSource) {
        NSArray *ds = [self.dataSource objectAtIndex:indexPath.section];
        NSDictionary *d = [ds objectAtIndex:indexPath.row];
        ActionBlock a = [d objectForKey:ACTION];//<-- Thread 1: EXC_BAD_ACCESS (code=2, address=0x802)
        if(a != nil) a();
    }
}

Puteți vedea că în didSelectRowAtIndexPath primesc un EXC_BAD_ACCESS dar nu sunt sigur de ce. Pentru că folosesc arc, nu este o problemă de zombie (deja verificată).

Using breakpoints I see that the self.dataSource exists after it's initialized, but not later when it's needed. It doesn't show up as either, it's just white space. Also, this works in debug but not in release so what does that mean?

** EDIT adăugând o captură de ecran **

You will notice that neither ds or d show up.. odd? xcode debug

1
Nu sunt sigur dacă este același în xcode, dar știu că de la dezvoltarea în Visual Studio, de asemenea, simbolurile de depanare în versiunile build nu sunt deloc de încredere
adăugat autor Dan F, sursa
@ a fost adăugat tot ecranul. Probabil va adăuga o anumită claritate situației mele.
adăugat autor Jacksonkr, sursa
Nu mi-ar face griji cu privire la absența ds sau d după accidentul. Încercați să puneți puncte de întrerupere și să le examinați înainte de accident. Ați încercat să puneți un breakpoint înainte de accident și să priviți conținutul ds și d atunci? Sau pune în declarații NSLog? Ar fi fascinant să vezi rezultatele NSLog (@ "d =% @", d).
adăugat autor Rob, sursa
Puteți înregistra valorile ds și d ? Un alt ajutor ar fi să înfășurați linia de eșec într-un bloc @ try/@ catch și să examinați descrierea excepției și callStackSymbols.
adăugat autor Phillip Mills, sursa
Acest lucru nu este probabil o soluție fixă, dar cu ARC se utilizează tipic slab/puternic, mai degrabă decât atribuiți/păstrați pentru proprietăți
adăugat autor Patrick Hernandez, sursa
De asemenea, dacă se prăbușește pe [d objectForKey: ACTION]; apoi "self.dataSource" și "ds" ar trebui să existe încă.
adăugat autor Patrick Hernandez, sursa

2 răspunsuri

Deci sunt două locuri pe care le pot vedea care ar putea provoca problema. Mai întâi, ce este ACTION ? Este un fel de NSString? Vreau doar să vă asigurați că utilizați un obiect cheie valid. În al doilea rând, (și mai probabil problema), se pare că ActionBlock este un fel de bloc de cod pe care îl stocați într-o matrice de colectare. Copiați acel bloc înainte de al stoca în matrice/dicționar? Trebuie să copiați orice bloc pe care intenționați să îl păstrați (depozitând) mai mult decât domeniul în care a fost creat. Acest lucru este ușor de făcut. De exemplu:

void (^NewBlock)(void) = [^{
    ....code....
} copy];

alternativ:

void (^NewBlock)(void) = ^{
    ....code....
};

[dictionary setObject:[NewBlock copy] forKey:ACTION]; //Assuming #define ACTION @"action"

Acest lucru se copiază pe heap astfel încât să poată fi stocat. Dacă nu îl copiați, veți obține BAD_EXC_ACCESS oricând încercați să faceți referire la blocul din afara domeniului în care a fost creat.

2
adăugat

Se pare că utilizați un UIViewController în locul unui UITableViewController. Dacă îmi amintesc corect, trebuie să mergeți la inspector și să trageți delegatul și sursa de date de la tableView la UIViewController. Nu-mi amintesc exact și nu sunt pe calculatorul meu, dar sunt sigur că am făcut-o de mai multe ori înainte de a începe să folosesc un UITableViewController pentru fiecare tableView pe care îl am.

Oh, și nu aș folosi dataSource ca un nume pentru matricea ta. Doar pentru a preveni conflictele de numire.

0
adăugat
Da, desigur, orice obiect poate fi. Spun doar că oricare ar fi aceste obiecte, tableView trebuie să știe despre ele. De aceea, conexiunile trebuie făcute. Din nou, a trecut mult timp de când am făcut-o în acest fel, ca să fiu ruginită.
adăugat autor Marcal, sursa
Orice obiect poate fi sursa de date și poate fi delegat pentru o vizualizare de tabel. Nu aveți nevoie de un controler de afișare a mesei.
adăugat autor jrturton, sursa
iOS dezvoltatori, România — Moldova
iOS dezvoltatori, România — Moldova
21 participanți

Parteneri: ciupacabra.com, @php_ro, @js_ro, @node_ro, @seo_ro Android: @ro_android