Aggiungere informazioni di accesso a un'app iOS usando una libreria di terze parti con l'API Graph mediante l'endpoint v2.0Add sign-in to an iOS app using a third-party library with Graph API using the v2.0 endpoint

La piattaforma delle identità Microsoft usa standard aperti, ad esempio OAuth2 e OpenID Connect.The Microsoft identity platform uses open standards such as OAuth2 and OpenID Connect. Gli sviluppatori possono usare qualsiasi libreria che desiderano integrare ai servizi.Developers can use any library they want to integrate with our services. Per aiutare gli sviluppatori a usare la piattaforma con altre librerie, sono state scritte alcune procedure dettagliate come questa, che illustrano come configurare le librerie di terze parti per connettersi alla piattaforma delle identità Microsoft.To help developers use our platform with other libraries, we've written a few walkthroughs like this one to demonstrate how to configure third-party libraries to connect to the Microsoft identity platform. La maggior parte delle librerie che implementano la specifica OAuth2 RFC6749 possono connettersi alla piattaforma delle identità Microsoft.Most libraries that implement the RFC6749 OAuth2 spec can connect to the Microsoft identity platform.

Con l'applicazione creata in questa procedura dettagliata, gli utenti possono accedere alla propria organizzazione e cercare altro all'interno dell'organizzazione tramite l'API Graph.With the application that this walkthrough creates, users can sign in to their organization and then search for others in their organization by using the Graph API.

Se non si ha familiarità con OAuth2 o OpenID Connect, gran parte di questo esempio risulterà poco chiara.If you're new to OAuth2 or OpenID Connect, much of this sample configuration may not make sense to you. Per informazioni, è consigliabile leggere Protocolli della versione 2.0: flusso del codice di autorizzazione di OAuth 2.0.We recommend that you read v2.0 Protocols - OAuth 2.0 Authorization Code Flow for background.

Nota

Per alcune funzionalità della piattaforma che trovano espressione negli standard OAuth2 o OpenID Connect, ad esempio l'accesso condizionale e la gestione criteri di Intune, è necessario usare le librerie di identità open source di Microsoft Azure.Some features of our platform that do have an expression in the OAuth2 or OpenID Connect standards, such as Conditional Access and Intune policy management, require you to use our open source Microsoft Azure Identity Libraries.

Non tutti gli scenari e le funzionalità di Azure Active Directory sono supportati dall'endpoint v2.0.The v2.0 endpoint does not support all Azure Active Directory scenarios and features.

Nota

Per determinare se è necessario usare l'endpoint v2.0, leggere le informazioni sulle limitazioni v2.0.To determine if you should use the v2.0 endpoint, read about v2.0 limitations.

Scaricare il codice da GitHubDownload code from GitHub

Il codice per questa esercitazione è salvato su GitHub.The code for this tutorial is maintained on GitHub. Per seguire la procedura è possibile scaricare la struttura dell'app come file con estensione zip o clonare la struttura:To follow along, you can download the app's skeleton as a .zip or clone the skeleton:

git clone --branch skeleton git@github.com:Azure-Samples/active-directory-ios-native-nxoauth2-v2.git

È anche possibile scaricare l'esempio e iniziare subito:You can also just download the sample and get started right away:

git clone git@github.com:Azure-Samples/active-directory-ios-native-nxoauth2-v2.git

Registrare un'appRegister an app

Creare una nuova app nel portale di registrazione delle applicazioni oppure seguire la procedura dettagliata descritta in Come registrare un'app con l'endpoint v2.0.Create a new app at the Application registration portal, or follow the detailed steps at How to register an app with the v2.0 endpoint. Verificare di:Make sure to:

  • Copiare l' ID applicazione assegnato all'app, perché verrà richiesto a breve.Copy the Application Id that's assigned to your app because you'll need it soon.
  • Aggiungere la piattaforma Mobile per l'app.Add the Mobile platform for your app.
  • Copiare l' URI di reindirizzamento dal portale.Copy the Redirect URI from the portal. È necessario usare il valore predefinito urn:ietf:wg:oauth:2.0:oob.You must use the default value of urn:ietf:wg:oauth:2.0:oob.

