如何使用适用于 Azure 移动应用的 iOS 客户端库

概述

本指南介绍如何使用最新的 Azure 移动应用 iOS SDK 执行常见方案。 如果不熟悉 Azure 移动应用,请先完成 Azure 移动应用快速入门 ,以创建后端、创建表并下载预生成的 iOS Xcode 项目。 本指南重点介绍客户端 iOS SDK。 若要了解有关后端服务器端 SDK 的详细信息,请参阅服务器 SDK HOWTO。

参考文档

iOS 客户端 SDK 的参考文档位于以下位置: Azure 移动应用 iOS 客户端参考

支持的平台

iOS SDK 支持适用于 iOS 8.0 或更高版本 Objective-C 项目、Swift 2.2 项目和 Swift 2.3 项目。

“服务器流”身份验证使用 WebView 来呈现界面。 如果设备无法显示 WebView UI,则需要在产品范围之外进行另一种身份验证方法。 因此,此 SDK 不适用于监视类型或类似受限的设备。

安装与先决条件

本指南假定你已使用表创建了后端。 本指南假定该表的架构与这些教程中的表具有相同的架构。 本指南还假定在代码中引用 MicrosoftAzureMobile.framework 和导入 MicrosoftAzureMobile/MicrosoftAzureMobile.h

如何:创建客户端

若要访问项目中的 Azure 移动应用后端,请创建一个 MSClient。 替换为 AppUrl 应用 URL。 你可以离开 gatewayURLStringapplicationKey 清空。 如果您设置了用于身份验证的网关,请将网关 URL 填写到gatewayURLString中。

Objective-C

MSClient *client = [MSClient clientWithApplicationURLString:@"AppUrl"];

Swift

let client = MSClient(applicationURLString: "AppUrl")

如何:创建数据表引用

若要访问或更新数据,请创建对后端表的引用。 将 TodoItem 替换为表的名称

Objective-C

MSTable *table = [client tableWithName:@"TodoItem"];

Swift

let table = client.tableWithName("TodoItem")

如何:查询数据

若要创建数据库查询,请查询 MSTable 对象。 以下查询获取 TodoItem 中的所有项,并记录每个项的文本。

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

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"])
        }
    }
}

如何:筛选返回的数据

若要筛选结果,有许多可用选项。

若要使用谓词进行筛选,请使用和 NSPredicatereadWithPredicate。 以下筛选器返回的数据仅查找不完整的 Todo 项。

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

// 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"])
        }
    }
}

如何:使用 MSQuery

若要执行复杂查询(包括排序和分页),请直接或使用谓词创建对象 MSQuery

Objective-C

MSQuery *query = [table query];
MSQuery *query = [table queryWithPredicate: [NSPredicate predicateWithFormat:@"complete == NO"]];

Swift

let query = table.query()
let query = table.queryWithPredicate(NSPredicate(format: "complete == NO"))

MSQuery 允许你控制多个查询行为。

  • 指定结果顺序
  • 限制要返回的字段
  • 限制要返回的记录数
  • 在响应中指定总计计数
  • 在请求中指定自定义查询字符串参数
  • 应用其他函数

执行MSQuery查询的方法是调用readWithCompletion对象。

如何:使用 MSQuery 对数据进行排序

若要对结果进行排序,让我们看看一个示例。 若要按字段“text”升序排序,然后按“complete”降序排序,请调用 MSQuery 如下所示:

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

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 限制字段和展开查询字符串参数

若要限制查询中返回的字段,请在 selectFields 属性中指定字段的名称。 此示例仅返回文本和已完成的字段:

Objective-C

query.selectFields = @[@"text", @"complete"];

Swift

query.selectFields = ["text", "complete"]

若要在服务器请求中包含其他查询字符串参数(例如,因为自定义服务器端脚本使用它们),请 query.parameters 填充如下:

Objective-C

query.parameters = @{
    @"myKey1" : @"value1",
    @"myKey2" : @"value2",
};

