In App Purchase on Mac Catalyst Not Working - swift

In app purchases work fine for my iOS side of things. The data from StoreKit is populated as it should. The same code doesn't work on the Mac Catalyst version of the project. I have even created a listing for my Mac app on App Store connect with different bundle identifiers for the in app purchases. I have a print function that returns what product StoreKit found, it works well on iOS, but results with nothing when using Mac Catalyst.
Here is what I have done:
Make sure that In App purchases has been added in the capabilities section.
Make sure the Store Kit framework has been imported.
Make sure the bundle identifiers are correct.
Make sure all agreements are filled out.
I am signed out of the Mac App Store.
Code that works on iOS but not on MacOS:
override func viewDidLoad() {
SKPaymentQueue.default().add(self)
let productIds: Set<String> = ["..."]
var request = SKProductsRequest(productIdentifiers: productIds)
request.delegate = self
request.start()
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print("Loaded")
for product in response.products {
print("What came: \(product.productIdentifier) \(product.localizedTitle) \(product.price.floatValue)")}
The iOS app will return with the Product Identifier, Title and Price. The Mac app will return with nothing at all.

I found the problem. I had not created a strong reference to my product request.
This line of code fixed my issue:
var request: SKProductsRequest!

Related

Unable to fetch IAP from App Store causing app to fail

I am trying to implement in App Purchases in a simple app I am creating.
I have a model method that is supposed to get the products using the productID. However the products array shown below returns an empty array. This causes the app to crash when trying to purchase an in app purchase.
I have followed a modified version of a tutorial I found online. But have not been able to figure out why mine doesn't work.
The Github repository for the project can be found here.
class Model {
var products = [SKProduct]()
func getProduct(containing keyword: String) -> SKProduct? {
print("The array of SKProducts in Model getProduct is \(products)")
let test = products.filter { $0.productIdentifier.contains(keyword) }.first
print(test)
return test
}
}

Is the SKStoreReviewController API also available for MacOS, and if yes, how to implement it?

I am using the SKStoreReviewController API in my iOS app to get reviews of my app. I also wanted to implement this into my MacOS app, but it seems that this is not possible. I imported StoreKit, but it says "Use of unresolved identifier 'SKStoreReviewController'". Do I need to implement this differently, or is this not meant to be used for the Mac Appstore?
As Marek pointed out, the SKStoreReviewController class is available since macOS 10.14+.
Use the requestReview() method to indicate when it makes sense within the logic of your app to ask the user for ratings and reviews within your app.
Apple still recommends in the Human Interface Guidelines to don't use buttons or other controls to request feedback and trigger, but trigger it only in other situations.
Apple has a nice example code to handle the review showing only for specific actions:
// If the count has not yet been stored, this will return 0
var count = UserDefaults.standard.integer(forKey: UserDefaultsKeys.processCompletedCountKey)
count += 1
UserDefaults.standard.set(count, forKey: UserDefaultsKeys.processCompletedCountKey)
print("Process completed \(count) time(s)")
// Get the current bundle version for the app
let infoDictionaryKey = kCFBundleVersionKey as String
guard let currentVersion = Bundle.main.object(forInfoDictionaryKey: infoDictionaryKey) as? String
else { fatalError("Expected to find a bundle version in the info dictionary") }
let lastVersionPromptedForReview = UserDefaults.standard.string(forKey: UserDefaultsKeys.lastVersionPromptedForReviewKey)
// Has the process been completed several times and the user has not already been prompted for this version?
if count >= 4 && currentVersion != lastVersionPromptedForReview {
let twoSecondsFromNow = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: twoSecondsFromNow, execute: {
SKStoreReviewController.requestReview()
UserDefaults.standard.set(currentVersion, forKey: UserDefaultsKeys.lastVersionPromptedForReviewKey)
})
}
Even though when I only call SKStoreReviewController.requestReview() there's no review prompt appearing. Does anyone know a a specific trick for macOS?
Edit: I've submitted an update to the app store and the review prompt is working! I don't know why it's not appearing when testing, but in production it seems to work!
SKStoreReviewController is for iOS only as seen in the "SDK" section of the
Documentation.
To let users write reviews, you will have to use the link to the Mac App Store.
let appid = 9999999999 // put your app id here
if let url = URL(string: "https://itunes.apple.com/us/app/id\?(appid)ls=1&mt=8&action=write-review") {
NSWorkspace.shared().open(url)
}
SKStoreReviewController is available even on macOS 10.14+, but sometimes i wasn't able to make it work with SKStoreReviewController.requestReview() so I use the manual mode that you can find here:
let appId = 1547575778 //Your app Id from the Itunes Connect portal
if let url = URL(string: "https://apps.apple.com/app/id\(appId)?action=write-review") {
NSWorkspace.shared.open(url)
}
SKStoreReviewController is available since macOS 10.14
You can use my tiny wrapper:
// Review after 3 launches
AppReview.requestIf(launches: 3)
// Review after 5 days
AppReview.requestIf(days: 5)
// Review after 3 launches and 5 days
AppReview.requestIf(launches: 3, days: 5)
https://github.com/mezhevikin/AppReview

