> ## 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](/zh-TW/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 套件組合，因為它同時適用於裝置和模擬器組建。*)

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 後端中正確的遊戲。

```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 程式庫](/zh-TW/build/core-features/common/async/async-libraries/async-library-xasync)所提供的工作和工作佇列。此模型與其他 GDK 函式和延伸模組 (例如 XBOX 服務 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 中任何呼叫的結果並加以偵錯，最簡單的方式是啟用[偵錯追蹤](/zh-TW/services/playfab/sdks/c/tracing)。啟用偵錯追蹤後，您既可以在偵錯工具輸出視窗中查看結果，也可以將結果連結至遊戲本身的記錄。

## 另請參閱

[API 參考文件](/zh-TW/services/playfab/api-references/c/pfauthentication/pfauthentication_members)


## Related topics

- [PlayFab 支援的語言](/zh-TW/services/playfab/sdks/languages/index.md)
- [Party 快速入門](/zh-TW/services/playfab/multiplayer/networking/quickstart.md)
- [詐騙防範快速入門](/zh-TW/services/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart.md)
- [推播通知快速入門](/zh-TW/services/playfab/live-service-management/game-configuration/title-communications/push-notifications/quickstart.md)
- [快速入門](/zh-TW/services/playfab/economy-monetization/economy-v2/quickstart.md)
