> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS 快速入门

> 将 PlayFab Services C SDK 添加到 Xcode 项目，并从使用原生 C 客户端库构建的 iOS 应用进行第一次 PlayFab API 调用。

# 快速入门：iOS

开始使用适用于 iOS 的 PlayFab Services SDK。按以下步骤将库包含到你的项目中，并试用基本 PlayFab 功能的示例代码。

本快速入门帮助你使用 iOS SDK 进行第一次 PlayFab API 调用。在继续之前，请确保已完成 [快速入门：Game Manager](/services/playfab/live-service-management/gamemanager/quickstart) 中的步骤，以确保你拥有 PlayFab 账户并熟悉 PlayFab Game Manager。

## 要求

* 一个 [PlayFab 开发者账户](https://developer.playfab.com)。
* 已安装 [XCode](https://developer.apple.com/xcode/) IDE。

## 项目设置

从 [PlayFab SDK 发布页面](https://github.com/PlayFab/PlayFabCSdk/releases/latest) 将 PlayFab iOS SDK 下载到你的项目中。

### 将 PlayFab C SDK 集成到你自己的项目中

#### 将二进制文件添加到你的游戏

通过下载或从源码构建获得二进制文件后，你应该能够轻松地将它们集成到你的游戏/应用中。你需要将以下二进制文件添加到你的游戏：

* HttpClient\_iOS.xcframework
* PlayFabCore\_iOS.xcframework
* PlayFabServices\_iOS.xcframework

按照以下说明添加它们：

1. 在 XCode 中，导航到你想要的目标并选择它。

2. 在 **General** 部分，向下滚动到 "**Frameworks, Libraries, and Embedded Content**" 部分，点击 "**+**" 号。

3. 搜索你的 **PlayFabServices** / **PlayFabCore** / **HttpClient** 二进制文件并选择 xcframework 文件夹。（*你也可以进入 xcframework 文件夹选择特定的库，但推荐导入 xcframework bundle，因为它同时适用于设备和模拟器构建。*）

4. 成功导入二进制文件后，HttpClient\_iOS、PlayFabCore\_iOS 和 PlayFabServices\_iOS 将列在 Frameworks, Libraries, and Embedded Content 下。

#### 添加头文件搜索路径

添加二进制文件后，你需要确保头文件搜索路径也正确设置。

1. 导航到你的项目。

2. 选择 "**Build Settings**"，然后搜索 "**Header Search Paths**"。

3. 更新属性值以包含 SDK 头文件。添加对 **include** 文件夹中头文件的引用。例如：
   ```
   PlayFabCSdk-iOS/include
   ```

## 初始化和登录

按照以下步骤让一些 PlayFab 示例调用运行起来。

### 头文件

包含 **PFServices.h** 以访问所有内置的 PlayFab 功能。

```cpp theme={null}
#include <playfab/services/PFServices.h>
```

### 初始化

PlayFab 初始化需要两个函数调用：**PFServicesInitialize** 和 **PFServiceConfigCreateHandle**。此初始化的结果是一个 **PFServiceConfigHandle**。你将此句柄提供给后续的登录调用，将调用指向 PlayFab 后端中正确的 title。

```cpp theme={null}
    HRESULT hr = PFServicesInitialize(nullptr); // Add your own error handling when FAILED(hr) == true

    PFServiceConfigHandle serviceConfigHandle{ nullptr };

    hr = PFServiceConfigCreateHandle(
            "https://ABCDEF.playfabapi.com",    // PlayFab API endpoint - obtained in the Game Manager
            "ABCDEF",                           // PlayFab Title id - obtained in the Game Manager
            &serviceConfigHandle);
```

### 登录

一旦你有了 **PFServiceConfigHandle**，就可以用它进行玩家登录调用。在 SDK 中，使用 **PFAuthenticationLoginWith\*Async** 方法，例如 **PFAuthenticationLoginWithAppleAsync**。此函数允许你使用 **Apple 用户的身份令牌** 将玩家登录到 PlayFab。（*请参阅 Apple 关于[使用 Sign in with Apple 对用户进行身份验证](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple)的文档*）。

进行登录调用后，可以使用 **XAsyncGetStatus** 检查调用状态。状态开始为 **E\_PENDING**，调用成功完成后变为 **S\_OK**。如果调用因某种原因失败，状态会反映该失败。所有 PlayFab Services 调用的错误处理方式都是这样。

与 **S\_OK** 结果一起，你会得到一个 **PFEntityHandle**。你使用此句柄以登录玩家的身份进行后续 PlayFab 调用。它包含以该玩家身份对 PlayFab 服务进行身份验证所需的任何材料。

```cpp theme={null}
PFAuthenticationLoginWithAppleRequest request{};
request.createAccount = true;
request.identityToken = identityToken; // A user identity token obtained from Apple

XAsyncBlock async{};
hr = PFAuthenticationLoginWithAppleAsync(serviceConfigHandle, &request, &async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

std::vector<char> loginResultBuffer;
PFAuthenticationLoginResult const* loginResult;
size_t bufferSize;
hr = PFAuthenticationLoginWithAppleGetResultSize(&async, &bufferSize);
loginResultBuffer.resize(bufferSize);

PFEntityHandle entityHandle{ nullptr };
hr = PFAuthenticationLoginWithAppleGetResult(&async, &entityHandle, loginResultBuffer.size(), loginResultBuffer.data(), &loginResult, nullptr);
```

## 服务调用

玩家登录后，你现在可以对 PlayFab 后端进行调用。以下是一个获取存储在 PlayFab 中当前玩家文件的调用示例。

### 获取 EntityKey

对于某些 PlayFab 调用来说，知道玩家的 **PFEntityKey** 会很有用。一旦你有了 **PFEntityToken**，就可以使用 **PFEntityGetEntityKey** 检索 **PFEntityKey**。

```cpp theme={null}
    PFEntityKey const* pEntityKey{};
    std::vector<char> entityKeyBuffer;
    size_t size{};
    HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size); // Add your own error handling when FAILED(hr) == true

    entityKeyBuffer.resize(size);
    hr = PFEntityGetEntityKey(entityHandle, entityKeyBuffer.size(), entityKeyBuffer.data(), &pEntityKey, nullptr);
```

### 调用 GetFiles

所有 PlayFab 调用都遵循类似的模式：准备请求对象、进行调用（使用登录得到的 **PFEntityHandle**）、创建接收响应的对象，然后调用 **GetResult** 函数以填充新创建的容器。

```cpp theme={null}
    XAsyncBlock async{};
    PFDataGetFilesRequest requestFiles{};
    requestFiles.entity = pEntityKey;

    HRESULT hr = PFDataGetFilesAsync(entityHandle, &requestFiles, &async); // Add your own error handling when FAILED(hr) == true
    hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

    size_t resultSize;
    hr = PFDataGetFilesGetResultSize(&async, &resultSize);

    std::vector<char> getFilesResultBuffer(resultSize);
    PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
    hr = PFDataGetFilesGetResult(&async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
```

## 清理

当你的游戏准备关闭或你出于其他原因需要清理 PlayFab 时，请确保关闭所有已打开的句柄并调用 **PFServicesUninitializeAsync**。

```cpp theme={null}
    PFEntityCloseHandle(entityHandle);
    entityHandle = nullptr;

    PFServiceConfigCloseHandle(serviceConfigHandle);
    serviceConfigHandle = nullptr;

    XAsyncBlock async{};
    HRESULT hr = PFServicesUninitializeAsync(&async); // Add your own error handling when FAILED(hr) == true
    hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
```

## 异步 API 模式

PlayFab Services SDK 遵循 GDK 中实现的[异步编程模型](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/system/overviews/async-programming-model)。此编程模型涉及使用由 [XAsync 库](/build/core-features/common/async/async-libraries/async-library-xasync)提供的任务和任务队列。此模型与其他 GDK 函数和扩展（如 XBOX Services API）保持一致。虽然它引入了一些复杂性，但也带来了对异步操作的高度控制。

以下示例展示了如何对 **PFDataGetFilesAsync** 进行异步调用。

```cpp theme={null}
    auto async = std::make_unique<XAsyncBlock>();
    async->callback = [](XAsyncBlock* async)
    {
        std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // take ownership of XAsyncBlock

        size_t resultSize;
        HRESULT hr = PFDataGetFilesGetResultSize(async, &resultSize);
        if (SUCCEEDED(hr))
        {
            std::vector<char> getFilesResultBuffer(resultSize);
            PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
            PFDataGetFilesGetResult(async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
        }
    };

    PFDataGetFilesRequest requestFiles{};
    requestFiles.entity = m_pEntityKey;
    HRESULT hr = PFDataGetFilesAsync(m_entityHandle, &requestFiles, async.get());
    if (SUCCEEDED(hr))
    {
        async.release(); // at this point, the callback will be called so release the unique ptr
    }

```

## 错误处理

已完成的 **XAsync** 操作返回 HTTP 状态代码。错误状态代码在调用 **XAsyncGetStatus()** 或某个 **PF\*Get()** API 时表现为失败的 **HRESULT**，例如 **HTTP\_E\_STATUS\_NOT\_FOUND**。

要查看服务返回的详细错误消息，请参阅下一节关于调试的内容。这些详细的错误消息在开发期间可用于更好地理解 PlayFab 服务对客户端请求的反应。

## 调试

查看结果并调试 PlayFab Services SDK 中任何调用的最简单方法是启用 [调试跟踪](/services/playfab/sdks/c/tracing)。启用调试跟踪后，你既可以在调试器输出窗口中看到结果，也可以将结果挂接到自己游戏的日志中。

## 参见

[API 参考文档](/services/playfab/api-references/c/pfauthentication/pfauthentication_members)


## Related topics

- [PlayFab 支持的语言](/zh-CN/services/playfab/sdks/languages/index.md)
- [旧版 C++ PlayFab SDK](/zh-CN/services/playfab/sdks/playfab-cpp/index.md)
- [iOS 和 macOS 快速入门](/zh-CN/services/playfab/multiplayer/networking/apple-specific-requirements.md)
- [欺诈防范快速入门](/zh-CN/services/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart.md)
- [Party Unity 插件快速入门](/zh-CN/services/playfab/multiplayer/networking/party-unity-plugin-quickstart.md)