ios app rejected on using AWS cognito implementation from mobile hub

We recently got our ios app rejected because of the following:
We noticed that the user is taken to Safari to sign in or register for an account, which provides a poor user experience.
however, the bit that launches the safari window for facebook/Google login is part of the AWSMobileHubHelper framework so we can't modify that code.
Any ideas/solutions would be greatly appreciated.
So I found a workaround. I just grab the GIDSignIn instance and change the properties myself. In case any one else wants to know how, all you have to do is:
Add a bridge header and import #import <GoogleSignIn/GoogleSignIn.h>
Implement the presentViewController method for GIDSignInUIDelegate on your main login controller
func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!) {
presentViewController(viewController, animated: true, completion: nil)
}
Edit demo login code to be something like this:
func loginWithGoogle(delegate: GIDSignInUIDelegate!) {
let googleProvider = AWSGoogleSignInProvider.sharedInstance()
// It is important that these are initialized after
// AWSGoogleSignInProvider.sharedInstance() is called
GIDSignIn.sharedInstance().uiDelegate = delegate
GIDSignIn.sharedInstance().allowsSignInWithBrowser = false
GIDSignIn.sharedInstance().allowsSignInWithWebView = true
handleLoginWithSignInProvider(googleProvider, callback: callback)
}
As of iOS 9 using Facebook SDK, this is expected behavior per Facebook login. Mobile Hub quickstart app is just applying the Facebook SDK 3 and using the APIs as directed. Check out the brief description below and read through the comments to get a better insight. This was not a popular decision by Facebook and others have provided workarounds (to forcing user authentication via mobile browser) if you wish to experiment. As for the AWSMobileHubHelper framework, we are looking into making this available at some point but don't have a timeline for this.
"Logic that automatically defaults people to the optimum experience for iOS 9. This means that the SDK dialogs for Facebook Login, Sharing across Facebook and Messenger, App Invites, App Events, or Native Like will automatically determine the best experience for people based on their device."
Source:
https://developers.facebook.com/blog/post/2015/09/10/new-SDK-for-iOS9/

Sharing on WhatsApp in iOS 9.0

I m new in iOS development and i want to integrate WhatsApp sharing in my app in ios 9.0 . i have searched various methods but they all are depreciated in ios 9.0
Can anyone suggest me updated method for the same,
#IBAction func whattsappInvite(sender: UIButton)
{
let urlString = "Hello Friends, Sharing some data here... !"
let urlStringEncoded = urlString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
let url = NSURL(string: "whatsapp://send?text=\(urlStringEncoded!)")
if UIApplication.sharedApplication().canOpenURL(url!) {
UIApplication.sharedApplication().openURL(url!)
}
}
Apple changed the canOpenURL method on iOS 9. Apps which are checking for URL Schemes have to declare these Schemes as it is submitted to Apple. Else canOpenURL returns false.
Add whatsapp field in LSApplicationQueriesSchemes in info.plist of your app.
Or try using whatsapp share extension
To share with Whatsapp, you can use your code or this one as a base :
var whatsappURL:NSURL?= NSURL(string: "whatsapp://send?text=Hello%2C%20World!")
if (UIApplication.sharedApplication().canOpenURL(whatsappURL)) {
UIApplication.sharedApplication().openURL(whatsappURL)
}
None of these methods are deprecated in iOS 9.0.

Loading URL With Basic HTTP Authentication In Swift

I'm trying to send NSURLConnection.SendAsynchronousRequest to a URL that requests an authentication.
I'm implementing the method:
func connection(connection:NSURLConnection!, willSendRequestForAuthenticationChallenge challenge:NSURLAuthenticationChallenge!) {
if challenge.previousFailureCount > 1 {
} else {
println("Asking for auth")
let creds = NSURLCredential(user: usernameTextField.text, password: passwordTextField.text, persistence: NSURLCredentialPersistence.None)
challenge.sender.useCredential(creds, forAuthenticationChallenge: challenge)
The method is not being called, also the line is not being printed.
Am i doing everything right?
I'm new to coding with swift, it seems right to me but it just doesn't work...
(new edit) Hmm. rebooted and now it is calling willSendRequestForAuthenticationChallenge is being called. I didn't change any of the code, so Xcode must have gotten in an odd state. If I figure out more, I'll update.
(original post)
Seems to be a problem in Xcode 6 Beta 4. I put my code back in Beta 3 and my willSendRequestForAuthenticationChallenge is being called. I'll run for this as a temp workaround for now.
I did file a radar with Apple on this one.