Restore purchase swift 4 programmatically - ios

This problem occurs to me: Purchase a subscription through a movie with a lock. I click on the camera button. The subscription view opens. I make my purchase: I display an error message (but the purchase is still successful).
func subscribe(sub: SubscriptionType) {
DispatchQueue.main.async { let _ = MBProgressHUD.standardHud(over: self.managedView) }
FS2Recipes.subscribe(sku: sub.sku()).then { _ in
self.subscribed()
}.catch { error in
debugPrint("Error \(error.localizedDescription)")
let alert = UIAlertController(title: "Ooops", message: "There was an error processing your purchase. Try again later!", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in
self?.dismiss()
}))
self.present(alert, animated: true, completion: nil)
}.always {
DispatchQueue.main.async { let _ = MBProgressHUD.hide(for: self.managedView, animated: true) }
}
}
Error

Related

File is not opening after Downloading has been completed iOS swift

When downloading completed I'm showing the alert that download has been completed after that when user click on dismiss button in alert popup self.quickLook(url: url) func will call.
But not showing the file in webView. When removing the alert code everything working fine and file opening in webView.
func showAlerts(){
let alertController = UIAlertController(title: "Download", message: "Download Completed", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "dismiss", style: .default, handler: { _ in
self.dismiss(animated: true, completion: nil)
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
#IBAction func openDoc(_ sender: UIButton) {
if let url = URL(string: "https://ikddata.ilmkidunya.com/images/books/12th-class-chemistry-chapter-10.pdf") {
self.loadFileAsync(url: url) { response, error in
if error == nil {
self.showAlerts()
self.quickLook(url: url)
}
}
}
}
Check console screenshot
Console screenshot see msg
How's your quickLook implemented? I guess it also calls present. You cannot present two things at the same time on iOS.
An option would be to quickLook after the alert is dismissed. Something like:
func showAlerts(and onDismiss: (() -> Void)? = nil) {
let alertController = UIAlertController(title: "Download", message: "Download Completed", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "dismiss", style: .default, handler: { _ in
self.dismiss(animated: true) { onDismiss?() }
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
#IBAction func openDoc(_ sender: UIButton) {
if let url = URL(string: "https://ikddata.ilmkidunya.com/images/books/12th-class-chemistry-chapter-10.pdf") {
loadFileAsync(url: url) { response, error in
if error == nil {
self.showAlerts { self.quickLook(url: url) }
}
}
}
}
Judging from your words it's exactly what you expect.

iOS IAP Restore needs few tries

I encounter a really awkward behavior of in app purchases in my app.
The app is a webview, so I created a webview and load my local HTML files.
Since my last update, the IAP Restore now needs several tries until it finally restores the specific product. I have 3 products and I noticed that my first IAP needs 1-2 tries until it restores, but the other 2 restore only after I try restore 3-4-5-6-7 times.
Nothing changed in restore code in the last update, and I did not find any clue anywhere in other found questions.
And a second question:
If I purchased all 3 products, should restoring one product restore all of them?
UPDATE:
Here is my code
func restorePurchases() {
NetworkActivityIndicatorManager.networkOperationStarted()
SwiftyStoreKit.restorePurchases(atomically: true) { results in
NetworkActivityIndicatorManager.networkOperationFinished()
for purchase in results.restoredPurchases {
let downloads = purchase.transaction.downloads
if !downloads.isEmpty {
SwiftyStoreKit.start(downloads)
} else if purchase.needsFinishTransaction {
// Deliver content from server, then:
SwiftyStoreKit.finishTransaction(purchase.transaction)
}
}
self.showAlert(self.alertForRestorePurchases(results))
}
}
func alertForRestorePurchases(_ results: RestoreResults) -> UIAlertController {
if results.restoreFailedPurchases.count > 0 {
print("Restore Failed: \(results.restoreFailedPurchases)")
return alertWithTitle("Restore succesful", message: "Everything was restored.")
} else if results.restoredPurchases.count > 0 {
print("Restore Success: \(results.restoredPurchases)")
var isSuccess = false
for i in 0 ..< results.restoredPurchases.count
{
let pId = results.restoredPurchases[0].productId
if pId == self.currentProductId
{
isSuccess = true
if(pId == appDelegate.pId1)
{
UserDefaultManager.setPurchaseStatus(flag: true)
self.purchaseTimer.invalidate()
}
else if(pId == appDelegate.pId2)
{
UserDefaultManager.setPicaPurchaseStatus(flag: true)
self.purchaseTimer.invalidate()
}
else if(pId == appDelegate.pId3)
{
UserDefaultManager.setPicaRealPurchaseStatus(flag: true)
self.purchaseTimer.invalidate()
}
makeJsScriptCall()
return alertWithTitle("Activated!", message: "Everything was restored!")
}
}
if(!isSuccess)
{
return alertWithTitle("Something went wrong", message: "This is the error that I get until I try restore 3-4 times")
}
func showPurchaseActionSheet() {
let alert = UIAlertController(title: "Choose Option", message: nil, preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Purchase", style: .default , handler:{ (UIAlertAction)in
self.purchase(.nonConsumablePurchase, atomically: true)
}))
alert.addAction(UIAlertAction(title: "Restore", style: .default , handler:{ (UIAlertAction)in
self.restorePurchases()
}))
alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler:{ (UIAlertAction)in
}))
alert.popoverPresentationController?.sourceView = self.view
self.present(alert, animated: true, completion: {
print("completion block")
})
}

RPScreenRecorder not recording mic in odd situations

Why won't RPScreenRecorder record the mic, even though it is enabled, if the permissions popup doesn't appear? It works when the popup appears but attempts after restarting the app don't record the mic.
here's the very simple app i made just to test this feature for a larger app.
I have tested this exact application on iOS 11 and it works every time. However on iOS 12+ it only works when the permission popup appears and that's every 8 minutes. It should work every time after giving permissions.
import ReplayKit
class ViewController: UIViewController, RPPreviewViewControllerDelegate {
private let recorder = RPScreenRecorder.shared()
private var isRecording = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func react() {
if !isRecording {
let alert = UIAlertController(title: "Record", message: "Would you like to record a video?", preferredStyle: .alert)
let okay = UIAlertAction(title: "Okay", style: .destructive, handler: { (action: UIAlertAction) in
self.startRecording()
})
alert.addAction(okay)
self.present(alert, animated: true, completion: nil)
} else {
stopRecording()
}
}
private func startRecording() {
guard self.recorder.isAvailable else {
print("Recording is not available at this time.")
return
}
self.recorder.isMicrophoneEnabled = true
self.recorder.startRecording{ [unowned self] (error) in
guard error == nil else {
print("There was an error starting the recording.")
return
}
print("Started Recording Successfully")
self.isRecording = true
}
}
private func stopRecording() {
recorder.stopRecording { [unowned self] (preview, error) in
print("Stopped recording")
guard preview != nil else {
print("Preview controller is not available.")
return
}
let alert = UIAlertController(title: "Recording Finished", message: "Would you like to edit or delete your recording?", preferredStyle: .alert)
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { (action: UIAlertAction) in
self.recorder.discardRecording(handler: { () -> Void in
print("Recording suffessfully deleted.")
})
})
let editAction = UIAlertAction(title: "Edit", style: .default, handler: { (action: UIAlertAction) -> Void in
preview?.previewControllerDelegate = self
self.present(preview!, animated: true, completion: nil)
})
alert.addAction(editAction)
alert.addAction(deleteAction)
self.present(alert, animated: true, completion: nil)
self.isRecording = false
}
}
func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
dismiss(animated: true)
}
}
I expect that the mic should record every single time after allowing the permissions however it appears to only be recording the mic during the sessions in which it asks for those permissions.
This appears to have been fixed in iOS 13. The OS now asks for permission every time you request to record the screen. I still don't have a fix for iOS 12 however.

