
ブログ
import StoreKit
class PurchaseManager: ObservableObject {
@Published var isAdRemoved = false
private var task: Task<Void, Never>?
init() {
task = observeTransactions()
Task {
await updatePurchaseStatus()
}
}
deinit {
task?.cancel()
}
func purchaseRemoveAds() async throws {
guard let product = try await Product.products(for: ["com.yourapp.removeads"]).first else {
throw NSError(domain: "Product not found", code: 0)
}
let result = try await product.purchase()
if case .success(let verification) = result, case .verified = verification {
await updatePurchaseStatus()
}
}
private func updatePurchaseStatus() async {
for await result in Transaction.currentEntitlements {
if case .verified(let transaction) = result,
transaction.productID == "com.yourapp.removeads" {
await MainActor.run { self.isAdRemoved = true }
return
}
}
await MainActor.run { self.isAdRemoved = false }
}
private func observeTransactions() -> Task<Void, Never> {
Task.detached {
for await result in Transaction.updates {
if case .verified = result {
await self.updatePurchaseStatus()
}
}
}
}
}
@main
struct YourApp: App {
@StateObject var purchaseManager = PurchaseManager()
@State private var refreshID = UUID()
var body: some Scene {
WindowGroup {
VStack(spacing: 0) {
ContentView()
.id(refreshID)
.environmentObject(purchaseManager)
if !purchaseManager.isAdRemoved {
BannerAdView()
.frame(width: 320, height: 50)
}
}
.onChange(of: purchaseManager.isAdRemoved) {
refreshID = UUID() // Viewを更新
}
}
}
}
struct SettingsView: View {
@EnvironmentObject var purchaseManager: PurchaseManager
var body: some View {
Form {
Section(header: Text("広告設定")) {
if purchaseManager.isAdRemoved {
Label("広告は削除されています", systemImage: "checkmark.circle")
.foregroundColor(.green)
} else {
Button("広告を削除する") {
Task {
try? await purchaseManager.purchaseRemoveAds()
}
}
}
}
}
.navigationTitle("設定")
}
}
import GoogleMobileAds
import SwiftUI
struct BannerAdView: UIViewRepresentable {
func makeUIView(context: Context) -> GADBannerView {
let view = GADBannerView(adSize: kGADAdSizeBanner)
view.adUnitID = "ca-app-pub-3940256099942544/2934735716" // テストID
view.rootViewController = UIApplication.shared.windows.first?.rootViewController
view.load(GADRequest())
return view
}
func updateUIView(_ uiView: GADBannerView, context: Context) {}
}
StoreKit2では購入状態の監視を Transaction.updates で行う
SwiftUIでは @StateObject と @Published を活用し、動的に広告表示を切り替える
.id(UUID()) を使ってView全体をリフレッシュするのが即時反映のポイント
Q. 購入しても広告がすぐ消えません。
A. .id() によるView更新や @Published の反映漏れが原因です。onChange(of:)でリセットIDを切り替える方法が有効です。
Q. 広告を一度非表示にしたら復活しませんか?
A. StoreKit2は購入状態を自動で復元します。アプリ再起動後でも Transaction.currentEntitlements で取得可能です。
WWDCセッションの動画: Appleは毎年WWDCでStoreKitに関するセッションを公開しています。最新情報やベストプラクティスを学ぶのに最適です。過去のセッションもアーカイブされているので、「StoreKit」で検索してみてください。
Appleのサンプルコード: Appleが公開しているサンプルコードは、具体的な実装方法を理解する上で非常に役立ちます。「StoreKit」や「In-App Purchase」で検索すると関連するサンプルが見つかることがあります。
この記事へのトラックバックはありません。
この記事へのコメントはありません。