Scaricare la libreria di terze parti NXOAuth2 e creare un'area di lavoroDownload the third-party NXOAuth2 library and create a workspace

Per questa procedura dettagliata verrà usato OAuth2Client di GitHub, una libreria OAuth2 per Mac OS X e iOS (Cocoa e Cocoa Touch).For this walkthrough, you will use the OAuth2Client from GitHub, which is an OAuth2 library for Mac OS X and iOS (Cocoa and Cocoa touch). Questa libreria si basa sulla bozza 10 della specifica OAuth2. Questa libreria implementa il profilo dell'applicazione nativa e supporta l'endpoint di autorizzazione dell'utente.This library is based on draft 10 of the OAuth2 spec. It implements the native application profile and supports the authorization endpoint of the user. Ecco tutto ciò che serve per l'integrazione con la piattaforma delle identità di Microsoft.These are all the things you'll need to integrate with the Microsoft identity platform.

Aggiungere la libreria al progetto con CocoaPodsAdd the library to your project by using CocoaPods

CocoaPods è un gestore delle dipendenze per i progetti Xcode.CocoaPods is a dependency manager for Xcode projects. Gestisce automaticamente i passaggi di installazione precedenti.It manages the previous installation steps automatically.

$ vi Podfile
  1. Aggiungere il codice seguente al podfile:Add the following to this podfile:

     platform :ios, '8.0'
    
     target 'QuickStart' do
    
     pod 'NXOAuth2Client'
    
     end
    
  2. Caricare il podfile usando CocoaPods.Load the podfile by using CocoaPods. Verrà creata una nuova area di lavoro Xcode da caricare.This will create a new Xcode workspace that you will load.

    $ pod install
    ...
    $ open QuickStart.xcworkspace
    

Esplorare la struttura del progettoExplore the structure of the project

Nello scheletro è configurata la struttura seguente per il progetto:The following structure is set up for our project in the skeleton:

  • Una visualizzazione master con una ricerca UPNA Master View with a UPN Search
  • Una visualizzazione dettagli per i dati sull'utente selezionatoA Detail View for the data about the selected user
  • Una visualizzazione di accesso che consente a un utente di accedere all'app per eseguire query al graficoA Login View where a user can sign in to the app to query the graph

Si passerà a diversi file nella struttura per aggiungere l'autenticazione.We will move to various files in the skeleton to add authentication. Altre parti del codice, ad esempio il codice visivo, non sono pertinenti all'identità e vengono fornite automaticamente.Other parts of the code, such as the visual code, do not pertain to identity but are provided for you.

Configurare il file settings.plst nella libreriaSet up the settings.plst file in the library

  • Nel progetto QuickStart, aprire il file settings.plist .In the QuickStart project, open the settings.plist file. Sostituire i valori degli elementi nella sezione in modo che corrispondano ai valori usati nel portale di Azure.Replace the values of the elements in the section to reflect the values that you used in the Azure portal. Il codice farà riferimento a questi valori ogni volta che viene usata la libreria di autenticazione di Active Directory.Your code will reference these values whenever it uses the Active Directory Authentication Library.
    • clientId è l'ID client dell'applicazione copiato dal portale.The clientId is the client ID of your application that you copied from the portal.
    • redirectUri è l'URL di reindirizzamento fornito dal portale.The redirectUri is the redirect URL that the portal provided.

Configurare la libreria NXOAuth2Client in LoginViewControllerSet up the NXOAuth2Client library in your LoginViewController

