스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
App Store 특가 구현하기
App Store Connect와 최신 StoreKit 기능 및 API로 App Store 특가를 통해 사용자의 참여도를 높이는 방법을 알아보세요. 이전 구독자를 되찾고 구독 재참여를 유도하기 위한 특가 항목을 설정하는 방법과 Mac용 앱을 위한 특가 코드를 생성하는 방법을 설명합니다. 샌드박스 및 Xcode상의 테스트를 통해 특가 항목이 원활하게 작동하는지 확인하는 방법도 살펴보세요.
챕터
- 0:00 - Introduction
- 1:32 - Updates to offers
- 4:37 - Introducing win-back offers
- 7:10 - Configure win-back offers
- 16:50 - Support win-back offers
- 28:44 - Streamlined purchasing
리소스
- Forum: App Store Distribution & Marketing
- Generating a signature for promotional offers
- Message
- offer
- PurchaseIntent
- Setting up StoreKit Testing in Xcode
- StoreKit views
- Submit feedback
- Supporting subscription offer codes in your app
- Testing win-back offers in Xcode
관련 비디오
WWDC24
WWDC23
-
다운로드Array
-
-
4:25 - Present offer code redemption sheet on macOS - SwiftUI API
// Present offer code redemption sheet on macOS - SwiftUI API import SwiftUI import StoreKit struct MyView: View { @State var showOfferCodeRedemption: Bool = false var body: some View { Button("Redeem Code") { showOfferCodeRedemption = true } .offerCodeRedemption(isPresented: $showOfferCodeRedemption) { result in // Handle result } } }
-
20:15 - Choose preferred offer in a SubscriptionStoreView
// Choose preferred offer in a SubscriptionStoreView import SwiftUI import StoreKit struct MyView: View { let groupID: String var body: some View { SubscriptionStoreView(groupID: groupID) .preferredSubscriptionOffer { product, subscription, eligibleOffers in let freeTrialOffer = eligibleOffers .filter { $0.paymentMode == .freeTrial } .max { lhs, rhs in lhs.period.value < rhs.period.value } return freeTrialOffer ?? eligibleOffers.first } } }
-
23:05 - Check subscription entitlement and offer eligibility
// Check subscription entitlement and offer eligibility import StoreKit func shouldShowMerchandising( for groupID: String, productIDs: [Product.ID] ) async throws -> MerchandisingVisibility { // Get subscription status let statuses = try await Product.SubscriptionInfo.status(for: groupID) // Check if the customer is already entitled to the subscription let entitlement = SubscriptionEntitlement(for: statuses) if entitlement.autoRenewalEnabled { return .hidden } // Check for offers to show in merchandising UI let products = try await Product.products(for: productIDs) let isEligibleForIntroOffer = await Product.SubscriptionInfo.isEligibleForIntroOffer(for: groupID) if isEligibleForIntroOffer { let subscriptions = products.map { ($0, $0.subscription?.introductoryOffer) } return .visible(subscriptions) } // Check for eligible win-back offers let purchasedStatus = statuses.first { $0.transaction.unsafePayloadValue.ownershipType == .purchased } let renewalInfo = try purchasedStatus?.renewalInfo.payloadValue let bestWinBackOfferID = renewalInfo?.eligibleWinBackOfferIDs.first // Return the product with the offer if there is one if let bestWinBackOfferID { let subscriptions: [(Product, Product.SubscriptionOffer?)] = products.map { let winBackOffer = $0.subscription?.winBackOffers.first { $0.id == bestWinBackOfferID } return ($0, winBackOffer) } return .visible(subscriptions) } // Only return the product if there is no offer return .visible(products.map { ($0, nil) }) } struct SubscriptionEntitlement { let isEntitled: Bool let autoRenewalEnabled: Bool init(for statuses: [Product.SubscriptionInfo.Status]) { let entitledStatuses = statuses.filter { $0.state == .subscribed || $0.state == .inBillingRetryPeriod || $0.state == .inGracePeriod } isEntitled = !entitledStatuses.isEmpty autoRenewalEnabled = entitledStatuses.contains { $0.renewalInfo.unsafePayloadValue.willAutoRenew } } } enum MerchandisingVisibility { case hidden case visible([(Product, Product.SubscriptionOffer?)]) }
-
25:26 - Add a win-back offer to a purchase
// Add a win-back offer to a purchase import StoreKit func purchase( _ product: Product, with offer: Product.SubscriptionOffer? ) async throws { // Prepare the purchase options var purchaseOptions: Set<Product.PurchaseOption> = [] // Add win-back offer to the purchase if let offer, offer.type == .winBack { purchaseOptions.insert(.winBackOffer(offer)) } // Make the purchase try await product.purchase(options: purchaseOptions) }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.