Swift

query.parameters = ["myKey1": "value1", "myKey2": "value2"]

如何:配置页面大小

使用 Azure 移动应用,页面大小控制从后端表一次拉取的记录数。 然后,对数据的调用 pull 将基于此页大小对数据进行批处理,直到没有更多要拉取的记录。

可以使用 MSPullSettings 配置页面大小,如下所示。 默认页面大小为 50,下面的示例将其更改为 3。

出于性能原因,可以配置不同的页面大小。 如果你有大量小型数据记录,则高页大小会减少服务器往返次数。

此设置仅控制客户端上的页面大小。 如果客户端要求页面大小大于移动应用后端支持的大小,则页面大小上限为后端配置为支持的最大大小。

此设置是数据记录的 数量,而不是 字节大小

如果增加客户端页面大小,还应增加服务器上的页面大小。 有关执行此作的步骤 ,请参阅“如何:调整表分页大小 ”。

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

let pullSettings = MSPullSettings(pageSize: 3)
table.pullWithQuery(query, queryId:nil, settings: pullSettings) { (error) in
    if let err = error {
        print("ERROR ", err)
    }
}

如何:插入数据

若要插入新表行,请创建 NSDictionary 并调用 table insert。 如果启用了 动态架构 ,Azure 应用服务移动后端会基于该 NSDictionary属性自动生成新列。

如果未提供 id,后端将自动生成一个新的唯一 ID。 使用您自己的id来填入电子邮件地址、用户名或您自定义的值作为ID。 提供自己的 ID 可能会简化联接和面向业务的数据库逻辑。

result 包含已插入的新项。 根据您的服务器逻辑,与传递到服务器的数据相比,它可能包含附加或被修改的数据。

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

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"])
    }
}

如何:修改数据

若要更新现有行,请修改项并调用 update

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

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 和更新后的字段:

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

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属性。

如何:删除数据

若要删除一项,请调用该项的 delete

Objective-C

[table delete:item completion:^(id itemId, NSError *error) {
    if(error) {
        NSLog(@"ERROR %@", error);
    } else {
        NSLog(@"Todo Item ID: %@", itemId);
    }
}];

Swift

table.delete(newItem as [NSObject: AnyObject]) { (itemId, error) in
    if let err = error {
        print("ERROR ", err)
    } else {
        print("Todo Item ID: ", itemId)
    }
}

或者,通过输入行 ID 进行删除:

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

table.deleteWithId("37BBF396-11F0-4B39-85C8-B319C729AF6D") { (itemId, error) in
    if let err = error {
        print("ERROR ", err)
    } else {
        print("Todo Item ID: ", itemId)
    }
}

在执行删除操作时,至少必须设置 id 属性。

如何:调用自定义 API

使用自定义 API,可以公开任何后端功能。 它不必映射到表操作。 不仅可以更好地控制消息传送,甚至可以读取/设置标头并更改响应正文格式。

若要调用自定义 API,请调用 MSClient.invokeAPI。 请求和响应内容被视为 JSON。 若要使用其他媒体类型, 请使用其他媒体类型的重载 invokeAPI。 若要发出GET请求而不是POST请求,请将参数HTTPMethod"GET"设置为参数并将其参数body设置为 nil (因为 GET 请求没有消息正文。如果自定义 API 支持其他 HTTP 谓词,请相应地进行更改HTTPMethod

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

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
                }
        }

如何:注册推送模板以发送跨平台通知

若要注册模板,请在客户端应用中向 client.push registerDeviceToken 方法传递模板。

Objective-C

[client.push registerDeviceToken:deviceToken template:iOSTemplate completion:^(NSError *error) {
    if(error) {
        NSLog(@"ERROR %@", error);
    }
}];

Swift

client.push?.registerDeviceToken(NSData(), template: iOSTemplate, completion: { (error) in
    if let err = error {
        print("ERROR ", err)
    }
})

模板的类型为 NSDictionary,可包含以下格式的多个模板:

