This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.m | |
// AVPlayerCaching | |
// | |
// Created by Anurag Mishra on 5/19/14. | |
// Sample code to demonstrate how to cache a remote audio file while streaming it with AVPlayer | |
// | |
#import "ViewController.h" | |
#import <AVFoundation/AVFoundation.h> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"vk_playback": 1, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) | |
@_functionBuilder public struct ViewBuilder { | |
/// Builds an empty view from an block containing no statements, `{ }`. | |
public static func buildBlock() -> EmptyView | |
/// Passes a single view written as a child view (e..g, `{ Text("Hello") }`) through | |
/// unmodified. | |
public static func buildBlock<Content>(_ content: Content) -> Content where Content : View | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var body: some View { | |
VStack{ | |
Text("World Time").font(.system(size: 30)) | |
Text("Yet another subtitle").font(.system(size: 20)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension IAPManager: SKPaymentTransactionObserver { | |
public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { | |
for transaction in transactions { | |
switch (transaction.transactionState) { | |
case .purchased: | |
SKPaymentQueue.default().finishTransaction(transaction) | |
notifyIsPurchased(transaction: transaction) | |
break | |
case .failed: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func refreshSubscriptionsStatus(callback : @escaping SuccessBlock, failure : @escaping FailureBlock){ | |
// save blocks for further use | |
self.refreshSubscriptionSuccessBlock = callback | |
self.refreshSubscriptionFailureBlock = failure | |
guard let receiptUrl = Bundle.main.appStoreReceiptURL else { | |
refreshReceipt() | |
// do not call block yet | |
return | |
} | |
#if DEBUG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private func refreshReceipt(){ | |
let request = SKReceiptRefreshRequest(receiptProperties: nil) | |
request.delegate = self | |
request.start() | |
} | |
func requestDidFinish(_ request: SKRequest) { | |
// call refresh subscriptions method again with same blocks | |
if request is SKReceiptRefreshRequest { | |
refreshSubscriptionsStatus(callback: self.successBlock ?? {}, failure: self.failureBlock ?? {_ in}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private func parseReceipt(_ json : Dictionary<String, Any>) { | |
// It's the most simple way to get latest expiration date. Consider this code as for learning purposes. Do not use current code in production apps. | |
guard let receipts_array = json["latest_receipt_info"] as? [Dictionary<String, Any>] else { | |
self.refreshSubscriptionFailureBlock?(nil) | |
self.cleanUpRefeshReceiptBlocks() | |
return | |
} | |
for receipt in receipts_array { | |
let productID = receipt["product_id"] as! String | |
let formatter = DateFormatter() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Starts products loading and sets transaction observer delegate | |
@objc func startWith(arrayOfIds : Set<String>!, sharedSecret : String){ | |
SKPaymentQueue.default().add(self) | |
self.sharedSecret = sharedSecret | |
self.productIds = arrayOfIds | |
loadProducts() | |
} | |
private func loadProducts(){ | |
let request = SKProductsRequest.init(productIdentifiers: productIds) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func purchaseProduct(product : SKProduct, success: @escaping SuccessBlock, failure: @escaping FailureBlock){ | |
guard SKPaymentQueue.canMakePayments() else { | |
return | |
} | |
guard SKPaymentQueue.default().transactions.last?.transactionState != .purchasing else { | |
return | |
} | |
self.successBlock = success | |
self.failureBlock = failure |
OlderNewer