Utilisation de PFRole

Bonjour ! J'ai fini de lire un série de cours sur l'apprentissage de l'objective-c et j'essaye donc maintenant de programmer ma propre application.


 


Cependant j'ai encore clairement du mal pour lire correctement de la documentation afin d'exploiter les classe et méthode incluses dans les divers SDK que l'on peut récupérer... Si quelqu'un connait d'ailleurs un article qui explique clairement comment se lit et s'utilise une doc je suis preneur :)


 


En attendant voici mon soucis :


J'essaye de construire une application très simple de listes, l'utilisateur se connecte avec Facebook accède aux listes qu'il a créé. Il peut en créer une nouvelle ou bien revoir une ancienne pour y apporter des modifications.


Jusque là  tout fonctionne bien !


 


Ce que je veux maintenant c'est qu'un bouton en bas d'une liste permette de déclencher un event affichant les amis Facebook de la personne qui ont aussi installé cette app. Les personnes sélectionnées ont ensuite accès à  la liste partagée par l'utilisateur.


 


J'utilise parse pour créer cette application, et dans leur doc j'ai vu qu'ils ont implémenté un objet PFRole qui permet de créer des roles de type admin modérateur etc etc.


Les liens de la doc : 


 


- https://parse.com/docs/ios/api/Classes/PFRole.html


 


- https://www.parse.com/docs/ios_guide#roles/iOS


 


 


Mais donc voilà , je n'ai aucune idée de comment je peux implémenter cette fonction dans mon code :/


Je n'ai pas bien compris le concept d'ACL non plus... ce qui n'aide certainement pas.


 


Pour l'appli, il y a en gros 4 vues :


1/ loginView


2/ homeView (qui affiche les listes de l'utilisateur)


3/ ListView (qui affiche une view pour la création d'une nouvelle liste)


4/ oldListView (qui affiche une liste déjà  créée) 


 


le code de homeView et listView  :


 


HomeView.m



#import "AAHomeViewController.h"
#import "AAListViewController.h"
#import "AAOldViewController.h"
#import "AAConstants.h"


@interface AAHomeViewController ()


@end

@implementation AAHomeViewController



-(id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
self.parseClassName = @AllLists;
self.textKey = @listName;
self.pullToRefreshEnabled = YES;
self.paginationEnabled = NO;
}
return self;
}


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

-(void)refreshTable:(NSNotification *)notification
{
[self loadObjects];
}


- (void)viewDidLoad

{

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTable:) name:@refreshTable object:nil];
// Do any additional setup after loading the view.



}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(void)objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(@error : %@", [error localizedDescription]);
}

#pragma mark - initial Query

-(PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:@user equalTo:[PFUser currentUser]];

return query;

}


#pragma mark - Segue

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@homeToOldListSegue]) {

AAOldViewController *nextVC = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

nextVC.oldList = [self.objects objectAtIndex:indexPath.row];


}
}

#pragma mark - UITableView DataSources



-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{

static NSString *simpleTableIdentifier = @Cell;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

cell.textLabel.text = [object objectForKey:@listName];

return cell;
}


#pragma Button Item

- (IBAction)addBarButtonItemPressed:(UIBarButtonItem *)sender {
[self performSegueWithIdentifier:@homeToListSegue sender:nil];
}



/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

@end


listView.m





@interface AAListViewController ()

@property (strong, nonatomic) IBOutlet UIBarButtonItem *saveBarButton;

@property (strong, nonatomic) NSMutableArray *myList;
@property (strong, nonatomic) IBOutlet UITextView *textView;
@property (strong, nonatomic) IBOutlet UITextField *titleLabel;
@property (strong, nonatomic) IBOutlet UIButton *shareButton;
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;

@property (retain, nonatomic) FBFriendPickerViewController *friendPickerController;

@property (strong, nonatomic) PFObject *theNewList;


@end

@implementation AAListViewController

-(NSMutableArray *)myList
{
if (!_myList) {
_myList = [[NSMutableArray alloc] init];
}
return _myList;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

self.textView.text = nil;


// Do any additional setup after loading the view.

}