Objective-C

NSDictionary *iOSTemplate = @{ @"templateName": @{ @"body": @{ @"aps": @{ @"alert": @"$(message)" } } } };

Swift

let iOSTemplate = ["templateName": ["body": ["aps": ["alert": "$(message)"]]]]

所有标签都会为了安全从请求中移除。 若要将标记添加到安装中的安装或模板,请参阅 使用适用于 Azure 移动应用的 .NET 后端服务器 SDK。 若要使用这些已注册的模板发送通知,请使用 通知中心 API

如何处理错误

调用 Azure 应用服务移动后端时,完成块包含参数 NSError 。 发生错误时,此参数不为空。 在代码中,应检查此参数并根据需要处理错误,如前面的代码片段所示。

该文件 <WindowsAzureMobileServices/MSError.h> 定义常量 MSErrorResponseKeyMSErrorRequestKey以及 MSErrorServerItemKey。 若要获取与错误相关的更多数据,

Objective-C

NSDictionary *serverItem = [error.userInfo objectForKey:MSErrorServerItemKey];

Swift

let serverItem = error.userInfo[MSErrorServerItemKey]

此外,该文件为每个错误代码定义常量:

Objective-C

if (error.code == MSErrorPreconditionFailed) {

Swift

if (error.code == MSErrorPreconditionFailed) {

如何:使用 Active Directory 身份验证库对用户进行身份验证

可以借助 Active Directory 身份验证库 (ADAL) 使用 Azure Active Directory 将用户登录到应用程序。 使用标识提供者 SDK 进行客户端流身份验证比使用 loginWithProvider:completion: 方法更好。 客户端流身份验证提供更原生的 UX 感觉,并允许进行其他自定义。

  1. 请根据如何为 Active Directory 登录配置应用服务教程,配置您的移动应用后端以支持 AAD 登录。 请务必完成注册本机客户端应用程序的可选步骤。 对于 iOS,我们建议重定向 URI 采用格式 <app-scheme>://<bundle-id>。 有关详细信息,请参阅 ADAL iOS 快速入门

  2. 使用 Cocoapods 安装 ADAL。 编辑 Podfile 以包括以下定义,将 YOUR-PROJECT 替换为 Xcode 项目的名称:

     source 'https://github.com/CocoaPods/Specs.git'
     link_with ['YOUR-PROJECT']
     xcodeproj 'YOUR-PROJECT'
    

    和 Pod:

     pod 'ADALiOS'
    
  3. 使用终端从包含项目的目录运行 pod install ,然后打开生成的 Xcode 工作区(而不是项目)。

  4. 根据所使用的语言,将以下代码添加到应用程序。 在每一个中,进行以下替换:

    • INSERT-AUTHORITY-HERE 替换为在其中预配应用程序的租户名称。 格式应为 https://login.microsoftonline.com/contoso.onmicrosoft.com。 此值可以从 Azure 门户中 Azure Active Directory 中的“域”选项卡复制。
    • INSERT-RESOURCE-ID-HERE 替换为移动应用后端的客户端 ID。 可以在门户中“Azure Active Directory 设置”下面的“高级”选项卡获取此客户端 ID。
    • INSERT-CLIENT-ID-HERE 替换为从本机客户端应用程序复制的客户端 ID。
    • 使用 HTTPS 方案将 INSERT-REDIRECT-URI-HERE 替换为站点的 /.auth/login/done 终结点。 此值应类似于 https://contoso.azurewebsites.net/.auth/login/done

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

// 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)
            }
        }
}

如何:使用适用于 iOS 的 Facebook SDK 对用户进行身份验证

