如何使用适用于 Azure 移动应用的 iOS 客户端库How to Use iOS Client Library for Azure Mobile Apps
概述Overview
本指南介绍如何使用最新的 Azure 移动应用 iOS SDK 执行常见任务。This guide teaches you to perform common scenarios using the latest Azure Mobile Apps iOS SDK. 对于 Azure 移动应用的新手,请先完成 Azure 移动应用快速入门,创建后端、创建表并下载预先生成的 iOS Xcode 项目。If you are new to Azure Mobile Apps, first complete Azure Mobile Apps Quick Start to create a backend, create a table, and download a pre-built iOS Xcode project. 本指南侧重于客户端 iOS SDK。In this guide, we focus on the client-side iOS SDK. 若要了解有关用于后端的服务器端 SDK 的详细信息,请参阅 Server SDK 操作方法。To learn more about the server-side SDK for the backend, see the Server SDK HOWTOs.
参考文档Reference documentation
iOS 客户端 SDK 的参考文档位于此处:Azure 移动应用 iOS 客户端参考。The reference documentation for the iOS client SDK is located here: Azure Mobile Apps iOS Client Reference.
支持的平台Supported Platforms
iOS SDK 支持适用于 iOS 8.0 版及更高版本的 Objective-C 项目、Swift 2.2 项目和 Swift 2.3 项目。The iOS SDK supports Objective-C projects, Swift 2.2 projects, and Swift 2.3 projects for iOS versions 8.0 or later.
“服务器流”身份验证在呈现的 UI 中使用 WebView。The "server-flow" authentication uses a WebView for the presented UI. 如果设备不能显示 Web 视图 UI,则需使用本产品范围外的另一种身份验证方法。If the device is not able to present a WebView UI, then another method of authentication is required that is outside the scope of the product.
因此这个 SDK 不适用于监视类型或同样受限制的设备。This SDK is thus not suitable for Watch-type or similarly restricted devices.
安装与先决条件Setup and Prerequisites
本指南假设已创建了包含表的后端。This guide assumes that you have created a backend with a table. 本指南假设该表的架构与这些教程中的表相同。This guide assumes that the table has the same schema as the tables in those tutorials. 本指南还假设在代码中引用了 MicrosoftAzureMobile.framework
并导入了 MicrosoftAzureMobile/MicrosoftAzureMobile.h
。This guide also assumes that in your code, you reference MicrosoftAzureMobile.framework
and import MicrosoftAzureMobile/MicrosoftAzureMobile.h
.
如何:创建客户端How to: Create Client
若要在项目中访问 Azure 移动应用后端,请创建 MSClient
。To access an Azure Mobile Apps backend in your project, create an MSClient
. 将 AppUrl
替换为应用 URL。Replace AppUrl
with the app URL. 可以将 gatewayURLString
和 applicationKey
留空。You may leave gatewayURLString
and applicationKey
empty. 如果设置了用于身份验证的网关,请使用网关 URL 填充 gatewayURLString
。If you set up a gateway for authentication, populate gatewayURLString
with the gateway URL.
Objective-C :Objective-C :
MSClient *client = [MSClient clientWithApplicationURLString:@"AppUrl"];
Swift :Swift :
let client = MSClient(applicationURLString: "AppUrl")
如何:创建表引用How to: Create Table Reference
若要访问或更新数据,请创建到后端表的引用。To access or update data, create a reference to the backend table. 将 TodoItem
替换为表名称Replace TodoItem
with the name of your table
Objective-C :Objective-C :
MSTable *table = [client tableWithName:@"TodoItem"];
Swift :Swift :
let table = client.tableWithName("TodoItem")
如何:查询数据How to: Query Data
若要创建数据库查询,请查询 MSTable
对象。To create a database query, query the MSTable
object. 以下查询将获取 TodoItem
中的所有项,并记录每个项的文本。The following query gets all the items in TodoItem
and logs the text of each item.
Objective-C :Objective-C :
[table readWithCompletion:^(MSQueryResult *result, NSError *error) {
if(error) { // error is nil if no error occurred
NSLog(@"ERROR %@", error);
} else {
for(NSDictionary *item in result.items) { // items is NSArray of records that match query
NSLog(@"Todo Item: %@", [item objectForKey:@"text"]);
}
}
}];
Swift :Swift :
table.readWithCompletion { (result, error) in
if let err = error {
print("ERROR ", err)
} else if let items = result?.items {
for item in items {
print("Todo Item: ", item["text"])
}
}
}
如何:筛选返回的数据How to: Filter Returned Data
可以使用许多可用选项来筛选结果。To filter results, there are many available options.
若要使用谓词进行筛选,请使用 NSPredicate
和 readWithPredicate
。To filter using a predicate, use an NSPredicate
and readWithPredicate
. 以下筛选器返回的数据只用于查找未完成的待办事项。The following filters returned data to find only incomplete Todo items.
Objective-C :Objective-C :
// Create a predicate that finds items where complete is false
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"complete == NO"];
// Query the TodoItem table
[table readWithPredicate:predicate completion:^(MSQueryResult *result, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
for(NSDictionary *item in result.items) {
NSLog(@"Todo Item: %@", [item objectForKey:@"text"]);
}
}
}];
Swift :Swift :
// Create a predicate that finds items where complete is false
let predicate = NSPredicate(format: "complete == NO")
// Query the TodoItem table
table.readWithPredicate(predicate) { (result, error) in
if let err = error {
print("ERROR ", err)
} else if let items = result?.items {
for item in items {
print("Todo Item: ", item["text"])
}
}
}
如何:使用 MSQueryHow to: Use MSQuery
若要执行复杂查询(包括排序和分页),请使用谓词直接创建 MSQuery
对象:To perform a complex query (including sorting and paging), create an MSQuery
object, directly or by using a predicate:
Objective-C :Objective-C :
MSQuery *query = [table query];
MSQuery *query = [table queryWithPredicate: [NSPredicate predicateWithFormat:@"complete == NO"]];
Swift :Swift :
let query = table.query()
let query = table.queryWithPredicate(NSPredicate(format: "complete == NO"))
MSQuery
允许用户控制几种查询行为。MSQuery
lets you control several query behaviors.
- 指定结果顺序Specify order of results
- 限制要返回的字段Limit which fields to return
- 限制要返回的记录数Limit how many records to return
- 指定响应中的总计数Specify total count in response
- 指定请求中的自定义查询字符串参数Specify custom query string parameters in request
- 应用其他函数Apply additional functions
通过对对象调用 readWithCompletion
来执行 MSQuery
查询。Execute an MSQuery
query by calling readWithCompletion
on the object.
如何:使用 MSQuery 对数据排序How to: Sort Data with MSQuery
让我们先看一个示例,来了解如何对结果排序。To sort results, let's look at an example. 如果要对字段“text”进行升序排序,并对“complete”进行降序排序,请调用 MSQuery
,如下所示:To sort by field 'text' ascending, then by 'complete' descending, invoke MSQuery
like so:
Objective-C :Objective-C :
[query orderByAscending:@"text"];
[query orderByDescending:@"complete"];
[query readWithCompletion:^(MSQueryResult *result, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
for(NSDictionary *item in result.items) {
NSLog(@"Todo Item: %@", [item objectForKey:@"text"]);
}
}
}];
Swift :Swift :
query.orderByAscending("text")
query.orderByDescending("complete")
query.readWithCompletion { (result, error) in
if let err = error {
print("ERROR ", err)
} else if let items = result?.items {
for item in items {
print("Todo Item: ", item["text"])
}
}
}
如何:使用 MSQuery 限制字段和展开查询字符串参数How to: Limit Fields and Expand Query String Parameters with MSQuery
若要限制在查询中返回的字段,请在 selectFields 属性中指定字段的名称。To limit fields to be returned in a query, specify the names of the fields in the selectFields property. 此示例只返回 text 和 completed 字段:This example returns only the text and completed fields:
Objective-C :Objective-C :
query.selectFields = @[@"text", @"complete"];
Swift :Swift :
query.selectFields = ["text", "complete"]
若要在服务器请求中包含其他查询字符串参数(例如,某个自定义服务器端脚本要使用这些参数),请按如下所示填充 query.parameters
:To include additional query string parameters in the server request (for example, because a custom server-side script uses them), populate query.parameters
like so:
Objective-C :Objective-C :
query.parameters = @{
@"myKey1" : @"value1",
@"myKey2" : @"value2",
};
Swift :Swift :
query.parameters = ["myKey1": "value1", "myKey2": "value2"]
如何:配置页面大小How to: Configure Page Size
在 Azure 移动应用中,页面大小控制每次从后端表提取的记录数。With Azure Mobile Apps, the page size controls the number of records that are pulled at a time from the backend tables. pull
数据的调用稍后会基于此页面大小对数据进行批量处理,直到没有更多要提取的记录。A call to pull
data would then batch up data, based on this page size, until there are no more records to pull.
可使用 MSPullSettings 配置页面大小,如下所示。It's possible to configure a page size using MSPullSettings as shown below. 默认的页面大小为 50,下面的示例将其更改为 3。The default page size is 50, and the example below changes it to 3.
可以配置不同的页面大小,以提高性能。You could configure a different page size for performance reasons. 如果有大量小型数据记录,增大页面大小可减少服务器往返次数。If you have a large number of small data records, a high page size reduces the number of server round-trips.
此设置仅控制客户端侧的页面大小。This setting controls only the page size on the client side. 如果客户端请求的页面大小超过移动应用后端支持的大小,则页面大小受限于后端配置为支持的最大值。If the client asks for a larger page size than the Mobile Apps backend supports, the page size is capped at the maximum the backend is configured to support.
此设置也是数据记录的数目 ,而不是字节大小 。This setting is also the number of data records, not the byte size .
如果要增加客户端页面大小,还应增加服务器上的页面大小。If you increase the client page size, you should also increase the page size on the server. 请参阅“如何:调整表分页大小”以获取执行此操作的步骤。See "How to: Adjust the table paging size" for the steps to do this.
Objective-C :Objective-C :
MSPullSettings *pullSettings = [[MSPullSettings alloc] initWithPageSize:3];
[table pullWithQuery:query queryId:@nil settings:pullSettings
completion:^(NSError * _Nullable error) {
if(error) {
NSLog(@"ERROR %@", error);
}
}];
Swift :Swift :
let pullSettings = MSPullSettings(pageSize: 3)
table.pullWithQuery(query, queryId:nil, settings: pullSettings) { (error) in
if let err = error {
print("ERROR ", err)
}
}
如何:插入数据How to: Insert Data
若要插入新的表行,请创建 NSDictionary
并调用 table insert
。To insert a new table row, create a NSDictionary
and invoke table insert
. 如果启用动态架构,Azure App Service 移动后端将根据 NSDictionary
自动生成新列。If Dynamic Schema is enabled, the Azure App Service mobile backend automatically generates new columns based on the NSDictionary
.
如果未提供 id
,后端会自动生成新的唯一 ID。If id
is not provided, the backend automatically generates a new unique ID. 提供自己的 id
,以使用电子邮件地址、用户名或自己的自定义值作为 ID。Provide your own id
to use email addresses, usernames, or your own custom values as ID. 提供自己的 ID 可以让联接和业务导向型数据库逻辑变得更容易。Providing your own ID may ease joins and business-oriented database logic.
result
包含插入的新项。The result
contains the new item that was inserted. 根据服务器逻辑,与传递给服务器的项相比,它可能包含其他或已修改的数据。Depending on your server logic, it may have additional or modified data compared to what was passed to the server.
Objective-C :Objective-C :
NSDictionary *newItem = @{@"id": @"custom-id", @"text": @"my new item", @"complete" : @NO};
[table insert:newItem completion:^(NSDictionary *result, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
NSLog(@"Todo Item: %@", [result objectForKey:@"text"]);
}
}];
Swift :Swift :
let newItem = ["id": "custom-id", "text": "my new item", "complete": false]
table.insert(newItem) { (result, error) in
if let err = error {
print("ERROR ", err)
} else if let item = result {
print("Todo Item: ", item["text"])
}
}
如何:修改数据How to: Modify Data
若要更新现有的行,请修改项并调用 update
:To update an existing row, modify an item and call update
:
Objective-C :Objective-C :
NSMutableDictionary *newItem = [oldItem mutableCopy]; // oldItem is NSDictionary
[newItem setValue:@"Updated text" forKey:@"text"];
[table update:newItem completion:^(NSDictionary *result, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
NSLog(@"Todo Item: %@", [result objectForKey:@"text"]);
}
}];
Swift :Swift :
if let newItem = oldItem.mutableCopy() as? NSMutableDictionary {
newItem["text"] = "Updated text"
table2.update(newItem as [NSObject: AnyObject], completion: { (result, error) -> Void in
if let err = error {
print("ERROR ", err)
} else if let item = result {
print("Todo Item: ", item["text"])
}
})
}
或者,提供行 ID 和更新的字段:Alternatively, supply the row ID and the updated field:
Objective-C :Objective-C :
[table update:@{@"id":@"custom-id", @"text":"my EDITED item"} completion:^(NSDictionary *result, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
NSLog(@"Todo Item: %@", [result objectForKey:@"text"]);
}
}];
Swift :Swift :
table.update(["id": "custom-id", "text": "my EDITED item"]) { (result, error) in
if let err = error {
print("ERROR ", err)
} else if let item = result {
print("Todo Item: ", item["text"])
}
}
进行更新时,至少必须设置 id
属性。At minimum, the id
attribute must be set when making updates.
如何:删除数据How to: Delete Data
若要删除某个项,请对该项调用 delete
:To delete an item, invoke delete
with the item:
Objective-C :Objective-C :
[table delete:item completion:^(id itemId, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
NSLog(@"Todo Item ID: %@", itemId);
}
}];
Swift :Swift :
table.delete(newItem as [NSObject: AnyObject]) { (itemId, error) in
if let err = error {
print("ERROR ", err)
} else {
print("Todo Item ID: ", itemId)
}
}
或者,提供行 ID 来进行删除:Alternatively, delete by providing a row ID:
Objective-C :Objective-C :
[table deleteWithId:@"37BBF396-11F0-4B39-85C8-B319C729AF6D" completion:^(id itemId, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
NSLog(@"Todo Item ID: %@", itemId);
}
}];
Swift :Swift :
table.deleteWithId("37BBF396-11F0-4B39-85C8-B319C729AF6D") { (itemId, error) in
if let err = error {
print("ERROR ", err)
} else {
print("Todo Item ID: ", itemId)
}
}
进行删除时,至少必须设置 id
属性。At minimum, the id
attribute must be set when making deletes.
如何:调用自定义 APIHow to: Call Custom API
使用自定义 API 可以公开任何后端功能。With a custom API, you can expose any backend functionality. 无需映射到表操作。It doesn't have to map to a table operation. 不仅能进一步控制消息,甚至还可以读取或设置标头,并更改响应正文格式。Not only do you gain more control over messaging, you can even read/set headers and change the response body format.
若要调用自定义 API,请调用 MSClient.invokeAPI
。To call a custom API, call MSClient.invokeAPI
. 请求和响应内容被视为 JSON。The request and response content are treated as JSON. 若要使用其他媒体类型,请使用 invokeAPI
的其他重载。To use other media types, use the other overload of invokeAPI
. 若要发出 GET
请求而不是 POST
请求,请将参数 HTTPMethod
设置为 "GET"
,将参数 body
设置为 nil
(因为 GET 请求没有消息正文)。如果自定义 API 支持其他 HTTP 谓词,请相应地更改 HTTPMethod
。To make a GET
request instead of a POST
request, set parameter HTTPMethod
to "GET"
and parameter body
to nil
(since GET requests do not have message bodies.) If your custom API supports other HTTP verbs, change HTTPMethod
appropriately.
Objective-C :Objective-C :
[self.client invokeAPI:@"sendEmail"
body:@{ @"contents": @"Hello world!" }
HTTPMethod:@"POST"
parameters:@{ @"to": @"bill@contoso.com", @"subject" : @"Hi!" }
headers:nil
completion: ^(NSData *result, NSHTTPURLResponse *response, NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
} else {
// Do something with result
}
}];
Swift :Swift :
client.invokeAPI("sendEmail",
body: [ "contents": "Hello World" ],
HTTPMethod: "POST",
parameters: [ "to": "bill@contoso.com", "subject" : "Hi!" ],
headers: nil)
{
(result, response, error) -> Void in
if let err = error {
print("ERROR ", err)
} else if let res = result {
// Do something with result
}
}
如何:注册推送模板以发送跨平台通知How to: Register push templates to send cross-platform notifications
若要注册模板,请在客户端应用中连同 client.push registerDeviceToken 方法一起传递模板即可。To register templates, pass templates with your client.push registerDeviceToken method in your client app.
Objective-C :Objective-C :
[client.push registerDeviceToken:deviceToken template:iOSTemplate completion:^(NSError *error) {
if(error) {
NSLog(@"ERROR %@", error);
}
}];
Swift :Swift :
client.push?.registerDeviceToken(NSData(), template: iOSTemplate, completion: { (error) in
if let err = error {
print("ERROR ", err)
}
})
模板类型是 NSDictionary,可以包含采用以下格式的多个模板:Your templates are of type NSDictionary and can contain multiple templates in the following format:
Objective-C :Objective-C :
NSDictionary *iOSTemplate = @{ @"templateName": @{ @"body": @{ @"aps": @{ @"alert": @"$(message)" } } } };
Swift :Swift :
let iOSTemplate = ["templateName": ["body": ["aps": ["alert": "$(message)"]]]]
出于安全考虑,从请求中删除所有标记。All tags are stripped from the request for security. 若要将标记添加到安装或安装中的模板,请参阅使用适用于 Azure 移动应用的 .NET 后端服务器 SDK。To add tags to installations or templates within installations, see Work with the .NET backend server SDK for Azure Mobile Apps. 若要使用这些注册的模板发送通知,请参阅通知中心 API。To send notifications using these registered templates, work with Notification Hubs APIs.
如何:处理错误How to: Handle Errors
调用 Azure 应用服务移动后端时,完成块包含 NSError
参数。When you call an Azure App Service mobile backend, the completion block contains an NSError
parameter. 如果出错,此参数为非 nil 值。When an error occurs, this parameter is non-nil. 应该在代码中检查此参数,并根据需要处理错误,如前面的代码片段中所示。In your code, you should check this parameter and handle the error as needed, as demonstrated in the preceding code snippets.
文件 <WindowsAzureMobileServices/MSError.h>
定义常量 MSErrorResponseKey
、MSErrorRequestKey
和 MSErrorServerItemKey
。The file <WindowsAzureMobileServices/MSError.h>
defines the constants MSErrorResponseKey
, MSErrorRequestKey
, and MSErrorServerItemKey
. 若要获取与错误相关的更多数据,请执行以下操作:To get more data related to the error:
Objective-C :Objective-C :
NSDictionary *serverItem = [error.userInfo objectForKey:MSErrorServerItemKey];
Swift :Swift :
let serverItem = error.userInfo[MSErrorServerItemKey]
此外,该文件还定义每个错误代码的常量:In addition, the file defines constants for each error code:
Objective-C :Objective-C :
if (error.code == MSErrorPreconditionFailed) {
Swift :Swift :
if (error.code == MSErrorPreconditionFailed) {
如何:使用 Active Directory 身份验证库对用户进行身份验证How to: Authenticate users with the Active Directory Authentication Library
可以借助 Active Directory 身份验证库 (ADAL) 使用 Azure Active Directory 将用户登录到应用程序。You can use the Active Directory Authentication Library (ADAL) to sign users into your application using Azure Active Directory. 使用标识提供者 SDK 的客户端流身份验证优于使用 loginWithProvider:completion:
方法。Client flow authentication using an identity provider SDK is preferable to using the loginWithProvider:completion:
method. 客户端流身份验证提供更自然的 UX 体验,并允许进行额外的自定义。Client flow authentication provides a more native UX feel and allows for additional customization.
根据 How to configure App Service for Active Directory login (如何为 Active Directory 登录配置应用服务)教程的说明,为 AAD 登录配置移动应用。Configure your mobile app backend for AAD sign-in by following the How to configure App Service for Active Directory login tutorial. 请务必完成注册本机客户端应用程序的可选步骤。Make sure to complete the optional step of registering a native client application. 对于 iOS,建议重定向 URI 采用
<app-scheme>://<bundle-id>
格式。For iOS, we recommend that the redirect URI is of the form<app-scheme>://<bundle-id>
. 有关详细信息,请参阅 ADAL iOS 快速入门。For more information, see the ADAL iOS quickstart.使用 Cocoapods 安装 ADAL。Install ADAL using Cocoapods. 编辑 Podfile 以包含以下定义,将 YOUR-PROJECT 替换为 Xcode 项目的名称:Edit your Podfile to include the following definition, replacing YOUR-PROJECT with the name of your Xcode project:
source 'https://github.com/CocoaPods/Specs.git' link_with ['YOUR-PROJECT'] xcodeproj 'YOUR-PROJECT'
Pod:and the Pod:
pod 'ADALiOS'
使用终端,从包含项目的目录运行
pod install
,然后打开生成的 Xcode 工作区(而不是项目)。Using the Terminal, runpod install
from the directory containing your project, and then open the generated Xcode workspace (not the project).根据使用的语言,将以下代码添加到应用程序。Add the following code to your application, according to the language you are using. 在每个应用程序中,进行以下替换:In each, make these replacements:
- 将 INSERT-AUTHORITY-HERE 替换为在其中预配应用程序的租户的名称。Replace INSERT-AUTHORITY-HERE with the name of the tenant in which you provisioned your application. 格式应为 https://login.chinacloudapi.cn/contoso.onmicrosoft.com 。The format should be https://login.chinacloudapi.cn/contoso.onmicrosoft.com. 可以在 Azure 门户中从 Azure Active Directory 的域选项卡复制此值。This value can be copied from the Domain tab in your Azure Active Directory in the Azure portal.
- 将 INSERT-RESOURCE-ID-HERE 替换移动应用后端的客户端 ID。Replace INSERT-RESOURCE-ID-HERE with the client ID for your mobile app backend. 可以在门户中“Azure Active Directory 设置” 下面的“高级” 选项卡获取此客户端 ID。You can obtain the client ID from the Advanced tab under Azure Active Directory Settings in the portal.
- 将 INSERT-CLIENT-ID-HERE 替换为从本机客户端应用程序复制的客户端 ID。Replace INSERT-CLIENT-ID-HERE with the client ID you copied from the native client application.
- 将 INSERT-REDIRECT-URI-HERE 替换为站点的 /.auth/login/done 终结点(使用 HTTPS 方案)。Replace INSERT-REDIRECT-URI-HERE with your site's /.auth/login/done endpoint, using the HTTPS scheme. 此值应类似于 https://contoso.chinacloudsites.cn/.auth/login/done 。This value should be similar to https://contoso.chinacloudsites.cn/.auth/login/done .
Objective-C :Objective-C :
#import <ADALiOS/ADAuthenticationContext.h>
#import <ADALiOS/ADAuthenticationSettings.h>
// ...
- (void) authenticate:(UIViewController*) parent
completion:(void (^) (MSUser*, NSError*))completionBlock;
{
NSString *authority = @"INSERT-AUTHORITY-HERE";
NSString *resourceId = @"INSERT-RESOURCE-ID-HERE";
NSString *clientId = @"INSERT-CLIENT-ID-HERE";
NSURL *redirectUri = [[NSURL alloc]initWithString:@"INSERT-REDIRECT-URI-HERE"];
ADAuthenticationError *error;
ADAuthenticationContext *authContext = [ADAuthenticationContext authenticationContextWithAuthority:authority error:&error];
authContext.parentController = parent;
[ADAuthenticationSettings sharedInstance].enableFullScreen = YES;
[authContext acquireTokenWithResource:resourceId
clientId:clientId
redirectUri:redirectUri
completionBlock:^(ADAuthenticationResult *result) {
if (result.status != AD_SUCCEEDED)
{
completionBlock(nil, result.error);;
}
else
{
NSDictionary *payload = @{
@"access_token" : result.tokenCacheStoreItem.accessToken
};
[client loginWithProvider:@"aad" token:payload completion:completionBlock];
}
}];
}
Swift :Swift :
// add the following imports to your bridging header:
// #import <ADALiOS/ADAuthenticationContext.h>
// #import <ADALiOS/ADAuthenticationSettings.h>
func authenticate(parent: UIViewController, completion: (MSUser?, NSError?) -> Void) {
let authority = "INSERT-AUTHORITY-HERE"
let resourceId = "INSERT-RESOURCE-ID-HERE"
let clientId = "INSERT-CLIENT-ID-HERE"
let redirectUri = NSURL(string: "INSERT-REDIRECT-URI-HERE")
var error: AutoreleasingUnsafeMutablePointer<ADAuthenticationError?> = nil
let authContext = ADAuthenticationContext(authority: authority, error: error)
authContext.parentController = parent
ADAuthenticationSettings.sharedInstance().enableFullScreen = true
authContext.acquireTokenWithResource(resourceId, clientId: clientId, redirectUri: redirectUri) { (result) in
if result.status != AD_SUCCEEDED {
completion(nil, result.error)
}
else {
let payload: [String: String] = ["access_token": result.tokenCacheStoreItem.accessToken]
client.loginWithProvider("aad", token: payload, completion: completion)
}
}
}