рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдФрд░ рдСрдЯреЛ-рд░рд┐рдиреНрдпреВрдПрдмрд▓ рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди

рдЫрд╡рд┐


рдирдорд╕реНрддреЗ! Apphud рд╕реЗ рдХрдиреЗрдХреНрдЯреЗрдб рдбреЗрдирд┐рд╕ - рдЖрдИрдУрдПрд╕-рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдХреНрд╖рдп рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗрд╡рд╛ред


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, WWDC 2019 рдореЗрдВ, Apple рдиреЗ рдЕрдкрдиреЗ рдирдП рдШреЛрд╖рдгрд╛рддреНрдордХ SwiftUI рдврд╛рдВрдЪреЗ рдХреА рдШреЛрд╖рдгрд╛ рдХреАред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдпрд╣ рдмрддрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рднреБрдЧрддрд╛рди рд╕реНрдХреНрд░реАрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ рдФрд░ рдСрдЯреЛ-рдЕрдХреНрд╖рдп рд╕рджрд╕реНрдпрддрд╛ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред


рдпрджрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рд▓рдШреБ рдкрд░рд┐рдЪрдпрд╛рддреНрдордХ рд▓реЗрдЦ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ рдпрджрд┐ рдЖрдк рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рддреЛ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдкрдврд╝реЗрдВред

рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ Xcode 11 рдЪрд╛рд╣рд┐рдПред рдПрдХ рдирдпрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ "SwiftUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ" рдХреЗ рдмрдЧрд▓ рдореЗрдВ рдПрдХ рдЪреЗрдХ рдорд╛рд░реНрдХ рд╣реИ ред


SwiftUI рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд░рдп рдкреНрд░рдмрдВрдзрдХ рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╣рдо рдЕрдкрдиреЗ рдкреНрд░рдмрдВрдзрдХ рдХреЛ рдирд╣реАрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдПрдХ рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЬрд┐рд╕реЗ рд╣рдо рдЕрдкрдиреЗ рдХреЛрдб рдХреЗ рд╕рд╛рде рдкреВрд░рдХ рдХрд░реЗрдВрдЧреЗред рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, SwiftyStoreKit ред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рд╕реЗ рдХрдХреНрд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред


рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдореБрдЦреНрдп рд╕реНрдХреНрд░реАрди рдкрд░ рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд╣рдорд╛рд░реА рд╕рджрд╕реНрдпрддрд╛ рдХреА рд╕рдорд╛рдкреНрддрд┐ рддрд┐рдерд┐ рдФрд░ рдЦрд░реАрдж рд╕реНрдХреНрд░реАрди рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдЯрди рднреА рд╡рд╣рд╛рдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗред


ProductsStore.shared.initializeProducts() if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: ContentView(productsStore: ProductsStore.shared)) self.window = window window.makeKeyAndVisible() } 

