스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
StoreKit 2 및 Xcode 내 StoreKit Testing의 새로운 기능
StoreKit 2의 최신 개선 사항과 Xcode의 StoreKit Testing에 대해 알아보세요. 앱 내 구입 홍보, StoreKit 메시지, 트랜잭션 모델, RenewalInfo 모델, 구독 관리용 App Store 시트에 대한 API 업데이트를 함께 살펴봅니다. 기기 내에서의 영수증 검증을 위해 SHA-256로 업그레이드하는 방법과 API를 사용하여 SwiftUI 뷰를 생성하는 방법도 알아보세요. 또한 앱 내 구입 및 구독을 디버깅하고 테스트할 수 있도록 Xcode에서 StoreKit Testing을 시작하는 방법도 알려드립니다. 트랜잭션 인스펙터를 알아보고, StoreKit 구성 에디터의 최신 업데이트 내용을 살펴보고, StoreKit 오류를 시뮬레이션하여 앱의 오류 처리를 테스트하는 방법을 배워보세요.
리소스
- Message
- Setting up StoreKit Testing in Xcode
- StoreKit
- Submit feedback
- Supporting promoted In-App Purchases in your app
- Testing failing subscription renewals and In-App Purchases
- Turn on Family Sharing for in-app purchases in App Store Connect
관련 비디오
WWDC23
WWDC22
WWDC21
-
다운로드Array
-
-
1:42 - Create a listener for promoted in-app purchases
// Create a listener for promoted in-app purchases import StoreKit let promotedPurchasesListener = Task { for await promotion in PurchaseIntent.intents { // Process promotion let product = promotion.product // Purchase promoted product do { let result = try await product.purchase() // Process result } catch { // Handle error } } }
-
2:57 - Check promotion order
// Check promotion order import StoreKit do { let promotions = try await Product.PromotionInfo.currentOrder if promotions.isEmpty { // No local promotion order set } for promotion in promotions { let productID = promotion.productID let productVisibility = promotion.visibility // Check promoted products } } catch { // Handle error }
-
3:26 - Set a promotion order
// Set a promotion order import StoreKit let newPromotionOrder: [String] = [ "acorns.individual", "nectar.cup", "sunflowerseeds.pile" ] do { try await Product.PromotionInfo.updateProductOrder(byID: newPromotionOrder) } catch { // Handle error }
-
4:02 - Update promotion visibility
// Update promotion visibility import StoreKit // Hide “acorns.individual” do { try await Product.PromotionInfo.updateProductVisibility(.hidden, for: "acorns.individual") } catch { // Handle error }
-
4:17 - Update promotion visibility (alternative method)
// Update promotion visibility import StoreKit do { let promotions = try await Product.PromotionInfo.currentOrder // Hide the first product if var firstPromotion = promotions.first { firstPromotion.visibility = .hidden try await firstPromotion.update() } } catch { // Handle error }
-
8:32 - Product view
// Product view import SwiftUI import StoreKit struct BirdFoodShop: View { let productID: String let productImage: String var body: some View { ProductView(id: productID) { BirdFoodProductIcon(for: productID) } .productViewStyle(.large) } }
-
8:52 - Store view
// Store view import SwiftUI import StoreKit struct BirdFoodShop: View { let productIDs: [String] var body: some View { StoreView(ids: productIDs) { product in BirdFoodIcon(productID: product.id) } } }
-
9:19 - Subscription view
// Subscription view import SwiftUI import StoreKit struct BackyardBirdsPassShop: View { let groupID: String var body: some View { SubscriptionStoreView(groupID: groupID) } }
-
21:09 - Simulated off-device purchase using StoreKitTest
// Simulated off-device purchase using StoreKitTest import StoreKit import StoreKitTest func testSubscriptionRenewal() async throws { let session = try SKTestSession(configurationFileNamed: "Store") let oneYearInterval: TimeInterval = (365 * 24 * 60 * 60) let transaction = try await session.buyProduct( identifier: "birdpass.individual", options: [ .purchaseDate(Date.now - oneYearInterval) ] ) // Inspect transaction }
-
21:48 - Set a simulated purchase error when loading products
// Set a simulated purchase error when loading products import StoreKit import StoreKitTest func testLoadProducts() async throws { let session = try SKTestSession(configurationFileNamed: "Store") let productIDs = [ "acorns.individual", "nectar.cup" ] // Set a simulated error, then load products, expecting an error session.setSimulatedError(.generic(.networkError), forAPI: .loadProducts) do { _ = try await Product.products(for: productIDs) XCTFail("Expected a network error") } catch StoreKitError.networkError(_) { // Expected error thrown, continue... } // Disable simulated error session.setSimulatedError(nil, forAPI: .loadProducts) }
-
22:24 - Set a faster subscription renewal rate in a test session
// Set a faster subscription renewal rate in a test session import StoreKit import StoreKitTest func testSubscriptionRenewal() async throws { let session = try SKTestSession(configurationFileNamed: "Store") // Set renewals to expire every minute session.timeRate = .oneRenewalEveryMinute let transaction = try await session.buyProduct(identifier: "birdpass.individual") // Wait for renewals and inspect transactions }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.