可以使用适用于 iOS 的 Facebook SDK 通过 Facebook 将用户登录到应用程序。 使用客户端流身份验证最好使用 loginWithProvider:completion: 该方法。 客户端流身份验证提供一种更符合本机的用户体验,并允许进行更多的自定义。

  1. 按照 如何为 Facebook 登录配置应用服务 教程,为 Facebook 登录配置移动应用后端。

  2. 按照 适用于 iOS 的 Facebook SDK 安装适用于 iOS 的 Facebook SDK - 入门 文档。 您可以向现有注册中添加 iOS 平台,而无需创建新应用。

  3. Facebook 的文档在应用委托中包含一些 Objective-C 代码。 如果使用 Swift,则可以对 AppDelegate.swift 使用以下翻译:

    // Add the following import to your bridging header:
    //        #import <FBSDKCoreKit/FBSDKCoreKit.h>
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
        FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
        // Add any custom logic here.
        return true
    }
    
    func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
        let handled = FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
        // Add any custom logic here.
        return handled
    }
    
  4. 除了将 FBSDKCoreKit.framework 添加到您的项目之外,还要以相同的方式添加 FBSDKLoginKit.framework 的引用。

  5. 根据所使用的语言,将以下代码添加到应用程序。

    Objective-C

    #import <FBSDKLoginKit/FBSDKLoginKit.h>
    #import <FBSDKCoreKit/FBSDKAccessToken.h>
    // ...
    - (void) authenticate:(UIViewController*) parent
                completion:(void (^) (MSUser*, NSError*)) completionBlock;
    {
        FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
        [loginManager
            logInWithReadPermissions: @[@"public_profile"]
            fromViewController:parent
            handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
                if (error) {
                    completionBlock(nil, error);
                } else if (result.isCancelled) {
                    completionBlock(nil, error);
                } else {
                    NSDictionary *payload = @{
                                            @"access_token":result.token.tokenString
                                            };
                    [client loginWithProvider:@"facebook" token:payload completion:completionBlock];
                }
            }];
    }
    

    Swift

    // Add the following imports to your bridging header:
    //        #import <FBSDKLoginKit/FBSDKLoginKit.h>
    //        #import <FBSDKCoreKit/FBSDKAccessToken.h>
    
    func authenticate(parent: UIViewController, completion: (MSUser?, NSError?) -> Void) {
        let loginManager = FBSDKLoginManager()
        loginManager.logInWithReadPermissions(["public_profile"], fromViewController: parent) { (result, error) in
            if (error != nil) {
                completion(nil, error)
            }
            else if result.isCancelled {
                completion(nil, error)
            }
            else {
                let payload: [String: String] = ["access_token": result.token.tokenString]
                client.loginWithProvider("facebook", token: payload, completion: completion)
            }
        }
    }
    

如何:使用适用于 iOS 的 Twitter Fabric 对用户进行身份验证

