Adding some more details based on my current experience: My task is to convert an OBJC codebase from premium to freemium on IOS16, and I want to use the new features of StoreKit2 (originalPurchaseDate and originalAppVersion) in my objective-C code. I'm using the Storekit2 example code (https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api), especially the file "store.swift", and my problem was to be able to call the functions in that file from my OBJC modules. So here is what helped me:
- Create an object in store.swift, and flag it with @objc (see below). As the object is in the swift file, it can call all the swift code. The @objc makes the object visible to the OBJC code as well.
- Each property and each function that should be visible to OBJC must be proceeded with "@objc"
import Foundation
import StoreKit
@objc(MySwiftObject)
class MySwiftObject : NSObject {
@objc
var someProperty: AnyObject = "Some Initializer Val" as NSString
override init() {
}
@objc
func someFunction(someArg: Any) -> NSString {
return "You sent me \(someArg)" as NSString
}
@objc
func myAppTransaction() async {
do {
// Get the appTransaction.
if #available(iOS 16.0, *) {
let shared = try await AppTransaction.shared
if case .verified(let appTransaction) = shared {
// Get the major version number of the version the customer originally purchased.
let versionComponents = appTransaction.originalAppVersion.split(separator: ".")
let originalMajorVersion = versionComponents[0]
if originalMajorVersion < "2" {
// This customer purchased the app before the business model changed.
// Deliver content that they're entitled to based on their app purchase.
}
else {
// This customer purchased the app after the business model changed.
}
}
} else {
// Fallback on earlier versions
}
}
catch {
// Handle errors.
}
}
}
- To make anything visible in OBJC code, we need an include file, which is auto-generated by the compiler - this was the point that I didn't understand for a long time. The name of the include file is "-Swift.h", for e.g. my app name is "dogwalk", so the include file is named "dogwalk-Swift.h", this is what you can use in the #include statement, no help from autocomplete, you have to type the full statement. See below for the OBJC example code:
#import "dogwalk-Swift.h"
MySwiftObject * myOb = [[MySwiftObject alloc] init];
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
NSString * retString = [myOb someFunctionWithSomeArg:@"my string example"];
NSLog(@"RetString: %@", retString);
[myOb myAppTransactionWithCompletionHandler:^{
NSLog(@"appTransaction completed");
}];