Available in Classic and VPC
This page describes how to use GAMEPOT iOS SDK for developing games in iOS. You can integrate the game and dashboard by installing the SDK and configuring the environment.
Requirements
The recommended specifications required to use the GAMEPOT SDK for iOS are as follows:
- Minimum specifications: iOS 15 or later
(If you need support for a lower version of iOS, please contact Ncloud Support with your request. )
Install SDK and configure environment
You can install the iOS SDK, configure the environment, and integrate the game and GAMEPOT dashboard to use features required for the game development.
The GAMEPOT SDK supports the following languages.
- Korean, English, Italian, Thai, Vietnamese, Japanese, Chinese (Simplified/Traditional), Indonesian, German, Spanish, French
When the app is launched, it is displayed in the supported language in the SDK based on the device's language. If it is an unsupported language, it will be displayed in English.
SDK installation
The following describes how to install GAMEPOT iOS SDK and configure a project.
- Log in to the dashboard with the admin account.
- Create a podfile via CocoaPods in the iOS project folder.
pod init - Add the NBase SDK to the podfile file. For podfile definitions, see "Set podfile" item below.
- Install the NBase SDK via CocoaPods.
pod install
For the iOS SDK, cocoapods must be installed for normal installation.
Set podfile
Open the podfile with an editor and add the frameworks required by the GAMEPOT SDK.
platform :ios, '15.0'
# Project main target
target 'project main target' do
...
pod 'NBase'
...
end
- When using Google login and Facebook login
platform :ios, '15.0'
target 'GAMEPOT_GAME' do
use_frameworks!
# Pods for Nbase SDK
pod 'NBase'
pod 'NBaseAdapterProviderGoogle'
pod 'NBaseAdapterProviderFacebook'
end
| Name | Version | Description | Dependeny modules |
|---|---|---|---|
| NBase | 3.0.59 | GAMEPOT base module | X |
| NBaseAdapterProviderGoogle | 3.0.56 | Google login | X |
| NBaseAdapterProviderFacebook | 3.0.57 | Facebook login | FBSDKLoginKit (17.4.0) |
| NBaseAdapterProviderNaver | 3.0.57 | NAVER Login | X |
| NBaseAdapterProviderLine | 3.0.57 | LINE login | X |
| NBaseAdapterProviderKakao | 3.0.56 | Kakao login | X |
| NBaseAdapterProviderX | 3.0.57 | X login | X |
Email, Apple, and guest logins are applied to the base module.
Some dependent frameworks can only be added through the Swift Package Manager.
-
In Xcode, go to Project Settings, and then enter the Package Dependencies settings.

-
Add "https://github.com/apollographql/apollo-ios.git" to the URL input field at the top right, search for it, select apollo-ios, and then add it with Add Package.
-
Add the Apollo and ApolloAPI modules displayed in the modal to the main target of your project.