可以使用 Fabric for iOS 通过 Twitter 将用户登录到应用程序。 与使用 loginWithProvider:completion: 方法相比,客户端流身份验证更可取,因为它提供了更加原生的用户体验,并允许进行额外的自定义。

  1. 按照 如何为 Twitter 登录配置应用服务 教程,为 Twitter 登录配置移动应用后端。

  2. 按照 适用于 iOS 的 Fabric - 入门 文档进行操作,设置 TwitterKit,并将 Fabric 添加到项目中。

    注释

    默认情况下,Fabric 会为你创建 Twitter 应用程序。 可以通过使用以下代码片段注册之前创建的使用者密钥和使用者机密来避免创建应用程序。 或者,可以将提供给应用服务的使用者密钥和使用者机密值替换为 在 Fabric 仪表板中看到的值。 如果选择此选项,请确保将回调 URL 设置为占位符值,例如 https://<yoursitename>.azurewebsites.net/.auth/login/twitter/callback

    如果选择使用之前创建的机密,请将以下代码添加到应用代理:

    Objective-C

    #import <Fabric/Fabric.h>
    #import <TwitterKit/TwitterKit.h>
    // ...
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[Twitter sharedInstance] startWithConsumerKey:@"your_key" consumerSecret:@"your_secret"];
        [Fabric with:@[[Twitter class]]];
        // Add any custom logic here.
        return YES;
    }
    

    Swift

    import Fabric
    import TwitterKit
    // ...
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
        Twitter.sharedInstance().startWithConsumerKey("your_key", consumerSecret: "your_secret")
        Fabric.with([Twitter.self])
        // Add any custom logic here.
        return true
    }
    
  3. 根据所使用的语言,将以下代码添加到应用程序。

    Objective-C

    #import <TwitterKit/TwitterKit.h>
    // ...
    - (void)authenticate:(UIViewController*)parent completion:(void (^) (MSUser*, NSError*))completionBlock
    {
        [[Twitter sharedInstance] logInWithCompletion:^(TWTRSession *session, NSError *error) {
            if (session) {
                NSDictionary *payload = @{
                                            @"access_token":session.authToken,
                                            @"access_token_secret":session.authTokenSecret
                                        };
                [client loginWithProvider:@"twitter" token:payload completion:completionBlock];
            } else {
                completionBlock(nil, error);
            }
        }];
    }
    

    Swift

    import TwitterKit
    // ...
    func authenticate(parent: UIViewController, completion: (MSUser?, NSError?) -> Void) {
        let client = self.table!.client
        Twitter.sharedInstance().logInWithCompletion { session, error in
            if (session != nil) {
                let payload: [String: String] = ["access_token": session!.authToken, "access_token_secret": session!.authTokenSecret]
                client.loginWithProvider("twitter", token: payload, completion: completion)
            } else {
                completion(nil, error)
            }
        }
    }
    

如何:使用适用于 iOS 的 Google Sign-In SDK 对用户进行身份验证

可以使用适用于 iOS 的 Google Sign-In SDK,使用 Google 帐户将用户登录到应用程序。 谷歌最近宣布了对其 OAuth 安全策略的更改。 这些策略更改需要将来使用 Google SDK。

  1. 按照 如何为 Google 登录配置应用服务 教程,为 Google 登录配置移动应用后端。

  2. 按照 Google Sign-In for iOS - 开始集成 文档中的说明,安装用于 iOS 的 Google SDK。 可以跳过“使用后端服务器进行身份验证”部分。

  3. 根据所使用的语言,将以下内容添加到委托中的 signIn:didSignInForUser:withError: 方法。

    Objective-C

    NSDictionary *payload = @{
                                @"id_token":user.authentication.idToken,
                                @"authorization_code":user.serverAuthCode
                                };
    
    [client loginWithProvider:@"google" token:payload completion:^(MSUser *user, NSError *error) {
        // ...
    }];
    

    Swift

    let payload: [String: String] = ["id_token": user.authentication.idToken, "authorization_code": user.serverAuthCode]
    client.loginWithProvider("google", token: payload) { (user, error) in
        // ...
    }
    
  4. 请确保在应用委托中的 application:didFinishLaunchingWithOptions: 添加以下内容,并将用于步骤 1 中配置应用服务的“SERVER_CLIENT_ID”替换为相同的 ID。

    Objective-C

    [GIDSignIn sharedInstance].serverClientID = @"SERVER_CLIENT_ID";
    

    Swift

    GIDSignIn.sharedInstance().serverClientID = "SERVER_CLIENT_ID"
    
  5. 根据所使用的语言,在实现 GIDSignInUIDelegate 协议的 UIViewController 中,将以下代码添加到应用程序。 在再次登录之前,你已签出,虽然不需要再次输入凭据,但你会看到一个同意对话框。 仅当会话令牌过期时调用此方法。

    Objective-C

    #import <Google/SignIn.h>
    // ...
    - (void)authenticate
    {
            [GIDSignIn sharedInstance].uiDelegate = self;
            [[GIDSignIn sharedInstance] signOut];
            [[GIDSignIn sharedInstance] signIn];
    }
    

    Swift

    // ...
    func authenticate() {
        GIDSignIn.sharedInstance().uiDelegate = self
        GIDSignIn.sharedInstance().signOut()
        GIDSignIn.sharedInstance().signIn()
    }