Showing posts with label objective-c. Show all posts
Showing posts with label objective-c. Show all posts

Wednesday, September 30, 2020

How To Invoke Swift code from Objective C code

I wasted a couple of hours trying to do exactly this. The lack of clear documentation didn't help either. I decided to write small post about this so that others do not have to waste their time digging through the documentation.

How do you invoke Swift code from Objective C code?


Swift class either need to be derived from NSObject or they need to be @objc attribute. Let's look at a simple swift class that we want to invoke from Objective C. 


When you add the Swift class to the Objective C project, XCode will ask whether you want to generate the "Bridging Header", just say yes. This header is useful when you want to invoke Objective C code from Swift code. But we are interested in doing the opposite, i.e. invoke Swift code from Objective C code.

Next we need to head to XCode -> Project Properties -> Target -> Build Settings, search for "Generated Interface". You should see a single entry called "Objective-C Generated Interface Header Name". You need to make a note of the generated header file name, it follows the format "<Product Module Name>-Swift.h"




This is the name of the header file that we need to include in our Objective C code to invoke the Swift code. This header file is auto-generated by XCode.

In the Build Settings search for "Bridging Header". You should see an entry called "Objective-C Bridging Header". This setting points to the path of the Bridging Header generated by XCode earlier. The value here should have been populated by XCode automatically. 


We also need to set the value of "Swift Language Version" Build Setting. Search for "Language Version" and set the value.



Now that the Build Settings are out of the way, here is the sample Objective C code which invokes the Swift class we defined above.


Please note that you can only include the "<Product Module Name>-Swift.h" in the .m or .mm files. To use the Swift class in .h file, just forward declare it using @MySwiftClass.

Thats about all there is to invoke Swift code from Objective C, we do not need to change any other Build Settings. If the documentation was clear enough, I would not have to write this post!

Saturday, November 30, 2019

How to do iOS Receipt Validation in Objective-C

Until you do it yourself, receipt validation might feel like one of the most unclear topic, when it comes to verifying In App Purchases (IAP) on iOS platform for an App Developer.

This post documents the exact steps and code needed to perform receipt validation with AppStore.

The Receipt

As soon as the app is installed or updated, Apple puts a purchase receipt (signed by Apple via AppStore) in the main bundle of the app.

Think of the receipt as the trusted record of a purchase. It also includes any in-app purchases that the user might have made.

Receipt Validation

By verifying the receipts, App Developers can protect their revenue and enforce their business model directly in their application. Receipt Validation plays a key role in verifying whether the auto-renewing subscription is currently active or not.

Here are the steps needed to validate the receipt.
  • First step in the process is to load the receipt from apps main bundle
  • If the receipt is not found, we could refresh the receipt using SKReceiptRefreshRequest
    • This is especially helpful during development and debugging.
  • Refreshing the receipt tells the system that the application needs to retrieve a new receipt

  • Before we could send the receipt information to AppStore, we will need the App's Shared Secret.
  • To get this, log on to itunesconnect and navigate to My Apps -> Click on your App -> Click on Features 
  • Click on the In-App Purchases section. On the right side you will see the link App-Specific Shared Secret, click this link to generate the App-Specific Shared Secret. It will pop up a dialog where you could generate a new secret or view the existing secret.
  • Note down the generate secret somewhere, we need to pass this value to AppStore for receipt verification.

  • Next, we need send the receipt details along with App-Specific Shared Secret to AppStore. We have to hit different URL based on whether the app is running in the sandbox environment or production environment.
  • Now we need to send the Base 64 encoded receipt information along with App-Specific shared secret to the AppStore API. The response of this API is a JSON object with details about various purchases user has made on the app.
  • Full list of receipt fields found in this JSON response can be found here
  • "latest_receipt_info" field is part of the JSON response. It is an Array containing the details of IAP and Subscription purchases made by the user on the app. 
  • Each purchase holds information like
    • Which product was purchased: "product_id"
    • When was the purchase made: "original_purchase_date"
    • Whether or not the auto-renewing subscription is running the trial period: "is_trial_period"
    • The date of the auto-renewing subscription expires: "expires_date"
    • What was the intent behind the subscription expiration: "expiration_intent"
  • Now all that is left is to parse the JSON response and iterate through the contents of "latest_receipt_info" field. Here's the code that does it.

Thats about all that is needed to perform receipt validation.

However, please note that, since we can't build a trusted connection between a user’s device and the App Store directly, we should should always call AppStore receipt validation API from a trusted server. Details of how to do that, is out of scope of this post.

Saturday, October 31, 2015

How to fix Cocos2.1 shader crash on iOS 9 - Part 2

In my previous post, I explained how to fix the open GL Shader related crash on iOS 9.  This crash was specifically occurring for apps using Cocos 2.1, the crash fix did work correctly on iOS8 and above.  But the fix had introduced another crash on iOS7 devices.  The crash report looked like this:

I investigated the issue for sometime and then I had my "duh!" moment.  The code that fixes the crash on iOS 9 used the method "containsString" of NSString class to find whether string A contains string B (on line no 18).

The method "containsString" was only introduced in iOS 8 hence, it was not available on devices running iOS 7 and below.  When the code tries to use that method it obviously crashes the app!

We changed the code to not use "containsString" and used "rangeOfString" instead.  This method was supported on iOS 7 as well.  The updated code looks like this:

Heres the fully updated code that works on all devices running iOS 7 and above.
Such a silly mistake this was!

Wednesday, September 30, 2015

How to fix Cocos2.1 shader crash on iOS 9

We have been using Cocos2D 2.1 for our game Monster Math.  Recently we decided to release an update to the game by compiling it against iOS 9.  To our surprise the game started crashing right at the launch with the following error.

A little investigation showed that it was crashing while creating OpenGL shaders.  A little googling proved that others were facing the same issue (more details here and here).

Whats the Fix - How Do They Do It! 

To fix the crash, I had to modify code in file CCGLProgram.m of Cocos2D and change the method compileShader as follows.

Once I made the change, the crash disappeared and it stared launching the game without any problems.

After this change we released an update of our game to AppStore.  We did however see a few crash reports around this very same issue from devices that were running iOS 7.

Will have to investigate further and fix it for iOS 7 devices as well.  Will keep you guys posted on what we did to fix it for iOS 7 devices, till then, have fun!
Have some Fun!