How to implement a YesNo box as a ViewController method?

I would like to add a method to my ViewController that shows a message with text as an alert with a Yes and a No button. The result should be of type Bool (Yes/No).
What I have tried is the following:
func YesNoBox(msg: String) -> Bool
{
var retVal = false
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in NSLog("The \"Yes\" alert occured."); retVal = true })
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in NSLog("The \"No\" alert occured."); retVal = false })
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
return retVal
}
However, the value of retVal is always false. If I was in C/C++, I guess I could resolve this issue with a pointer, but this is Swift (and I am pretty new to this).
Any idea anyone how I could get this working?
EDIT: The problem that I have is the following. On a ViewController I have a TextField. When I tap on the text field, the app should ask the user whether they want to paste the text from the clipboard. If yes, paste, otherwise give the TextField the focus (i.e. let the cursor blink in it). I tried to do this with 'textFieldShouldBeginEditing' and in this method I display the YesNoBox. The problem is that the TextField never gets the focus after the YesNoBox is closed. And when I use 'becomeFirstResponder()' after the Box call, the app freezes. I don't know what to do?
Use a completion
func yesNoBox(msg: String,completion:#escaping(Bool) -> ())
{
let alert = UIAlertController(title: "", message: msg, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler:
{ _ in
NSLog("The \"Yes\" alert occured.");
completion(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler:
{ _ in
NSLog("The \"No\" alert occured.");
completion(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
call
yesNoBox(msg:"someMessage") { yes in
if yes {
// do yes action
}
else {
// do no action
}
}
2 Callbacks:
This function has 2 completions ( imagine we have a function that uploads an image and notifies the progress with a completion and another 1 to say done )
func uploadImage(data: Data,progress:#escaping(Float) -> (),completion:#escaping(Bool) -> ()) {
// implementation here
}
To call
self.uploadImage(someData) { progress in
print(progress)
}) { done in
print(done)
}
This can be achieved with completion handlers.
func showAlertWithOptions(title: String, message: String, completionHandler: #escaping (Bool) -> Void) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action_yes = UIAlertAction(title: "Yes", style: .default, handler: { _ in
completionHandler(true)
})
let action_no = UIAlertAction(title: "No", style: .cancel, handler: { _ in
completionHandler(false)
})
alert.addAction(action_yes)
alert.addAction(action_no)
self.present(alert, animated: true, completion: nil)
}
Now call the function and add any other functions or actions that you want to perform depending on the action selected.
showAlertWithOptions(title: "Any title", message: "Any message") { success in
if success {
NSLog("The \"Yes\" alert occured.")
} else {
NSLog("The \"No\" alert occured.")
}
}

How to access the view controller which is evoked by the stopRecording() method of ReplayKit framework. And how to save the video in my camera roll

How to access the view controller which is evoked by the stopRecording() method of ReplayKit framework. And how to save the video in the camera roll?
Try this if you haven't gotten to work yet:
func stopRecording() {
let sharedRecorder = RPScreenRecorder.sharedRecorder()
sharedRecorder.stopRecordingWithHandler { (previewViewController: RPPreviewViewController?, error: NSError?) in
if previewViewController != nil {
print("stopped recording")
previewViewController!.previewControllerDelegate = self
let alertController = UIAlertController(title: "Recording", message: "Tap view to watch, edit, share, or save your screen recording!", preferredStyle: .Alert)
let viewAction = UIAlertAction(title: "View", style: .Default, handler: { (action: UIAlertAction) -> Void in
self.view?.window?.rootViewController?.presentViewController(previewViewController!, animated: true, completion: nil)
})
alertController.addAction(viewAction)
self.previewViewController = previewViewController!
self.previewViewController.modalPresentationStyle = UIModalPresentationStyle.FullScreen
self.view?.window?.rootViewController!.presentViewController(alertController, animated: true, completion: nil)
} else {
print("recording stopped working")
//create the alert
let alert = UIAlertController(title: "Alert", message: "Sorry, there was an error recording your screen. Please Try Again!", preferredStyle: UIAlertControllerStyle.Alert)
// show the alert
self.view!.window?.rootViewController!.presentViewController(alert, animated: true, completion: nil)
alert.addAction(UIAlertAction(title: "Try Again!", style: UIAlertActionStyle.Destructive, handler: { action in
// add action
}))
}
}
}
internal func previewControllerDidFinish(previewController: RPPreviewViewController) {
self.previewViewController.dismissViewControllerAnimated(true, completion: nil)
print("cancel and save button pressed")
}

Resources