-(void)checkForList
{
//PFQuery *queryForList = [PFQuery queryWithClassName:@Text];

}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)saveBarButtonPressed:(UIBarButtonItem *)sender {




self.theNewList = [PFObject objectWithClassName:@AllLists];

[self.theNewList setObject:self.textView.text forKey:kAAUserTextViewClassKey];
[self.theNewList setObject:self.titleLabel.text forKey:kAATextViewTitleKey];
[self.theNewList setObject:self.userFBID forKey:kAAUserListShareSelfIdKey];
[self.theNewList setObject:[PFUser currentUser] forKey:KAAUserUserKey];

for (int x=0; x < [self.myList count]; x++) {

[self.theNewList setObject:self.myList[x] forKey:kAAUserListShareKey];
}

[self.theNewList saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
[[NSNotificationCenter defaultCenter] postNotificationName:@refreshTable object:self];
[self dismissViewControllerAnimated:YES completion:nil];
}
}];
}

-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}

- (IBAction)shareWithButtonPressed:(UIButton *)sender {
self.friendPickerController = [[FBFriendPickerViewController alloc] init];
self.friendPickerController.title = @Share With...;
[self.friendPickerController loadData];
[self.friendPickerController clearSelection];
[self.friendPickerController setDelegate:self];

[self presentViewController:self.friendPickerController animated:YES completion:nil];
}