Per configurare la libreria NXOAuth2Client, sono necessari alcuni valori.The NXOAuth2Client library requires some values to get set up. Dopo avere completato questa attività, è possibile usare il token acquisito per le chiamate all'API Graph.After you complete that task, you can use the acquired token to call the Graph API. Poiché LoginView verrà chiamato ogni volta che è necessario eseguire l'autenticazione, è opportuno inserire i valori di configurazione nel file.Because LoginView will be called any time we need to authenticate, it makes sense to put configuration values in to that file.

  • Aggiungere alcuni valori al file LoginViewController.m per impostare il contesto per l'autenticazione e l'autorizzazione.Let's add some values to the LoginViewController.m file to set the context for authentication and authorization. I dettagli sui valori seguono il codice.Details about the values follow the code.

    NSString *scopes = @"openid offline_access User.Read";
    NSString *authURL = @"https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
    NSString *loginURL = @"https://login.microsoftonline.com/common/login";
    NSString *bhh = @"urn:ietf:wg:oauth:2.0:oob?code=";
    NSString *tokenURL = @"https://login.microsoftonline.com/common/oauth2/v2.0/token";
    NSString *keychain = @"com.microsoft.azureactivedirectory.samples.graph.QuickStart";
    static NSString * const kIDMOAuth2SuccessPagePrefix = @"session_state=";
    NSURL *myRequestedUrl;
    NSURL *myLoadedUrl;
    bool loginFlow = FALSE;
    bool isRequestBusy;
    NSURL *authcode;
    

Esaminiamo i dettagli del codice.Let's look at details about the code.

La prima stringa è per scopes.The first string is for scopes. Il valore User.Read consente di leggere il profilo di base dell'utente connesso.The User.Read value allows you to read the basic profile of the signed in user.

Per altre informazioni su tutti gli ambiti disponibili, vedere Microsoft Graph permission scopes(Ambiti di autorizzazione di Microsoft Graph).You can learn more about all the available scopes at Microsoft Graph permission scopes.

Per authURL, loginURL, bhh, tokenURL è consigliabile usare i valori specificati in precedenza.For authURL, loginURL, bhh, and tokenURL, you should use the values provided previously. Se si usano le librerie di identità di Microsoft Azure open source, verrà eseguito il pull automatico di questi dati usando gli endpoint dei metadati.If you use the open source Microsoft Azure Identity Libraries, we pull this data down for you by using our metadata endpoint. L'estrazione di questi valori è stata eseguita automaticamente.We've done the hard work of extracting these values for you.

Il valore keychain è il contenitore che la libreria NXOAuth2Client userà per creare un portachiavi in cui archiviare i token.The keychain value is the container that the NXOAuth2Client library will use to create a keychain to store your tokens. Per ottenere l'accesso Single Sign-On SSO in più app, è possibile specificare lo stesso portachiavi in ogni applicazione, oltre a richiedere l'uso di tale portachiavi nei diritti XCode.If you'd like to get single sign-on (SSO) across numerous apps, you can specify the same keychain in each of your applications and request the use of that keychain in your Xcode entitlements. Questa procedura è illustrata nella documentazione di Apple.This is explained in the Apple documentation.

Gli altri valori sono necessari per usare la libreria e creare automaticamente le posizioni per inserire i valori nel contesto.The rest of these values are required to use the library and create places for you to carry values to the context.

Creare una cache di URLCreate a URL cache

All'interno di (void)viewDidLoad(), che viene sempre chiamato dopo il caricamento della visualizzazione, il codice seguente prepara una cache per l'uso.Inside (void)viewDidLoad(), which is always called after the view is loaded, the following code primes a cache for our use.

Aggiungere il codice seguente:Add the following code:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.loginView.delegate = self;
    [self setupOAuth2AccountStore];
    [self requestOAuth2Access];
    NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                         diskCapacity:20 * 1024 * 1024
                                                             diskPath:nil];
    [NSURLCache setSharedURLCache:URLCache];

}

Creare una visualizzazione Web per l'accessoCreate a WebView for sign-in

Una visualizzazione Web consente di chiedere all'utente altri fattori, ad esempio un SMS (se configurato), o di restituire messaggi di errore all'utente.A WebView can prompt the user for additional factors like SMS text message (if configured) or return error messages to the user. Ora verrà configurata la visualizzazione Web e in seguito verrà scritto il codice per gestire i callback che si verificheranno nella visualizzazione Web dal servizio di gestione delle identità.Here you'll set up the WebView and then later write the code to handle the callbacks that will happen in the WebView from the identity services.

