Post

Replies

Boosts

Views

Activity

Reply to Are in-app purchase receipts included in the App Store receipt on initial install on a new device?
To your question, yes, the app receipt after a new install on a 2nd device after you had already subscribed would contain the past purchase. Note that if the 2nd device already has the app installed before the 1 set device made the purchase, then it would not. Thanks a lot for sharing this information. I had no idea using using server receipt validation also implicitly refreshed the receipt. For the case of Auto renewable subscriptions especially this is a bit of a bummer. I was expecting/hoping StoreKit would push an auto-renewable subscription purchase to all devices logged in with the same Apple ID via SKPaymentQueue, but it does not until at least the first iAP receipt for the subscription is active on the device. Couldn't a manual call to -restoreCompletedTransactions on SKPaymentQueue achieve the same thing at launch (if determined that no iAP receipt is present). This is a single method call and the code would be way simpler. I'm aware that using server side receipt validation has other benefits but I'm specifically referring to proactively restoring in app purchases. Local receipt validation wasn’t discussed specifically because it won’t have the latest purchase status reliably, therefore you can’t create this experience accurately. Therefore to create such an experience you will either need to adopt StoreKit2 or use verifyReceipt with app receipts. I can still think of a way that this won't provide exactly the user experience I was hoping for. On app launch use server-side receipt validation. Install the app both on two devices, an iPhone and an iPad. Launch the app on both devices. Subscribe to an auto renewable subscription on an iPhone. Since the app is already running on the iPad, server side receipt validation already finished before the purchase made on the iPhone completed, so the user still needs to use the "Restore in app purchases button" manually If the server pushed auto renewable subscription purchases to all devices logged in with the same Apple ID developers wouldn't have to worry about such timing issues. I suppose it would be possible for developers to manually implement this with either with their own server or CloudKit, but it would be really nice if StoreKit just did it.
Topic: App & System Services SubTopic: StoreKit Tags:
Jul ’22
Reply to Are WatchOS storyboards forbidden now ?
But having to develop in the same app, iOS part with UIKit storyboard and WatchOS part with SwiftUI, with completely different design logic, remain problematic. +1. And plus Objective-C can't be used to make Watch apps anymore? That's just awful. They are jumping the shark.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’22
Reply to I can't log out of iCloud in Simulator
This bug has been around for a long time. I also would like to test how my app behaves when the user signs out of iCloud while my app is running in memory. I'd rather not test this on my real device because logging out of my iCloud account has side effects with tons of apps using iCloud and I don't want to accidentally lose data. Would be great if we got better simulator support. I can sign in, but can't sign out.
Jun ’22
Reply to Are in-app purchase receipts included in the App Store receipt on initial install on a new device?
@endecotp I'm not sure why they recommend a server side approach to proactively restore in app purchases since that can be affected by network conditions if the receipt includes previous app purchases on initial install. Would be nice to know officially if this is the case or not. There may be some odd corner-cases where you don’t, so do have a “restore purchases” button. Indeed I do have a restore in app purchase button. Back when iTunes backups included apps I assume the receipt would need to be refreshed when installed on a new device. I assume this is still true if the the user installs the app using third party backup software instead of downloading from the App Store.
Topic: App & System Services SubTopic: StoreKit Tags:
Jun ’22
Reply to NSDocument, callback when renaming document from title bar
Try overriding -moveToURL:completionHandler: on NSDocument - (void)moveToURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler { [super moveToURL:url completionHandler:^(NSError * _Nullable theError) { if (theError == nil)         { //no error, file was moved.... } else { //error..... } //Call the original completion handler         if (completionHandler != nil) { completionHandler(theError); } }]; }
Topic: UI Frameworks SubTopic: AppKit Tags:
Jun ’22
Reply to Run CloudKit App Using the Production Environment From Xcode?
Right. But my question was about running from Xcode with the debugger attached. Apparently you can't run the app from Xcode (anymore?) using the entitlement I linked in my previous answer (I saw an old answer on Stackoverflow that seemed to indicate that using this entitlement was possible at some point). When I try I get a code signing error: "Provisioning profile "iOS Team ProvisioningProfile: My.ProfileName" doesn't match the entitlements file value for "com.apple.developer.icoud-container-environment entitlement. I tried creating a provisioning profile manually but with no luck.
Topic: Code Signing SubTopic: Entitlements Tags:
Jun ’22
Reply to UINavigationController's interactivePopGestureRecognizer sometimes causes the popped view controller to never be released (memory leak)
Just to add (for anyone else out there interested), reproducing the issue is a bit tricky. You have to invoke the interactive pop gesture a certain way to get the table view delegate method to be called, and then just pop it off in one motion. For me I set a log in -(nullable UISwipeActionsConfiguration*)tableView:(UITableView*)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath*)indexPath { NSLog(@"-leadingSwipeActionsConfigurationForRowAtIndexPath called"); UISwipeActionsConfiguration *theConfig; //make the object and return it.. return theConfig; } I also set a log in dealloc to verify whether or not the view controller is released. So I have to play with it a few times, push and pop the view controller. But when I see the log in -leadingSwipeActionsConfigurationForRowAtIndexPath: and I still have my finger down (and the interactive pop gesture is still recognizing my touch) and I pop off the view controller, my log in dealloc does not show up and the view controller leaks. I carefully went through each UIContextualAction I pass to the UISwipeActionsConfiguration and do a __weak and __strong dance like this: __weak MyViewController *weakSelf = self;    UIContextualAction *myAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal                                                                                          title:actionTitle                                                                                        handler:^(UIContextualAction *action,                                                                                                  UIView *sourceView,                                                                                                  void (^completionHandler)(BOOL))  { __strong MyViewController *strongSelf = weakSelf; //do whatever to respond to the action using strongSelf. }]; I believe this has now allowed my view controller to be released when I reproduce the issue, since the UIContextualActions don't retain the view controller in their action handlers. I think the UISwipeActionsConfiguration is still leaking though....with no obvious way for me to clear it when the view controller gets popped off the navigation stack (UISwipeActionController is private API). But at least the leak is not as bad. Instruments leak tool never picked up this leak I only found it by unexpectedly hitting breakpoints on a view controller that wasn't supposed to be in memory.
Topic: UI Frameworks SubTopic: UIKit Tags:
Jun ’22
Reply to UINavigationController's interactivePopGestureRecognizer sometimes causes the popped view controller to never be released (memory leak)
Thanks a lot for your response. That was very helpful (not sure why I didn't think of using the memory graph debugger duh)! The leak is caused by UISwipeActionsConfiguration. The view controller that is being leaked has a UITableView and implements the delegate method: -(nullable UISwipeActionsConfiguration*)tableView:(UITableView*)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath*)indexPath So the leak occurs when I start the navigation controller's interactive pop gesture and the table view simultaneously recognizes the gesture and calls the -tableView:leadingSwipeActionsConfigurationForRowAtIndexPath: method and I return a UISwipeActionsConfiguration just before the view controller is popped off the stack via the interactive pop gesture recognizer... The private UISwipeActionController is still holding on to the UISwipeActionsConfiguration, which is holding on to my view controller even after it has been dismissed from the UI, thus causing the leak. Ouch!
Topic: UI Frameworks SubTopic: UIKit Tags:
Jun ’22
Reply to StoreKit Configuration File: Auto-Renewable Subscriptions Suddenly Stop Working in StoreKit Testing Environment After Awhile
Also to add when this issue happens (suddenly unsubscribed without taking any user interaction) if I go to the "Manage StoreKit Transactions" window in Xcode while my app is running a debug session and view transactions, indeed the latest transaction in the list is "Expired." If I click the "Subscription Options" button it says "Select an Option to Resubscribe." I've taken no user interaction to unsubscribe to the subscription plan I'm currently testing. StoreKit Testing seems to just randomly unsubscribe me from the subscription plan. Anyone else run into this?
Topic: App & System Services SubTopic: StoreKit Tags:
May ’22
Reply to Subscription Renewal Rate in StoreKit Testing for Xcode Not Working For Subscriptions Unless They Are Monthly Subscriptions?
Thanks a lot for the reply. This was helpful. After changing "Monthly renewal rate to every 30 seconds" and making the purchase in the simulator, my weekly renewal subscription code is working. I think it would be nice to be able to set a renewal rate relative to weekly/yearly subscriptions in a more intuitive fashion, but at least this works. The autorenewable subscription code is triggered, but for my weekly subscription, the expiration date is actually not advanced a week into the future. For example here are two expiration date values in the separate in app purchase receipts after a renewal: 2022-05-02 21:23:10 +0000 2022-05-02 21:20:47 +0000 So in my UI I have an area: "Subscription expires on 5/02/22" After each renewal, this UI refreshes. But because the way Storekit testing works the label never actually changes. It would be cool if the expiration date in the receipt refreshed from 5/02/22 to 5/09/22 and so on, which would make a more realistic test environment.
Topic: App & System Services SubTopic: StoreKit Tags:
May ’22
Reply to StoreKit Testing Not Working for Existing macOS App. Receipt Validation Fails and gives me App Sandbox Receipt
This apparently hasn't changed. Xcode 13.2.1 receipt validation fails when I try to verify against the generated public certificate from the StoreKit configuration file. Receipt validation passes when I validate against the Apple root certificate...but then I'm in the sandbox environment and lose the benefits of StoreKit configuration testing.
Topic: App & System Services SubTopic: StoreKit Tags:
Apr ’22
Reply to NSMutableArray does not raise NSRangeException when trying to set an element at the end of the array
The code shown for your array named a should work. You have: NSMutableArray<NSNumber*> *a = @[@(0), @(0), @(0)].mutableCopy; a[3] = @(1); // works, but why? a[4] = @(1); // also works So you have three NSNumbers in an array at index 0, 1, 2. Then you add another number at index 3, which would be the same thing as doing this: [a addObject:@(1)]; I could be wrong but I believe the line in the documentation below is wrong: If index is beyond the end of the array (that is, if index is greater than or equal to the value returned by count), an NSRangeException is raised. I think it should say: If index is beyond the end of the array (that is, if index is greater than the value returned by count), an NSRangeException is raised. The documentation also says: Replaces the object at the index with the new object, possibly adding the object. You probably should file a bug. Either the documentation or the code is wrong but I believe it is the documentation.
Topic: App & System Services SubTopic: General Tags:
Mar ’22