-(void)facebookViewControllerDoneWasPressed:(id)sender {


for (id<FBGraphUser> user in self.friendPickerController.selection) {
NSLog(@%@", user.objectID);


[self.myList addObject:[NSString stringWithFormat:@%@", user.objectID]];
}
NSLog(@%@", self.myList);
[self dismissViewControllerAnimated:YES completion:nil];
}

-(void)facebookViewControllerCancelWasPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}



Voilà  par avance désolé il y a surement des choses en trop dans le code vu que je fais plein d'essais pour essayer de comprendre comment ça marche, le code n'est pas le plus propre du monde...


L'idée est donc, comment dans listView, à  la création de la liste je peux passer l'utilisateur actuel ainsi que les amis Facebook comme admin ? (la gestion des droits je devrai pouvoir me débrouiller par moi même :) )


 


Merci par avance !!!


Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    août 2014 modifié #2

    Désolé, je ne connais rien sur PFRole mais, s'il ne te dérange trop, puis-je proposer les petites modifications a ton code ?



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

    if (self)
    {
    self.parseClassName = @AllLists;

    self.textKey = @listName;

    self.pullToRefreshEnabled = YES;

    self.paginationEnabled = NO;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTable:) name:@refreshTable object:nil];
    }

    return self;
    }

    - (void)dealloc
    {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@refreshTable object:nil];
    }

    - (void)refreshTable:(NSNotification *)notification
    {
    [self loadObjects];
    }

    Ayant ajouté un observateur au NSNotificationCenter, il est super important de l'enlever. En plus, si possible, de "équilibrer" le "scope" de l'ajout et l'enlèvement ; dans ce cas là  dans les méthodes initWithCoder et dealloc.


  • Ah ok merci !


    D'ailleurs, à  quoi sert ce init with coder ? Il se passe quoi en mémoire lors de son initialisation ?


    Merci :)
  • Joanna CarterJoanna Carter Membre, Modérateur


    D'ailleurs, à  quoi sert ce init with coder ? Il se passe quoi en mémoire lors de son initialisation ?




     


    UIViewController met à  disposition deux "initialisers" :


     


    - [initWithCoder:]

     

    ... qui est appelé lorsque le UIViewController est créé comme initial view controller d'un storyboard

     

    - [initWithNibName:bundle:]

     

    ... qui est appelé lorsque le UIViewController est créé en code, soit un contrôleur secondaire d'un storyboard ou d'un fichier xib.

     

    Si tu créais le contrôleur pour un xib, -[initWithCoder] ne sera pas appelé, du coup, il faut déterminer quelle méthode sera appelé et poser le code supplémentaire là  dedans.

     

    En revanche, tu pourrais créer une méthode d'initialisation supplémentaire commune qui sera appelé des deux méthodes.

     

    Comment crées-tu les contrôleurs ?
  • D'accord, merci beaucoup pour les explications :)


     


    Je construit mes contrôleurs directement depuis le storyboard !


    (Bonne ou mauvaise habitude?)


  • CéroceCéroce Membre, Modérateur

    ça se discute, mais si Joanna te pose la question, c'est pour savoir quelle méthode -init sera appelée. A priori, si le ViewController est instancié depuis un Storyboard, alors ce sera bien -initWithCoder:.


  • Joanna CarterJoanna Carter Membre, Modérateur
    août 2014 modifié #7


    Je construit mes contrôleurs directement depuis le storyboard !


    (Bonne ou mauvaise habitude?)




     


    ça dépend.


     


    Je crois que ce n'est pas une bonne idée de faire un storyboard trop compliqué. Du coup, dans mon dernier projet, j'ai 13 storyboards et 75 xibs.


     


    Le plupart des xibs sont pour les cellules pour les table views, les claviers popovers, ou les autres petites vues.


     


    Moi, je limite les storyboard aux view controllers qui font une "scène", par ex. j'ai 5 view controllers dans un storyboard pour la scène de décollage, 4 view controllers dans un autre storyboard pour la scène d'atterrissage, 9 view controllers dans un autre storyboard pour la scène masses et centrage, etc. Mais tous les view controllers dans un storyboard ne sont pas forcement liés.


     


    Je préfère de créer mes cellules dans les les xibs et les "enregistrés" avec le table view ; ainsi je peux échanger les cellules sans avoir modifier les storyboards.


  • Joanna CarterJoanna Carter Membre, Modérateur
    août 2014 modifié #8

    Petit conseil :



    @interface AAListViewController ()

    @property (weak, nonatomic) IBOutlet UIBarButtonItem *saveBarButton;

    @property (strong, nonatomic) NSMutableArray *myList;
    @property (weak, nonatomic) IBOutlet UITextView *textView;
    @property (weak, nonatomic) IBOutlet UITextField *titleLabel;
    @property (weak, nonatomic) IBOutlet UIButton *shareButton;
    @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

    @property (retain, nonatomic) FBFriendPickerViewController *friendPickerController;

    @property (strong, nonatomic) PFObject *theNewList;

    @end

    Tous les IBOutlets devraient être weak, parce que ils sont déjà  tenus en strong dans le storyboard ou xib.


    Et, c'est quoi le friendPickerController ? Il n'est pas placé sur une view dans le storyboard ?




  • Petit conseil :


    Tous les IBOutlets devrait être weak, parce que ils sont déjà  tenus en strong dans le storyboard ou xib.




     


    Pas toutes les IBOutlets, seulement les vues qui ne sont pas des principales ( sous-vues d'une vue principale). Les vues principales doivent être en strong. 

  • AliGatorAliGator Membre, Modérateur
    août 2014 modifié #10
    Pour ça l'utilitaire FauxPas (cf mon autre post ici) sait te dire si tu en as mis en strong au lieu de weak et vice-versa.


    En effet seuls les top-level views du XIB doivent être strong et dans 95% des cas le XIB est un ViewControlleur dont la UIView principale est déjà  retenue par ledit VC et tous les IBOutlets pointenent vers des subviews donc en général ils sont tous weak du coup.
  • Bonjour !


     


    petit déterrage de topic ! 


     


    Dans un premier temps, désolé de ne pas avoir répondu à  vos messages mais sachez qu'ils m'ont été très constructifs :)


     


    Du coup j'ai fait ce que j'avais à  faire... tout recommencer.


     


    Je reste avec mes controllers édités sous storyboard étant donné que pour ma petite app j'en utilise au final "seulement" 5 et, qu'à  mon avis, il vaut mieux que je me concentre sur l'apprentissage des data model de base afin d'avoir une appli clean qui sera simple à  faire évoluer plutôt que d'apprendre à  placer mes boutons au pixel près en ligne de code :)


     


     


    Je devrais avoir fini l'app dans la semaine je vous balancerai un lien git si jamais vous voulez checker ce que j'ai écrit et me faire un retour.


     


    Cordialement,


     


    Alex !

Connectez-vous ou Inscrivez-vous pour répondre.