-(void)requestOAuth2Access {
    //to sign in to Microsoft APIs using OAuth2, we must show an embedded browser (UIWebView)
    [[NXOAuth2AccountStore sharedStore] requestAccessToAccountWithType:@"myGraphService"
                                   withPreparedAuthorizationURLHandler:^(NSURL *preparedURL) {
                                       //navigate to the URL returned by NXOAuth2Client

                                       NSURLRequest *r = [NSURLRequest requestWithURL:preparedURL];
                                       [self.loginView loadRequest:r];
                                   }];
}

Eseguire l'override dei metodi WebView per gestire l'autenticazioneOverride the WebView methods to handle authentication

Per indicare alla visualizzazione Web cosa accade quando un utente deve eseguire l'accesso come illustrato in precedenza, è possibile incollare il codice seguente.To tell the WebView what happens when a user needs to sign in as discussed previously, you can paste the following code.

- (void)resolveUsingUIWebView:(NSURL *)URL {

    // We get the auth token from a redirect so we need to handle that in the webview.

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(resolveUsingUIWebView:) withObject:URL waitUntilDone:YES];
        return;
    }

    NSURLRequest *hostnameURLRequest = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
    isRequestBusy = YES;
    [self.loginView loadRequest:hostnameURLRequest];

    NSLog(@"resolveUsingUIWebView ready (status: UNKNOWN, URL: %@)", self.loginView.request.URL);
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

    NSLog(@"webView:shouldStartLoadWithRequest: %@ (%li)", request.URL, (long)navigationType);

    // The webview is where all the communication happens. Slightly complicated.

    myLoadedUrl = [webView.request mainDocumentURL];
    NSLog(@"***Loaded url: %@", myLoadedUrl);

    //if the UIWebView is showing our authorization URL or consent URL, show the UIWebView control
    if ([request.URL.absoluteString rangeOfString:authURL options:NSCaseInsensitiveSearch].location != NSNotFound) {
        self.loginView.hidden = NO;
    } else if ([request.URL.absoluteString rangeOfString:loginURL options:NSCaseInsensitiveSearch].location != NSNotFound) {
        //otherwise hide the UIWebView, we've left the authorization flow
        self.loginView.hidden = NO;
    } else if ([request.URL.absoluteString rangeOfString:bhh options:NSCaseInsensitiveSearch].location != NSNotFound) {
        //otherwise hide the UIWebView, we've left the authorization flow
        self.loginView.hidden = YES;
        [[NXOAuth2AccountStore sharedStore] handleRedirectURL:request.URL];
    }
    else {
        self.loginView.hidden = NO;
        //read the Location from the UIWebView, this is how Microsoft APIs is returning the
        //authentication code and relation information. This is controlled by the redirect URL we chose to use from Microsoft APIs
        //continue the OAuth2 flow
       // [[NXOAuth2AccountStore sharedStore] handleRedirectURL:request.URL];
    }

    return YES;

}

Scrivere il codice per gestire il risultato della richiesta OAuth2.Write code to handle the result of the OAuth2 request

Il codice seguente gestirà l'URL di reindirizzamento restituito dalla visualizzazione Web.The following code will handle the redirectURL that returns from the WebView. Se l'autenticazione ha esito negativo, il codice ripete l'operazione.If authentication wasn't successful, the code will try again. Nel frattempo la libreria visualizzerà l'errore che è possibile visualizzare nella console o gestire in modo asincrono.Meanwhile, the library will provide the error that you can see in the console or handle asynchronously.

- (void)handleOAuth2AccessResult:(NSString *)accessResult {

    AppData* data = [AppData getInstance];

    //parse the response for success or failure
     if (accessResult)
    //if success, complete the OAuth2 flow by handling the redirect URL and obtaining a token
     {
         [[NXOAuth2AccountStore sharedStore] handleRedirectURL:accessResult];
    } else {
        //start over
        [self requestOAuth2Access];
    }
}

Configurare il contesto OAuth (archivio di account chiamato)Set up the OAuth Context (called account store)