SceneDelegate рд╡рд░реНрдЧ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдЗрд╕рдореЗрдВ, рд╣рдо рдПрдХ рд╕рд┐рдВрдЧрд▓рдЯрди рдХреНрд▓рд╛рд╕ ProductsStore рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░рд╛ рд░реВрдЯ ContentView рдмрдирд╛рдПрдВ рдФрд░ рд╕рд┐рдВрдЧрд▓рдЯрди рдХреЛ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред
ProductStore рд╡рд░реНрдЧ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


 class ProductsStore : ObservableObject { static let shared = ProductsStore() @Published var products: [SKProduct] = [] @Published var anyString = "123" // little trick to force reload ContentView from PurchaseView by just changing any Published value func handleUpdateStore(){ anyString = UUID().uuidString } func initializeProducts(){ IAPManager.shared.startWith(arrayOfIds: [subscription_1, subscription_2], sharedSecret: shared_secret) { products in self.products = products } } } 

рдпрд╣ рдЫреЛрдЯрд╛ рд╡рд░реНрдЧ, IAPManager рдКрдкрд░ "рдРрдб-рдСрди" рдХрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░, рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╕рдордп IAPManager рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред ProductsStore рд╡рд░реНрдЧ ObservableObject рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред


@Published рдФрд░ @Published рдХреНрдпрд╛ рд╣реИрдВ?


ObservableObject рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдЕрд╡рд▓реЛрдХрди рдФрд░ рдЙрд╕рдХреЗ рдЧреБрдгреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдкрд░ рдирдЬрд╝рд░ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИред рдЧреБрдгреЛрдВ рдХреЛ @Published рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, products рд╕рд░рдгреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рднреЗрдЬреА рдЬрд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЗрд╕ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдХрд┐рд╕реА рднреА рддрд░реАрдХреЗ рдФрд░ рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред


рдЙрддреНрдкрд╛рдж рд▓реЛрдбрд┐рдВрдЧ рдХреЛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЕрдиреБрд░реЛрдз рдХреЗ рдЕрдВрдд рдореЗрдВ рдЖрдкрдХреЛ рдЙрддреНрдкрд╛рдж рдЪрд░ рдХреЛ рдЙрддреНрдкрд╛рдж рд╕рд░рдгреА рдЕрд╕рд╛рдЗрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдХреИрд╕реЗ рд╕реБрдиреЗрдВ? рдпрд╣ @ObservedObject рдХреБрдВрдЬреА рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 @ObservedObject var productsStore : ProductsStore 

рд╕реАрдзреЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдХрд╣реЗрдВ, рддреЛ рдпрд╣ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рдХреЗрдВрджреНрд░ рдХреЗ рд╕рдорд╛рди рд╣реИред рдФрд░ рдЗрди рд╕реВрдЪрдирд╛рдУрдВ View рд╕реНрд╡реАрдХрд╛рд░ View рд▓рд┐рдП рдЖрдкрдХреЗ View , рдЖрдкрдХреЗ рдкрд╛рд╕ @ObservedObject рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдПрдХ рдЪрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред


рдЪрд▓рд┐рдП ProductStore рд╡рд░реНрдЧ рдХреЗ рддрд░реНрдХ рдкрд░ рд╡рд╛рдкрд╕ рдЖрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдореБрдЦреНрдп рдЙрджреНрджреЗрд╢реНрдп рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕рд░рдгреА рдкрд╣рд▓реЗ рд╕реЗ рд╣реА IAPManager рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ, рджреЛрд╣рд░рд╛рд╡ рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрд┐рдирд┐рдВрдЧ рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рдЦрд░реАрдж рдкреНрд░рдмрдВрдзрдХ рдХреЗ рддреИрдпрд╛рд░ рд╡рд░реНрдЧ рдХреЛ рдмрджрд▓рдирд╛ рд╣рдореЗрд╢рд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рддреГрддреАрдп-рдкрдХреНрд╖ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк ObservableObject рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдФрд░ рд╕реВрдЪрдирд╛рдПрдВ рднреЗрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред


рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ @ObservedObject рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛, @ObservedObject рд╡рд┐рд╢реЗрд╖рддрд╛ рднреА рд╣реИ, рдЬреЛ рд╕рд░рд▓ рдЪрд░ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, String рдпрд╛ Int ) рдФрд░ рдЕрдзрд┐рдХ рд╡реИрд╢реНрд╡рд┐рдХ @EnvironmentObject рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдмреАрдЪ рдЪрд░ рдХреЛ рдкрд╛рд╕ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рдмрд╛рд░ рдореЗрдВ рд╕рднреА View рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред


рдЪрд▓рд┐рдП ContentView start рд╕реНрдХреНрд░реАрди ContentView рд╣реИрдВ:


 struct ContentView : View { @ObservedObject var productsStore : ProductsStore @State var show_modal = false var body: some View { VStack() { ForEach (productsStore.products, id: \.self) { prod in Text(prod.subscriptionStatus()).lineLimit(nil).frame(height: 80) } Button(action: { print("Button Pushed") self.show_modal = true }) { Text("Present") }.sheet(isPresented: self.$show_modal) { PurchaseView() } } } } 

