2010-11-06 15 views
0

Je poste des entrées à partir d'un magasin de données de base persistant de manière asynchrone vers un serveur Web. Je souhaite supprimer chaque objet géré associé après un post réussi.Objectif c Aide sur les délégués personnalisés et les données asynchrones

Mon problème est que je suis en train de remplir le magasin et de créer des postes de façon à ce que je ne puisse pas effectuer une opération de publication/suppression en série. Y at-il un moyen de marquer un objet pour la suppression jusqu'à ce qu'il soit associé connectionDidFinishLoading appel a été fait, puis supprimez-le?

Je suppose également qu'en utilisant NSURLRequests asynchrone, l'application engendre plusieurs NSURLConnections et les exécute simultanément. Ai-je tort dans cette hypothèse?


(Mise à jour) Grâce au conseil d'Uberhamster, j'ai essayé d'utiliser des délégués mais j'échoue. C'est ainsi que je vais aborder ce problème. J'ai déclaré un protocole dans la classe qui gère les messages car c'est là que connectionDidFinishLoading vit.

@protocol postDelegate 
@optional 
- (void)postCompleted; 
@end 

@interface makePosts : NSObject { 
    //... 
    id <postsDelegate> delegate; 
} 

@property (nonatomic, assign) id <postsDelegate> delegate; 
//... 
@end 

@implementation makePosts 
    @synthesize delegate; 
    //... 
    - (void) connectionDidFinishLoading { 
     [delegate postCompleted]; 
    } 
    //... 
@end 

Et dans la classe qui saisit les données de la mémoire persistante et engendre NSURLConnections ce que je fais:

@interface myClass <postsDelegate> 
    //... 
    makePosts* makePostsObject; 
@end 

@implementation myClass 
- (void) batchPost { 
     //... 
     for(NSManagedObject* obj in items) { 
      makePostsObject = [[makePosts alloc] init]; 
      makePostsObject.delegate = self; 
      [makePostsObject setEntryName:[obj valueForKey:@"name"]]; // set reference here 
      NSString* post_data = [NSString stringWithString:[self createXMLPost:obj]]; 
      [makePostsObject postdata:[obj valueForKey:@"name"]]; 
      [makePostsObject release]; 
    } 


     - (void) postCompleted 
     { 
      NSLog(@"posted entry for: %@", makePostsObject.entryName); 
     } 

@end 

Je pense que ce que je fais mal fait myClass le délégué? postCompleted est appelé pour chaque publication que je fais, mais la référence est chaque fois pour le dernier message. Y a-t-il un moyen de récupérer le délégué de la fonction de rappel?

Répondre

2

D'abord, les classes devraient commencer par une lettre majuscule. Les commencer avec une lettre minuscule les rend difficiles à lire. En second lieu, @Uberhamster suggérait vous implémentez un délégué NSURLConnection comme suit:

@interface MyUploadDelegate : NSObject 

@property (nonatomic, retain) NSManagedObject *postObject; 

@end 

@implementation MyUploadDelegate 

@synthesize postObject; 

- (void)dealloc 
{ 
    [postObject release], postObject = nil; 
    [super dealloc]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection*)connection 
{ 
    //Connection is done, delete the object 
    [[[self postObject] managedObjectContext] deleteObject:[self postObject]]; 
} 

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error 
{ 
    //Deal with the error 
} 

@end 

Ensuite, votre code doit simplement faire:

for (NSManagedObject *postObject in items) { 
    MyUploadDelegate *delegate = [[MyUploadDelegate alloc] init]; 
    [delegate setPostObject:postObject]; 

    NSURLRequest *request = ...; 
    [NSURLConnection connectionWithRequest:request delegate:delegate]; 
} 

Vous devez également avoir une certaine rétention des délégués afin que vous puissiez garder piste d'eux et les nettoyer (l'exemple de code ci-dessus fuit délégués).

+0

La libération automatique de l'objet délégué à la création a pris en charge les fuites de mémoire.MyUploadDelegate * delegate = [[[MyUploadDelegate alloc] init] autorelease]; J'ai testé et ne peux pas trouver des cas de pointe où il échouerait. – CodeWombat

+0

Sauf que vous n'avez aucun moyen d'annuler une connexion, par exemple lorsque vous passez en arrière-plan ou lorsqu'un appel arrive. Garder le suivi du délégué et la connexion est un bon citoyen sur l'appareil. –

1

Vous pouvez instancier un objet délégué pour chaque requête NSURL que vous lancez, et cet objet délégué peut avoir une référence à l'élément de données principal en cours de traitement. Après cela, vous pouvez simplement supprimer l'objet de données de base correspondant du magasin dans le rappel, et tout devrait être dandy.

(En réponse à votre dernier paragraphe, je crois que vous avez raison dans cette hypothèse)

+0

Merci pour le conseil, j'ai essayé de mettre en place des délégués, mais je suis coincé avec la logique, j'ai mis à jour ma question avec ce que j'ai fait jusqu'à présent. – CodeWombat

+0

La réponse de Marcus ci-dessous semble excellente, et devrait vous aider. :) Malheureusement, je n'ai pas la réputation-fu pour commenter sa solution, mais je voulais ajouter que vous pouviez libérer les objets MyUploadDelegate dans connectionDidFinishLoading: et la connexion ... didFailWithError:, si vous voulez éviter les objets qui fuient. L'un ou l'autre sera appelé, donc vous pouvez être sûr qu'il sera finalement libéré. –

+0

J'ai intentionnellement évité d'ajouter cette autorelease parce que vous libérer est moche. Les délégués (et les connexions) devraient vraiment être suivis et nettoyés à l'extérieur. –