Qui è possibile chiamare -[NXOAuth2AccountStore setClientID:secret:authorizationURL:tokenURL:redirectURL:forAccountType:] nell'archivio account condiviso per ogni servizio a cui si desidera che l'applicazione abbia accesso.Here you can call -[NXOAuth2AccountStore setClientID:secret:authorizationURL:tokenURL:redirectURL:forAccountType:] on the shared account store for each service that you want the application to be able to access. Il tipo di account è una stringa che viene usata come identificatore per un determinato servizio.The account type is a string that is used as an identifier for a certain service. Poiché si accede all'API Graph, il codice fa riferimento a esso come "myGraphService".Because you are accessing the Graph API, the code refers to it as "myGraphService". Verrà quindi configurato un osservatore che segnalerà eventuali modifiche al token.You then set up an observer that will tell you when anything changes with the token. Dopo aver ottenuto il token, l'utente torna a masterView.After you get the token, you return the user back to the masterView.

- (void)setupOAuth2AccountStore {


        AppData* data = [AppData getInstance];

    [[NXOAuth2AccountStore sharedStore] setClientID:data.clientId
                                             secret:data.secret
                                              scope:[NSSet setWithObject:scopes]
                                   authorizationURL:[NSURL URLWithString:authURL]
                                           tokenURL:[NSURL URLWithString:tokenURL]
                                        redirectURL:[NSURL URLWithString:data.redirectUriString]
                                      keyChainGroup: keychain
                                     forAccountType:@"myGraphService"];

    [[NSNotificationCenter defaultCenter] addObserverForName:NXOAuth2AccountStoreAccountsDidChangeNotification
                                                      object:[NXOAuth2AccountStore sharedStore]
                                                       queue:nil
                                                  usingBlock:^(NSNotification *aNotification) {
                                                      if (aNotification.userInfo) {
                                                          //account added, we have access
                                                          //we can now request protected data
                                                          NSLog(@"Success!! We have an access token.");
                                                          dispatch_async(dispatch_get_main_queue(),^ {

                                                              MasterViewController* masterViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"masterView"];
                                                              [self.navigationController pushViewController:masterViewController animated:YES];
                                                          });
                                                      } else {
                                                          //account removed, we lost access
                                                      }
                                                  }];

    [[NSNotificationCenter defaultCenter] addObserverForName:NXOAuth2AccountStoreDidFailToRequestAccessNotification
                                                      object:[NXOAuth2AccountStore sharedStore]
                                                       queue:nil
                                                  usingBlock:^(NSNotification *aNotification) {
                                                      NSError *error = [aNotification.userInfo objectForKey:NXOAuth2AccountStoreErrorKey];
                                                      NSLog(@"Error!! %@", error.localizedDescription);
                                                  }];
}

Configurare la visualizzazione master per cercare e visualizzare gli utenti dall'API GraphSet up the Master View to search and display the users from the Graph API

Un'app Master-View-Controller (MVC) che visualizza i dati restituiti nella griglia non rientra nell'ambito di questa procedura dettagliata, ma online sono disponibili diverse esercitazioni che illustrano come compilarne una.A Master-View-Controller (MVC) app that displays the returned data in the grid is beyond the scope of this walkthrough, and many online tutorials explain how to build one. Tutto il codice è contenuto nel file dello scheletro.All this code is in the skeleton file. È tuttavia necessario gestire alcuni elementi dell'applicazione MVC:However, you do need to deal with a few things in this MVC application:

  • Rilevare quando un utente digita qualcosa nel campo di ricercaIntercept when a user types something in the search field
  • Fornire un oggetto di dati a MasterView in modo che possa visualizzare i risultati nella grigliaProvide an object of data back to the MasterView so it can display the results in the grid

Queste operazioni verranno eseguite sotto.We'll do those below.

Aggiungere un controllo per verificare se si è connessiAdd a check to see if you're logged in

