2 votes

Comment puis-je obtenir un NSArray à partir d'un bloc égal à un membre de données de classe ?

- (void)viewDidLoad
{
    [super viewDidLoad];
    [VenueManager searchNear:@"Orlando"
                      onLoad:^(NSArray *objects) {
                          self.locationObjects = objects;
                          [self.tableView reloadData];
                   } onError:^(NSError *error) {
                      NSLog(@"%@", error);
    }];

}

Ce code se trouve dans la méthode viewDidLoad de ma classe UITableViewController. C'est le point de départ de l'utilisation de RestKit pour analyser un fichier JSON provenant de FourSquare. Je m'arrachais les cheveux parce que je n'arrivais pas à faire apparaître les objets dans ma vue tableau jusqu'à ce que je mette [self.tableView reloadData] ;. Sans cet appel, l'application ne s'affiche même pas dans la vue tableau. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) car après l'exécution du bloc, les locationObjects seraient nuls.

Auparavant, lorsque je déboguais, le paramètre self.locationsObjects = objects fonctionnait lorsque j'étais dans le bloc (je ne suis pas très familier avec les blocs, soit dit en passant). Dès que je sortais du bloc, le débogueur disait que locationObjects était nul, même s'il avait dit qu'il y avait 30 objets, tout comme les objets le faisaient lorsque j'avais un point d'arrêt à l'instruction d'affectation.

Quelqu'un peut-il m'aider à comprendre ce qui se passe ici ?

Informations supplémentaires :

Actuellement, tout fonctionne, ou semble fonctionner, ma table est remplie avec les objets demandés dans le document JSON. À l'origine, je faisais exactement la même chose dans un ViewController normal et j'essayais de définir l'attribut objects du bloc égal à locationObjects . Ensuite, en utilisant un prepareForSegue j'essayais de passer la méthode locationObjects au tableViewController selon la méthode standard que j'ai apprise dans de nombreux tutoriels. J'obtiens une erreur SIGBAT. Le thread se terminait à cause d'un sélecteur non reconnu envoyé au contrôleur de vue de la table. En déboguant, j'ai découvert que locationObjects pourrait être nul dans la méthode prepareForSegue. Voici le code du fichier viewController.

Je recevrais aussi un avertissement ici locationTableViewController.locationObjects = self.locationObjects; disant quelque chose à propos de l'assignation d'un pointeur de type NSArray à un NSArray fort, ou quelque chose comme ça ( j'ai depuis changé beaucoup de choses en essayant de faire fonctionner le code et j'ai supprimé quelques actifs du storyboard, donc je ne suis pas sûr à 100% de la formulation).

@implementation CoffeeShopViewController

@synthesize venueCountLable = _venueCountLable;
@synthesize locationObjects = _locationObjects;

- (void)viewDidLoad
{
    [super viewDidLoad];
    [VenueManager searchNear:@"Orlando"
                      onLoad:^(NSArray *objects) {
                          self.venueCountLable.text = [NSString stringWithFormat:@"%d", objects.count];
                         self.locationObjects = objects;
    } onError:^(NSError *error) {
        NSLog(@"%@", error);
    }];

}

- (void)viewDidUnload
{
    [self setVenueCountLable:nil];
    [super viewDidUnload];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"locationTableSegue"])
    {
        LocationTableViewController *locationTableViewController = segue.destinationViewController;
        locationTableViewController.locationObjects = self.locationObjects;
    }
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

@end

1voto

Nirav Bhatt Points 2850

Essayez :

 @property (nonatomic, copy) NSArray *locationObjects;' 

Edit sur la raison pour laquelle cela fonctionne :

Pour être honnête, je ne connais pas vraiment la raison sous-jacente pour laquelle cela fonctionne et ne fonctionne pas. Lorsque j'ai constaté le problème, il m'a semblé que strong étant l'équivalent de retain, l'insertion de copy au lieu de strong pouvait garantir que les locationObjects ne seraient pas annulés. En y repensant, je me suis dit que mon hypothèse pouvait être erronée - retain signifiait littéralement "Ne libérez pas cet objet parce qu'il y a maintenant une autre personne qui le détient".

Cela, cependant, fonctionne un peu différemment. Voir este .

Ce que dit la réponse de Malaxeur et les commentaires ci-dessous pourrait éventuellement s'appliquer à NSArray dans votre exemple - malgré la forte propriété de locationObjects, ce qui vous est donné est une référence aux objets NSArray (un NSMutableArray*) au lieu d'une copie de celui-ci. Une fois hors de portée (fin de bloc), il n'est plus utilisable, et ARC le revendique. L'utilisation de la copie l'oblige à créer un autre espace en mémoire uniquement pour les locationObjects, qui resterait à jamais jusqu'à ce que vous le libériez.

Je ne considère toujours pas qu'il s'agit d'une explication parfaite, car je n'ai jamais compris les blocs dans leur intégralité. Je garde la porte ouverte à tous ceux qui en savent plus, et je la remplirai dès que je recevrai quelque chose d'utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X