Name Dependeny modules Location Version Framework NBase Apollo https://github.com/apollographql/apollo-ios.git 1.15.2
Preparation
- Copy the project ID and project key from Dashboard > Project settings.
- You can configure login, store, and integration settings in Dashboard > Project settings.
- See Configuration by login method for each login, set it in the console and add it to the dashboard.
- For in-app payment, see Configuration by store to set it in the console and add it to the dashboard.
- Register items for each store for in-app payment. Add them in Dashboard > Payment > In-app .
Reset
To perform an initialization, add the following code to the object used in the first scene loaded when the game starts.
Swift:
import NBase
NBase.initialize([projectId], projectKey: [projectKey], storeId: [storeId], language: [language], region: [region]) { result in
switch result {
case .success(let data):
NBase.showToast(message: data?.encodeToJson() ?? "")
case .failure(let error):
NBase.showToast(message: error.errorDescription ?? "")
}
}
Objective-C:
[NBaseBridge.shared initialize:[projectId] projectKey:[projectKey] storeId:[storeId] language:[language] region:[region] :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"Initialization Error: %@", error.localizedDescription);
} else {
NSLog(@"Initialization succeeded with result: %@", result);
}
}];
- Parameter
| Key | Type | Description | Required |
|---|---|---|---|
| projectId | String | Project ID (Dashboard → Project settings) | O |
| projectKey | String | Project key (Dashboard → Project settings) | O |
| storeId | String | Store name (Apple) | O |
| language | String | Language (en, ko, jp...) | O |
| region | String | Region name (kr, jp, sg, us, eu, preview) | O |
- Callback
| Key | Type | Description |
|---|---|---|
| status | Bool | Condition |
| language | String | Language |
| country | String | Country |
| remote_ip | String | IP |
| platform | String | Platform |
| sandbox | Bool | Sandbox status |
Login feature
Use login feature
Use the following code to use the SDK login feature that functions when clicking the login button according to the login UI implemented by the developer.
Swift:
NBase.signIn(serviceType: .google) { result in
switch result {
case .success(let data):
// signIn Success
print("signIn Success: \(data)")
break
case .failure(let error):
// signIn failed
print("signIn Failed: \(error)")
case .maintenance(let data):
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("maintenance: \(data)")
case .update(let data):
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("update: \(data)")
}
}
Objective-C:
[NBaseBridge.shared signIn:google :^(NSDictionary * _Nullable result, NSError * _Nullable error, NSDictionary * _Nullable errorData) {
if (error) {
// signIn failed
NSLog(@"signIn Failed: %@", error.localizedDescription);
} else if (result) {
NSDictionary *appStatus = result[@"appStatus"];
if (appStatus && appStatus[@"type"]) {
NSString *statusType = appStatus[@"type"];
if ([statusType isEqualToString:@"maintenance"]) {
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"maintenance: %@", appStatus);
}
else if ([statusType isEqualToString:@"update"]) {
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"update: %@", appStatus);
}
}
else {
// signIn success
NSLog(@"signIn Success: %@", result);
}
}
}];
If you use the pop-up provided by the SDK when updating or checking, add the following code.
Swift:
NBase.showAppStatusPopup(status: appStatus){ status, e in
if status.close {
// App Close
}
if status.next{
// Next, Optional update
}
}
Objective-C:
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
if (popupError) {
// showAppStatusPopup Error
} else if (popupResult) {
BOOL shouldClose = [[popupResult objectForKey:@"close"] boolValue];
BOOL shouldProceedNext = [[popupResult objectForKey:@"next"] boolValue];
if (shouldClose) {
// App Close
} else if (shouldProceedNext) {
// Next, Optional update
}
}
}];
- Parameter
| Key | Description |
|---|---|
| SignInServiceType.google | |
| SignInServiceType.anonymous | Guest |
| SignInServiceType.facebook | |
| SignInServiceType.apple | Apple |
| SignInServiceType.kakao | Kakao |
| SignInServiceType.x | X |
| SignInServiceType.line | LINE |
| SignInServiceType.naver | NAVER |
| SignInServiceType.github | GitHub |
| SignInServiceType.microsoft | Microsoft |
| SignInServiceType.huawei | Huawei |
- User
| Key | Type | Description |
|---|---|---|
| id | string | User's unique ID |
| socialId | string | Social ID |
| name | string | Name (if provided) |
| string | Email (if provided) | |
| token | string | Token |
| age | int | Age (if provided) |
| profile | string | Profile (if provided) |
| customField | string | Custom field |
| isSignUp | bool | Registration status |
| appStatus | AppStatus | Maintenance/update status |
- AppStatus
| Key | Type | Description |
|---|---|---|
| message | string | Message |
| startedAt | long | Start Time |
| endedAt | long | Exit time |
| currentAppVersion | string | Current app version |
| updateAppVersion | string | Update app version |
| currentAppVersionCode | string | Current app version code |
| updateAppVersionCode | string | Update app version code |
| isForce | bool | Whether to force update |
| url | string | URL registered for maintenance/update |
Login UI provided by SDK
You can use the login UI provided by GAMEPOT SDK in a completed form.
Use the following code to call the login UI provided by the SDK.
Swift:
NBase.openSignInUI { result in
switch result {
case .success(let data):
// openSignInUI Success
print("openSignInUI Success: \(data)")
break
case .failure(let error):
// openSignInUI failed
print("openSignInUI Failed: \(error)")
case .maintenance(let data):
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("maintenance: \(data)")
case .update(let data):
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("update: \(data)")
}
}
Objective-C:
[NBaseBridge.shared openSignInUI:^(NSDictionary * _Nullable result, NSError * _Nullable error, NSDictionary * _Nullable errorData) {
if (error) {
// openSignInUI Error
NSLog(@"openSignInUI Error: %@", error.localizedDescription);
} else if (result) {
NSDictionary *appStatus = result[@"appStatus"];
if (appStatus && appStatus[@"type"]) {
NSString *statusType = appStatus[@"type"];
if ([statusType isEqualToString:@"maintenance"]) {
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"maintenance: %@", appStatus);
return;
}
else if ([statusType isEqualToString:@"update"]) {
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"update: %@", appStatus);
return;
}
}
else {
// openSignInUI Success
NSLog(@"openSignInUI Success: %@", result);
}
}
}];
Auto login (optional)
After initialization, it will attempt to automatically log in with the last authentication method you logged in with. We recommend checking the last login provider type before attempting automatic login.
Swift:
// Check the last login provider type.
let lastProviderType = NBase.getLastProviderType()
if lastProviderType != .none {
// Attempt automatic login only if last login information is available.
NBase.signInLastLoggedIn(completionHandler: { result in
switch result {
case .success(let data):
// signInLastLoggedIn Success
print("signInLastLoggedIn Success: \(data)")
case .failure(let error):
// signInLastLoggedIn failed
print("signInLastLoggedIn Failed: \(error)")
case .maintenance(let data):
/* maintenance
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("maintenance: \(data)")
case .update(let data):
/* update
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("update: \(data)")
}
})
} else {
print("No last login provider found")
}
Objective-C:
// Check the last login provider type.
SignInServiceType lastProviderType = [NBaseBridge.shared getLastProviderType];
if (lastProviderType != SignInServiceTypeNone) {
// Attempt automatic login only if last login information is available.
[NBaseBridge.shared signInLastLoggedIn:^(NSDictionary * _Nullable result, NSError * _Nullable error, NSDictionary * _Nullable errorData) {
if (error) {
// signInLastLoggedIn failed
NSLog(@"signInLastLoggedIn Failed: %@", error.localizedDescription);
} else if (result) {
NSDictionary *appStatus = result[@"appStatus"];
if (appStatus && appStatus[@"type"]) {
NSString *statusType = appStatus[@"type"];
if ([statusType isEqualToString:@"maintenance"]) {
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"maintenance: %@", appStatus);
return;
}
else if ([statusType isEqualToString:@"update"]) {
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"update: %@", appStatus);
return;
}
}
else {
// signInLastLoggedIn success
NSLog(@"signInLastLoggedIn Success: %@", result);
}
}
}];
} else {
NSLog(@"No last login provider found");
}
The getLastProviderType() method returns the last logged-in provider type.
The signInLastLoggedIn() method attempts automatic login using the last authentication method used to log in.
- Callback
| Key | Type | Description |
|---|---|---|
| data | NBUser | User information upon successful login |
| error | NBaseError | Error information upon login failure |
Log out
Use the following code to use the SDK logout feature.
Swift:
NBase.signOut() { result in
switch result {
case .success(let status):
// signOut Success
print("signOut Success: \(status ?? false)")
case .failure(let error):
// signOut Failed
print("signOut Failed: \(error.errorCode), \(error.errorDescription ?? "")")
}
}
Objective-C:
[NBaseBridge.shared signOut:^(NSNumber *result, NSError *error) {
if (error) {
// signOut Failed
NSLog(@"signOut Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else {
// signOut Success
NSLog(@"signOut Success: %@", result.boolValue ? @"YES" : @"NO");
}
}];
- Callback
| Key | Type | Description |
|---|---|---|
| status | Bool | Success or Failure |
Membership withdrawal
Use the following code to use the SDK membership withdrawal feature.
Swift:
NBase.deleteMember() { result in
switch result {
case .success(let status):
// deleteMember Success
print("deleteMember Success: \(status ?? false)")
case .failure(let error):
// deleteMember Failed
print("deleteMember Failed: \(error.errorCode), \(error.errorDescription ?? "")")
}
}
Objective-C:
[NBaseBridge.shared deleteMember:^(NSNumber *result, NSError *error) {
if (error) {
// deleteMember Failed
NSLog(@"deleteMember Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else {
// deleteMember Success
NSLog(@"deleteMember Success: %@", result.boolValue ? @"YES" : @"NO");
}
}];
- Callback
| Key | Type | Description |
|---|---|---|
| status | Bool | Success or Failure |
Authenticate with ID and password (optional)
This is an authentication method that allows users to log in using their email address and password. It performs user authentication based on the user's email address and password. This feature plays an important role in traditional email/password-based authentication systems.
Swift:
NBase.signInWithPassword(username: [username], password: [password], options: [option]) { result in
switch result {
case .success(let user):
NBase.showToast(message: user?.encodeToJson() ?? "")
case .failure(let error):
NBase.showToast(message: error.errorDescription ?? "")
}
}
Objective-C:
[NBaseBridge.shared signInWithPassword:[username] password:[password] options:[options] :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
NSLog(@"signInWithPassword Error: %@", error.localizedDescription);
} else {
NSLog(@"signInWithPassword succeeded with result: %@", result);
}
}];
Log in with credentials (optional)
Use the following code to log in using credentials (access tokens) obtained from external social accounts.
Swift:
NBase.signInWithCredential(providerId: providerId, accessToken: accessToken, options: options) { result in
switch result {
case .success(let data):
// signInWithCredential Success
print("signInWithCredential Success: \(data)")
case .failure(let error):
// signInWithCredential Failed
print("signInWithCredential Failed: \(error.errorCode), \(error.errorDescription ?? "")")
case .maintenance(let data):
/* maintenance
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("maintenance: \(data)")
case .update(let data):
/* update
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: (data?.appStatus)) { status, e in
// Popup handling
}
*/
print("update: \(data)")
}
}
Objective-C:
[NBaseBridge.shared signInWithCredential:providerId accessToken:accessToken options:options :^(NSDictionary * _Nullable result, NSError * _Nullable error, NSDictionary * _Nullable errorData) {
if (error) {
// signInWithCredential Failed
NSLog(@"signInWithCredential Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else if (result) {
NSDictionary *appStatus = result[@"appStatus"];
if (appStatus && appStatus[@"type"]) {
NSString *statusType = appStatus[@"type"];
if ([statusType isEqualToString:@"maintenance"]) {
/* maintenance
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"maintenance: %@", appStatus);
return;
}
else if ([statusType isEqualToString:@"update"]) {
/* update
case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:appStatus :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"update: %@", appStatus);
return;
}
}
else {
// signInWithCredential success
NSLog(@"signInWithCredential Success: %@", result);
}
}
}];
- Parameter
| Key | Type | Description | Required |
|---|---|---|---|
| providerId | String | Provider ID (example: “google,” “facebook,” etc.) | O |
| accessToken | String | Access token of the social account | O |
| options | String | Additional options (optional) | X |
- Callback
| Key | Type | Description |
|---|---|---|
| data | NBUser | User information upon successful login |
| error | NBaseError | Error information upon login failure |
External account integration feature
Use external account integration feature
Use the following code to integrate another social account with your current GAMEPOT user account.
Swift:
NBase.createLinking(serviceType: .google) { result in
switch result {
case .success(let linkingId):
// createLinking Success
print("createLinking Success: \(linkingId ?? "")")
// Processing logic after successful account integration
case .failure(let error):
// createLinking Failed
print("createLinking Failed: \(error.errorCode), \(error.errorDescription ?? "")")
}
}
Objective-C:
[NBaseBridge.shared createLinking:google :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// createLinking Failed
NSLog(@"createLinking Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else {
// createLinking Success
NSLog(@"createLinking Success: %@", result);
// Processing logic after successful account integration
}
}];
- Parameter
| Key | Type | Description | Required |
|---|---|---|---|
| serviceType | SignInServiceType | Provider type to integrate (example: .google, .facebook, etc.) | O |
- Callback
| Key | Type | Description |
|---|---|---|
| linkingId | String | Integration ID returned when integration is successful |
Check integration list
Use the following code to check the list of social accounts currently integrated with your GAMEPOT user account.
Swift:
NBase.getLinkedLists() { result in
switch result {
case .success(let linkings):
// getLinkedLists Success
print("getLinkedLists Success: \(linkings)")
// Processing logic after checking the integration list
case .failure(let error):
// getLinkedLists Failed
print("getLinkedLists Failed: \(error.errorCode), \(error.errorDescription ?? "")")
}
}
Objective-C:
[NBaseBridge.shared getLinkedLists:^(NSDictionary * _Nullable result, NSError * _Nullable error) {
if (error) {
// getLinkedLists Failed
NSLog(@"getLinkedLists Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else {
// getLinkedLists Success
NSLog(@"getLinkedLists Success: %@", result);
// Processing logic after checking the integration list
}
}];
- Callback
| Key | Type | Description |
|---|---|---|
| linkings | Array | List of integrated accounts |
- Linking
| Key | Type | Description |
|---|---|---|
| id | String | Integration ID (use when removing account integration) |
| username | String | Social ID |
| provider | String | Social provider type |
Remove integration
To remove a specific social account integration from your current GAMEPOT user account, use the following code.
Swift:
NBase.deleteLinking(linkingId: linkingId) { result in
switch result {
case .success(let status):
// deleteLinking Success
print("deleteLinking Success: \(status ?? false)")
// Processing logic after successful integration removal
case .failure(let error):
// deleteLinking Failed
print("deleteLinking Failed: \(error.errorCode), \(error.errorDescription ?? "")")
}
}
Objective-C:
[NBaseBridge.shared deleteLinking:linkingId :^(NSNumber * _Nullable result, NSError * _Nullable error) {
if (error) {
// deleteLinking Failed
NSLog(@"deleteLinking Failed: %ld, %@", (long)error.code, error.localizedDescription);
} else {
// deleteLinking Success
NSLog(@"deleteLinking Success: %@", result.boolValue ? @"YES" : @"NO");
// Processing logic after successful integration removal
}
}];
- Parameter
| Key | Type | Description | Required |
|---|---|---|---|
| linkingId | String | Integration ID to remove (obtained from createLinking or getLinkedLists) | O |
- Callback
| Key | Type | Description |
|---|---|---|
| status | Bool | Success or Failure |
Check app status
Use the following code to check the current client's maintenance/update status.
Swift:
NBase.checkAppStatus() { status in
switch status {
case .success(let data):
if let data = data {
switch data {
case .maintenance(let maintenance):
// Maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: data) { status, e in
// Popup handling
}
*/
case .update(let update):
// Update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
NBase.showAppStatusPopup(status: data) { status, e in
// Popup handling
}
*/
}
} else {
// AppStatus Success
print("checkAppStatus success")
}
case .failure(let error):
print("checkAppStatus error: \(error)")
}
}
Objective-C:
[NBaseBridge.shared checkAppStatus:^(NSDictionary * _Nullable result, NSError * _Nullable error, NSDictionary * _Nullable errorData) {
if (error) {
NSLog(@"checkAppStatus error: \(error.localizedDescription)");
} else if (result) {
NSString *type = result[@"type"];
if ([type isEqualToString:@"maintenance"]) {
// maintenance
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:result :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"maintenance: %@", result);
}
else if ([type isEqualToString:@"update"]) {
// update
/* case 1: Use in-game popup implemented directly by the developer
case 2: Call the code below to use the SDK's own popup
[NBaseBridge.shared showAppStatusPopup:result :^(NSDictionary * _Nullable popupResult, NSError * _Nullable popupError) {
// Popup handling
}];
*/
NSLog(@"update: %@", result);
}
} else {
// AppStatus Success
NSLog(@"Normal Status - No maintenance or update required");
}
}];
Troubleshooting
Q. Authorization failed: Error Domain=AKAuthenticationError Code=-7026
A. Add Sign In with Apple by clicking TARGETS > +Capability .