Le funzionalità dell'applicazione sono limitate se l'utente non è connesso, quindi è opportuno controllare se è già presente un token nella cache.The application does little if the user is not signed in, so it's smart to check if there is already a token in the cache. Se il token non è presente, l'utente viene reindirizzato a LoginView per l'accesso.If not, you redirect to the LoginView for the user to sign in. Se si richiama, il modo migliore per eseguire azioni quando viene caricata una visualizzazione consiste nell'usare il metodo viewDidLoad() fornito da Apple.If you recall, the best way to do actions when a view loads is to use the viewDidLoad() method that Apple provides us.

- (void)viewDidLoad {
    [super viewDidLoad];


    NXOAuth2AccountStore *store = [NXOAuth2AccountStore sharedStore];
    NSArray *accounts = [store accountsWithAccountType:@"myGraphService"];

        if (accounts.count == 0) {

        dispatch_async(dispatch_get_main_queue(),^ {

            LoginViewController* userSelectController = [self.storyboard instantiateViewControllerWithIdentifier:@"LoginUserView"];
            [self.navigationController pushViewController:userSelectController animated:YES];
        });
        }

Aggiornare la visualizzazione tabella quando vengono ricevuti i datiUpdate the Table View when data is received

Quando l'API Graph restituisce i dati, è necessario visualizzarli.When the Graph API returns data, you need to display the data. Per semplicità viene fornito tutto il codice necessario per aggiornare la tabella.For simplicity, here is all the code to update the table. È sufficiente incollare i valori corretti nel codice boilerplate MVC.You can just paste the right values in your MVC boilerplate code.

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

        return [upnArray count];
}

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TaskPrototypeCell" forIndexPath:indexPath];

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

    User *user = nil;
     user = [upnArray objectAtIndex:indexPath.row];


    // Configure the cell
    cell.textLabel.text = user.name;
    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];

    return cell;
}

Consente di chiamare l'API Graph quando qualcuno digita nel campo di ricercaProvide a way to call the Graph API when someone types in the search field

Quando un utente digita un testo di ricerca nella casella, è necessario inserirlo nell'API Graph.When a user types a search in the box, you need to shove that over to the Graph API. La classe GraphAPICaller , che verrà compilata nel codice seguente, separa le funzionalità di ricerca dalla presentazione.The GraphAPICaller class, which you will build in the following code, separates the lookup functionality from the presentation. Per ora è opportuno scrivere il codice che alimenta i caratteri di ricerca dell'API Graph.For now, let's write the code that feeds any search characters to the Graph API. A questo scopo, viene fornito un metodo denominato lookupInGraphche considera la stringa che si vuole cercare.We do this by providing a method called lookupInGraph, which takes the string that we want to search for.


-(void)lookupInGraph:(NSString *)searchText {
if (searchText.length > 0) {

    };



        [GraphAPICaller searchUserList:searchText completionBlock:^(NSMutableArray* returnedUpns, NSError* error) {
            if (returnedUpns) {


                upnArray = returnedUpns;


            }
            else
            {
                UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"Error : %@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil];

                [alertView setDelegate:self];

                dispatch_async(dispatch_get_main_queue(),^ {
                    [alertView show];
                });
            }


        }];


}

Scrivere una classe helper per accedere all'API GraphWrite a Helper class to access the Graph API

Questo è l'elemento principale dell'applicazione.This is the core of our application. Mentre prima è stato inserito il codice nel modello MVC predefinito da Apple, qui viene scritto il codice per eseguire una query del grafico mentre l'utente digita e per restituire tali dati.Whereas the rest was inserting code in the default MVC pattern from Apple, here you write code to query the graph as the user types and then return that data. Di seguito viene riportato il codice con una spiegazione dettagliata.Here's the code, and a detailed explanation follows it.

Creare un nuovo file di intestazione Objective CCreate a new Objective C header file

Assegnare al file il nome GraphAPICaller.he aggiungere il codice seguente.Name the file GraphAPICaller.h, and add the following code.

@interface GraphAPICaller : NSObject<NSURLConnectionDataDelegate>

+(void) searchUserList:(NSString*)searchString
       completionBlock:(void (^) (NSMutableArray*, NSError* error))completionBlock;

@end