рдХреЛрдб рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВред ForEach рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ ForEach рд╣рдо рдЯреЗрдХреНрд╕реНрдЯ View рдмрдирд╛рддреЗ View , рдЬрд┐рд╕рдХреА рд╕рдВрдЦреНрдпрд╛ рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрддреА рд╣реИред рдЪреВрдБрдХрд┐ рд╣рдо рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ productsStore рдмрд╛рдБрдзрддреЗ productsStore , рдЬрдм рднреА ProductsStore рд╡рд░реНрдЧ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИ, рддреЛ View рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


SKProduct рд╡рд┐рдзрд┐ SKProduct рд╡рд░реНрдЧ SKProduct рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдФрд░ рд╕рджрд╕реНрдпрддрд╛ рдХреА рд╕рдорд╛рдкреНрддрд┐ рддрд┐рдерд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд╛рдВрдЫрд┐рдд рдкрд╛рда рд▓реМрдЯрд╛рддрд╛ рд╣реИ:


 func subscriptionStatus() -> String { if let expDate = IAPManager.shared.expirationDateFor(productIdentifier) { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .medium let dateString = formatter.string(from: expDate) if Date() > expDate { return "Subscription expired: \(localizedTitle) at: \(dateString)" } else { return "Subscription active: \(localizedTitle) until:\(dateString)" } } else { return "Subscription not purchased: \(localizedTitle)" } } 

рдпрд╣ рд╣рдорд╛рд░реА рд╕реНрдЯрд╛рд░реНрдЯ рд╕реНрдХреНрд░реАрди рд╣реИ
рдпрд╣ рд╣рдорд╛рд░реА рд╕реНрдЯрд╛рд░реНрдЯ рд╕реНрдХреНрд░реАрди рд╣реИ


рдЕрдм рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рд╕реНрдХреНрд░реАрди рдкрд░ рдЬрд╛рдПрдВред рдЪреВрдВрдХрд┐, Apple рдХреЗ рдирд┐рдпрдореЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рднреБрдЧрддрд╛рди рд╕реНрдХреНрд░реАрди рдкрд░ рдЦрд░реАрджрд╛рд░реА рдХреА рд╢рд░реНрддреЛрдВ рдХрд╛ рдПрдХ рд▓рдВрдмрд╛ рдкрд╛рда рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд▓рд┐рдП ScrollView рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреБрджреНрдзрд┐рдорд╛рди рд╣реЛрдЧрд╛ред


 var body: some View { ScrollView (showsIndicators: false) { VStack { Text("Get Premium Membership").font(.title) Text("Choose one of the packages above").font(.subheadline) self.purchaseButtons() self.aboutText() self.helperButtons() self.termsText().frame(width: UIScreen.main.bounds.size.width) self.dismissButton() }.frame(width : UIScreen.main.bounds.size.width) }.disabled(self.isDisabled) } 

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ рдПрдХ рдЕрд▓рдЧ рдлрд╝реЙрдиреНрдЯ рдХреЗ рд╕рд╛рде рджреЛ рдкрд╛рда рджреГрд╢реНрдп рдмрдирд╛рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдиреНрдп рд╕рднреА рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдЕрдкрдиреЗ рддрд░реАрдХреЛрдВ рд╕реЗ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рддреАрди рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


  1. рдЕрдзреНрдпрдпрди рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЕрдзрд┐рдХ рдкрдардиреАрдп рдФрд░ рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред


  2. рдЗрд╕ рд▓реЗрдЦрди рдХреЗ рд╕рдордп, Xcode 11 рдмреАрдЯрд╛ рдЕрдХреНрд╕рд░ рдЬрдорд╛ рджреЗрддрд╛ рд╣реИ рдФрд░ рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдХреЛрдб рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдбрд╛рд▓рдХрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреА рдорджрдж рдХрд░рддрд╛ рд╣реИред


  3. рдпрд╣ рджрд┐рдЦрд╛рдПрдВ рдХрд┐ рджреГрд╢реНрдп рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ body рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред



purchaseButtons() рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ purchaseButtons() рд╡рд┐рдзрд┐:


 func purchaseButtons() -> some View { // remake to ScrollView if has more than 2 products because they won't fit on screen. HStack { Spacer() ForEach(ProductsStore.shared.products, id: \.self) { prod in PurchaseButton(block: { self.purchaseProduct(skproduct: prod) }, product: prod).disabled(IAPManager.shared.isActive(product: prod)) } Spacer() } } 

рдпрд╣рд╛рдВ рд╣рдо рдПрдХ рдХреНрд╖реИрддрд┐рдЬ рд╕реНрдЯреИрдХ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ ForEach рд▓реВрдк рдореЗрдВ рд╣рдо рдПрдХ рдХрд╕реНрдЯрдо ForEach рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЙрддреНрдкрд╛рдж рдФрд░ рдХреЙрд▓рдмреИрдХ рдмреНрд▓реЙрдХ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред


PurchaseButton рд╡рд░реНрдЧ:


 struct PurchaseButton : View { var block : SuccessBlock! var product : SKProduct! var body: some View { Button(action: { self.block() }) { Text(product.localizedPrice()).lineLimit(nil).multilineTextAlignment(.center).font(.subheadline) }.padding().frame(height: 50).scaledToFill().border(Color.blue, width: 1) } } 

рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдмрдЯрди рд╣реИ рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддреЗ рд╕рдордп рдкрд╛рд░рд┐рдд рдмреНрд▓реЙрдХ рдХреЛ рд╕реНрдЯреЛрд░ рдФрд░ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреЛрд▓ рд╕реНрдЯреНрд░реЛрдХ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо localizedPrice() рд╡рд┐рдзрд┐ рдореЗрдВ рдЙрддреНрдкрд╛рдж рдХреА рдХреАрдордд рдФрд░ рд╕рджрд╕реНрдпрддрд╛ рдХреА рдЕрд╡рдзрд┐ рдХреЛ рдкрд╛рда рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред


рд╕рджрд╕реНрдпрддрд╛ рдЦрд░реАрдж рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ:


 func purchaseProduct(skproduct : SKProduct){ print("did tap purchase product: \(skproduct.productIdentifier)") isDisabled = true IAPManager.shared.purchaseProduct(product: skproduct, success: { self.isDisabled = false ProductsStore.shared.handleUpdateStore() self.dismiss() }) { (error) in self.isDisabled = false ProductsStore.shared.handleUpdateStore() } } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЦрд░реАрджрд╛рд░реА handleUpdateStore рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, handleUpdateStore рд╡рд┐рдзрд┐ handleUpdateStore , рдЬрд┐рд╕рдХреЗ рд╕рд╛рде handleUpdateStore рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рднреЗрдЬреА рдЬрд╛рддреА рд╣реИред рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдХрд┐ рдореЛрдбрд▓ рд╕реНрдХреНрд░реАрди рдХреЛ рдЫреБрдкрд╛рддреЗ рд╕рдордп ContentView рд╕рджрд╕реНрдпрддрд╛ ContentView рд╕реНрдерд┐рддрд┐ рдХреЛ ContentView ред dismiss рд╡рд┐рдзрд┐ рдореЛрдбрд▓ рд╡рд┐рдВрдбреЛ рдХреЛ рдЫреБрдкрд╛рддреА рд╣реИред


рдЪреВрдВрдХрд┐ рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рдврд╛рдВрдЪрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЦрд┐рдбрд╝рдХреА рдХреЛ рдЫрд┐рдкрд╛рдирд╛ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рд╣рдореЗрдВ presentationMode @Environment рдЪрд░ рдХреЗ рд░реИрдкрд░ рдкрд░ dismiss() рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕реЗ @Environment рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ @Environment :


 struct PurchaseView : View { @State private var isDisabled : Bool = false @Environment(\.presentationMode) var presentationMode private func dismiss() { self.presentationMode.wrappedValue.dismiss() } func dismissButton() -> some View { Button(action: { self.dismiss() }) { Text("Not now").font(.footnote) }.padding() } ... 

presentationMode рдЪрд░ рдкрд░реНрдпрд╛рд╡рд░рдг рдореВрд▓реНрдпреЛрдВ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ - рд╡реИрд╢реНрд╡рд┐рдХ рддрд░реАрдХреЛрдВ рдФрд░ рдЧреБрдгреЛрдВ рдХреЗ рд╡рд┐рд╢реЗрд╖ рд╕реЗрдЯред SwiftUI рдореЗрдВ, рдЪрд░ рдХреЗ рдорд╛рдиреЛрдВ рдХреЛ рдмрджрд▓рддреЗ рд╕рдордп рд▓рдЧрднрдЧ рд╕рднреА рдХреНрд░рд┐рдпрд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ, рдЖрдк рд╢рдмреНрдж рдХреЗ рд╢рд╛рдмреНрджрд┐рдХ рдЕрд░реНрдереЛрдВ рдореЗрдВ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рд╕рдм рдХреБрдЫ рдЕрдЧреНрд░рд┐рдо рдореЗрдВ рдмрд╛рдзреНрдп рд╣реИред рдФрд░ рдХреНрд░рдо рдореЗрдВ рдХреБрдЫ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд░реИрдкрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рд╕рджрд╕реНрдпрддрд╛ рдЦрд░реАрдж рд╕реНрдХреНрд░реАрди
рд╕рджрд╕реНрдпрддрд╛ рдЦрд░реАрдж рд╕реНрдХреНрд░реАрди


рдирд┐рд╖реНрдХрд░реНрд╖


рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред рдЬрдм рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЕрдкрдиреА рдирд╡реАрдирддрдо рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддреЛ Apple рдХреЛ рдкреНрдпрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк SwiftUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ iOS 13 рдХреЗ рд▓рд┐рдП рдПрдХ рдРрдк рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рдХреБрдЦреНрдпрд╛рдд Apple рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдирдИ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рд╕реЗ рдбрд░реЛ рдордд - рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЖрдк рдпрд╣рд╛рдВ рдкреВрд░рд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред


10 рдорд┐рдирдЯ рдореЗрдВ рдЕрдкрдиреЗ iOS рдРрдк рдореЗрдВ рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? Apphud рдФрд░ рдПрдХреАрдХреГрдд рдХрд░реЗрдВ:
  • рдХреЗрд╡рд▓ рдПрдХ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦрд░реАрджрд╛рд░реА рдХрд░реЗрдВ;
  • рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИ;
  • рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рджрд╕реНрдпрддрд╛ рдкреНрд░рд╕реНрддрд╛рд╡реЛрдВ рдХреЛ рдПрдХреАрдХреГрдд рдХрд░реЗрдВ
  • рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рд╕реНрдерд╛рдиреАрдп рдореБрджреНрд░рд╛ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдПрдореНрдкреНрд▓рд┐рдЯреНрдпреВрдб, рдорд┐рдХреНрд╕рдкреИрдирд▓, рд╕реНрд▓реИрдХ рдФрд░ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо рдХреЛ рд╕рджрд╕реНрдпрддрд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо рднреЗрдЬреЗрдВ;
  • рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдордВрдерди рджрд░ рдШрдЯрд╛рдПрдВ рдФрд░ рдмрд┐рдирд╛ рд╕рджрд╕реНрдпрддрд╛ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд▓реМрдЯрд╛рдПрдВред


рдХреНрдпрд╛ рдкрдврд╝рдирд╛ рд╣реИ?


Source: https://habr.com/ru/post/hi458116/


All Articles