Qui è possibile osservare che si sta specificando un metodo che accetta una stringa e restituisce completionBlock.Here you see that a specified method takes a string and returns a completionBlock. Questo completionBlock, come è intuibile, aggiornerà la tabella fornendo un oggetto con dati popolati in tempo reale mentre l'utente esegue la ricerca.This completionBlock, as you may have guessed, will update the table by providing an object with populated data in real time as the user searches.

Creare un nuovo file Objective CCreate a new Objective C file

Assegnare al file il nome GraphAPICaller.me aggiungere il metodo seguente.Name the file GraphAPICaller.m, and add the following method.

+(void) searchUserList:(NSString*)searchString
       completionBlock:(void (^) (NSMutableArray* Users, NSError* error)) completionBlock
{
    if (!loadedApplicationSettings)
    {
        [self readApplicationSettings];
    }

    AppData* data = [AppData getInstance];

    NSString *graphURL = [NSString stringWithFormat:@"%@%@/users", data.graphApiUrlString, data.apiversion];

    NXOAuth2AccountStore *store = [NXOAuth2AccountStore sharedStore];
    NSDictionary* params = [self convertParamsToDictionary:searchString];

    NSArray *accounts = [store accountsWithAccountType:@"myGraphService"];
    [NXOAuth2Request performMethod:@"GET"
                        onResource:[NSURL URLWithString:graphURL]
                   usingParameters:params
                       withAccount:accounts[0]
               sendProgressHandler:^(unsigned long long bytesSend, unsigned long long bytesTotal) {
                   // e.g., update a progress indicator
               }
                   responseHandler:^(NSURLResponse *response, NSData *responseData, NSError *error) {
                       // Process the response
                       if (responseData) {
                           NSError *error;
                           NSDictionary *dataReturned = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
                           NSLog(@"Graph Response was: %@", dataReturned);

                           // We can grab the top most JSON node to get our graph data.
                           NSArray *graphDataArray = [dataReturned objectForKey:@"value"];

                           // Don't be thrown off by the key name being "value". It really is the name of the
                           // first node. :-)

                           //each object is a key value pair
                           NSDictionary *keyValuePairs;
                           NSMutableArray* Users = [[NSMutableArray alloc]init];

                           for(int i =0; i < graphDataArray.count; i++)
                           {
                               keyValuePairs = [graphDataArray objectAtIndex:i];

                               User *s = [[User alloc]init];
                               s.upn = [keyValuePairs valueForKey:@"userPrincipalName"];
                               s.name =[keyValuePairs valueForKey:@"displayName"];
                               s.mail =[keyValuePairs valueForKey:@"mail"];
                               s.businessPhones =[keyValuePairs valueForKey:@"businessPhones"];
                               s.mobilePhones =[keyValuePairs valueForKey:@"mobilePhone"];


                               [Users addObject:s];
                           }

                           completionBlock(Users, nil);
                       }
                       else
                       {
                           completionBlock(nil, error);
                       }

                   }];
}

Ora questo metodo verrà analizzato in dettaglio.Let's go through this method in detail.

L'elemento principale di questo codice è il metodo NXOAuth2Requestche accetta i parametri definiti prima nel file settings.plist.The core of this code is in the NXOAuth2Request, method which takes the parameters that you've already defined in the settings.plist file.

Il primo passaggio consiste nel creare la chiamata API Graph corretta.The first step is to construct the right Graph API call. Poiché si sta chiamando /users, lo si specifica aggiungendolo alla risorsa API Graph insieme alla versione.Because you are calling /users, you specify that by appending it to the Graph API resource along with the version. Questi elementi vengono inseriti in un file delle impostazioni esterno perché possono essere modificati man mano che l'API evolve.It makes sense to put these in an external settings file because these can change as the API evolves.

NSString *graphURL = [NSString stringWithFormat:@"%@%@/users", data.graphApiUrlString, data.apiversion];

È quindi necessario specificare altri parametri che verranno forniti alla chiamata API Graph.Next, you need to specify parameters that you will also provide to the Graph API call. È molto importante non inserire i parametri nell'endpoint della risorsa perché i caratteri non conformi all'URI vengono eliminati in fase di esecuzione.It is very important that you do not put the parameters in the resource endpoint because that is scrubbed for all non-URI conforming characters at runtime. Tutto il codice della query deve essere fornito nei parametri.All query code must be provided in the parameters.


NSDictionary* params = [self convertParamsToDictionary:searchString];

Come si può notare, viene chiamato un metodo convertParamsToDictionary che non è ancora stato scritto.You might notice this calls a convertParamsToDictionary method that you haven't written yet. Verrà fatto ora alla fine del file:Let's do so now at the end of the file:

+(NSDictionary*) convertParamsToDictionary:(NSString*)searchString
{
    NSMutableDictionary* dictionary = [[NSMutableDictionary alloc]init];

        NSString *query = [NSString stringWithFormat:@"startswith(givenName, '%@')", searchString];

           [dictionary setValue:query forKey:@"$filter"];



    return dictionary;
}

Ora il metodo NXOAuth2Request verrà usato per ottenere di nuovo i dati dall'API in formato JSON.Next, let's use the NXOAuth2Request method to get data back from the API in JSON format.

NSArray *accounts = [store accountsWithAccountType:@"myGraphService"];
    [NXOAuth2Request performMethod:@"GET"
                        onResource:[NSURL URLWithString:graphURL]
                   usingParameters:params
                       withAccount:accounts[0]
               sendProgressHandler:^(unsigned long long bytesSend, unsigned long long bytesTotal) {
                   // e.g., update a progress indicator
               }
                   responseHandler:^(NSURLResponse *response, NSData *responseData, NSError *error) {
                       // Process the response
                       if (responseData) {
                           NSError *error;
                           NSDictionary *dataReturned = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
                           NSLog(@"Graph Response was: %@", dataReturned);

                           // We can grab the top most JSON node to get our graph data.
                           NSArray *graphDataArray = [dataReturned objectForKey:@"value"];

Infine si esaminerà come vengono restituiti i dati a MasterViewController.Finally, let's look at how you return the data to the MasterViewController. I dati vengono restituiti come serializzati e devono essere deserializzati e caricati in un oggetto che MainViewController possa usare.The data returns as serialized and needs to be deserialized and loaded in an object that the MainViewController can consume. A questo scopo, la struttura include un file User.m/h che crea un oggetto User.For this purpose, the skeleton has a User.m/h file that creates a User object. L'oggetto User viene popolato con le informazioni del grafico.You populate that User object with information from the graph.

                           // We can grab the top most JSON node to get our graph data.
                           NSArray *graphDataArray = [dataReturned objectForKey:@"value"];

                           // Don't be thrown off by the key name being "value". It really is the name of the
                           // first node. :-)

                           //each object is a key value pair
                           NSDictionary *keyValuePairs;
                           NSMutableArray* Users = [[NSMutableArray alloc]init];

                           for(int i =0; i < graphDataArray.count; i++)
                           {
                               keyValuePairs = [graphDataArray objectAtIndex:i];

                               User *s = [[User alloc]init];
                               s.upn = [keyValuePairs valueForKey:@"userPrincipalName"];
                               s.name =[keyValuePairs valueForKey:@"displayName"];
                               s.mail =[keyValuePairs valueForKey:@"mail"];
                               s.businessPhones =[keyValuePairs valueForKey:@"businessPhones"];
                               s.mobilePhones =[keyValuePairs valueForKey:@"mobilePhone"];


                               [Users addObject:s];

Eseguire l'esempioRun the sample

Se è stata usata la struttura o si è seguita la procedura dettagliata, l'applicazione verrà ora eseguita.If you've used the skeleton or followed along with the walkthrough your application should now run. Avviare il simulatore e fare clic su Accedi per usare l'applicazione.Start the simulator and click Sign in to use the application.

Ottenere aggiornamenti della sicurezza per il prodottoGet security updates for our product

È consigliabile ricevere notifiche in caso di problemi di sicurezza. A tale scopo, visitare Security TechCenter e sottoscrivere gli avvisi di sicurezza.We encourage you to get notifications of when security incidents occur by visiting the Security TechCenter and subscribing to Security Advisory Alerts.