I hope someone, who has released application with in-app purchase subscriptions in the Mac App Store, can help me to resolve issues with application rejection. The App Review Team is completely useless, as they keep repeating the same messages and claims to all my desperate pleas for more information and explanation about what I should do to get approval for the application.
Application in question has some basic features offered for free, but using some advanced features requires purchasing a subscription (which can be monthly or yearly). Once a user try to use any advanced feature, he/she will be informed about required subscription and is offered to purchase monthly or yearly subscription. Purchasing follows starboard in-app purchase procedure and upon purchasing a subscription, the user can use all advanced features.
This all works and has been successfully tested using sandbox Apple ID. The application has been submitted for a review, but it was rejected due to the following reason:
Guideline 2.1 - Performance - App Completeness
We are unable to complete the review of your app because one or more of your in-app purchase products have not been submitted for review.
Next Steps
To resolve this issue, please be sure to take action and submit your in-app purchases and upload a new binary in App Store Connect so we can proceed with our review.
I have no idea what "in-app purchase products" I have to submit for review. I asked the review team about it, but I got essentially the same reply as quoted above. Then I asked the same question again and even uploaded two videos with my reply, showing subscription purchase process in the application, after which advanced features become available. But again, I got this reply:
Regarding the guideline 2.1.0, we would like to clarify that as we were able to find in-app purchase items in the binary, we noticed that they have not been submitted for review.
To resolve this issue, please be sure to take action and submit your in-app purchases and upload a new binary in App Store Connect so we can proceed with our review.
So again, I'm required to "submit my in-app purchases" because "as we were able to find in-app purchase items in the binary, we noticed that they have not been submitted for review". The even suggested this:
Consult with fellow developers and Apple engineers on the Apple Developer Forums.
Can someone with application with subscription(s) distributed on the Mac App Store PLEASE explain to me what this response means and what do I need to submit to them for a review? Pretty please, as I'm becoming really annoyed and frustrated with such clumsy and unhelpful approval process, unclear reasons for rejection and completely useless reply by the review team.
Thanks a lot!
-- Dragan
Post
Replies
Boosts
Views
Activity
I’ve finally changed my main development platform to macOS 14 Sonoma and almost immediately have I encountered something I consider being a bug. I searched for similar issues, but nowhere have I found any relevant information or help.
The issue is rather funny; if you have a subview and, for whatever reason, it finds itself outside of its superview’s bounds, it remains visible, instead of being hidden. It’s like you have a window on your room wall, but still the interior of your room is visible outside of window’s borders :-)
Here’s a simple Xcode project that explains what I’m talking about:
https://zigz.ag/temp/SubviewBug/UnhiddenXcodeProject.zip
Unpack and build this project, run the test application and see it yourself.
However, there are some differences, regarding the Xcode/SDK version used to build the application and the macOS version it runs on. The project format is “Xcode 13.0” and MACOSX_DEPLOYMENT_TARGET = 13.0. Here you can find application bundle, build with Xcode 14:
https://zigz.ag/temp/SubviewBug/UnhiddenXcode14Build.zip
The relevant build parameters, as found in application's Info.plist are:
BuildMachineOSBuild: 22G605
DTPlatformVersion: 13.3
DTSDKBuild: 22E245
DTXcode: 1431
DTXcodeBuild: 14E300c
If you run it on both Ventura and Sonoma, you’ll see ti behaves as expected. However, here you can find application bundle, build with Xcode 15:
https://zigz.ag/temp/SubviewBug/UnhiddenXcode15Build.zip
The relevant build parameters, as found in application's Info.plist are:
BuildMachineOSBuild: 23D56
DTPlatformVersion: 14.2
DTSDKBuild: 23C53
DTXcode: 1520
DTXcodeBuild: 15C500b
Now, if you run this build on Ventura, you’ll see it behaves fine. Running it on Sonoma however, shows the behaviour I’m trying to explain; the ratio button titled “Two” remains visible, even though its superview shrinks and it goes out of its superview’s bounds. So, the issue is present only on Sonoma, if build with Xcode 15.
The difference is visible even inside Interface Builder. Here is a short video of shrinking a superview in IB of Xcode 14, note how the “Two” radio button becomes invisible, as it goes outside of its superview’s bounds:
https://zigz.ag/temp/SubviewBug/InterfaceBuilderXcode14.mov
Here is the video of shrinking the same superview in IB of Xcode 15, the “Two” radio button remains visible regardless of its superview’s bounds:
https://zigz.ag/temp/SubviewBug/InterfaceBuilderXcode15.mov
Is this a bug? Or did I miss something in macOS 14 Sonoma SDK release notes, which would indicate from now on this is expected behaviour (highly unlikely)?
-- Dragan
Hi all,
I’ve never used NSFileCoordinator class, simply because I haven’t had any need for it until now. And now that I’m about to need it rather soon, I’m trying to get a grasp on it, but it does’t go very well so far. Even though the documentation reads pretty clear, I don’t seem to get it correctly. Also, I haven’t found any example online, which would be of any value to me, so I’m taking my chances here. In order to begin to understand it, I’ll start with the simplest real case scenario, for which I don’t even understand yet whether NSFileCoordinator is the way to go.
Let’s say, I have a bunch of directories in a parent directory (so, all are at the same level in the file system hierarchy), which I want to compress and pack in a ZIP archive (for example) programatically (e.g. using libarchive). After selecting which directories to zip, I’d like to ensure that once the zipping operation has started, any changes to all files and directories in the hierarchies of selected directories to be packed will stay unchanged, until the zipping operation is complete. That means, no file anywhere in the hierarchies should be modified in any way and no directory or file anywhere in the hierarchies should be added, deleted or moved.
I thought I would achieve this by using one NSFileCoordinator and a bunch NSFileAccessIntent objects, each for every directory at the top level of the hierarchies. The intents will be for reading without changing, because that’s what I want to do; just to read those directories and files (and zip them) without making any changes to them. The code would be something like this (I want to do the operation asynchronously):
NSMutableArray *intents = [NSMutableArray arrayWithCapacity:[sources count]];
for (NSURL *source in sources)
[intents addObject:[NSFileAccessIntent readingIntentWithURL:source options:NSFileCoordinatorReadingWithoutChanges]];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[coordinator coordinateAccessWithIntents:intents queue:[NSOperationQueue new] byAccessor:^(NSError *error)
{
// Do the zipping here.
}];
It looks simple and straightforward, but it doesn’t really work as I thought it would. Once the operation is started, I can modify files and directories the way I described above, from within the same application/process, as well as others (using NSFileCoordinator approach), like Finder.
Hence, I’d really appreciate if someone can point me in the right direction. For example, what needs to be done to achieve this simple example I described above. Once I get some pointers, I may start understanding those classes and documentation in the right way and work myself through more complex examples and use cases.
Thanks for any insights.
-- Dragan
I have an application, which "messes" with files in different ways. It can modify, move, copy, even delete them. So far all file operations were performed directly, without any checking if affected files were already busy or locked by other processes (or even the same application). So, in case a locked file is encountered and the operation failed, an appropriate error was reported.
Now I want to enhance this behaviour and ensure two things:
make sure all files to be performed on are available for the operation in question (not busy/locked by other processes)
before the operation starts, inform other processes, so they can act accordingly if necessary.
The most obvious solution to me is using NSFileCoordinator class and its reading/writing options. And even though documentation for this class is quite descriptive and helpful, I have some unanswered questions. So before doing my own tests (and perhaps even coming to potentially wrong conclusions), I'd like to ask here if someone has already had experience with this class and what I want to achieve with it.
The basic question is: if I start coordinated operation (reading or writing) on a directory identified by an URL, does that operation intent automatically spans to all files and folders in the directory, all the way down the whole directory hierarchy?
Or let me try to me more specific; I want to read all files in a certain directory, but then also list all its subfolders and read their (sub)files and go on like that down the directory hierarchy. While doing so, I don't want any other process to mess (modify, delete…) with any of those subfiles and subdirectories in the hierarchy. Is it enough to request coordinated reading to the root directory only, or do I still need to require coordinating reading to subfiles and subfolders? Or to put it another way, if I start coordinated reading on the root directory only, will other processes still be allowed to mess with subfiles and subdirectories?
Or does this behaviour depend on the read/write option I actually want to perform? For example, requesting NSFileCoordinatorReadingWithoutChanges on a directory doesn't necessarily imply reading intent to all its subfolders and subfiles down the hierarchy. But requesting e.g. NSFileCoordinatorWritingForDeleting on a directory certainly implies the deletion will also affect all its subfiles and subfolders.
I hope I was clear enough about what I want to achieve. Thanks for any insights.
-- Dragan
I have a simple problem, but I’m not able to solve it in an easy way, so I suspect I’m doing something wrong.
I have a simple view-based NSTableView, which is a dragging source. The data being dragged are provided to the pasteboard using the standard data source method - [NSObject tableView:writeRowsWithIndexes:toPasteboard:]. When rows of the table view are dragged, AppKit automatically creates a dragging image consisting of the visual copy for all dragged rows and all columns of the table view. If I want only particular columns, I can override -[NSTableView dragImageForRowsWithIndexes:tableColumns:event:offset:] and include only the columns I want in the dragged image.
Since -[NSObject tableView:writeRowsWithIndexes:toPasteboard:]is rendered deprecated as of macOS 11, I want to use the alternative (which also supports multiple item dragging) -[NSObject tableView:pasteboardWriterForRow:]. However, when I use this method, AppKit creates a dragging image consisting of the visual copy for all dragged rows, BUT ONLY the column where the drag started. Overriding -[NSTableView dragImageForRowsWithIndexes:tableColumns:event:offset:] has no effect, as in this case that method isn’t being called at all.
So the question is, how do I influence the dragging image creation in the latter case? I haven’t found in docs anything related to that (except for the method mentioned above, but not being called in this case). Implementing data source method -[NSObject tableView:updateDraggingItemsForDrag:] doesn’t help, as it’s really intended to change the dragging image after the dragging has started and at the time it’s called for the first time, the AppKit created image is already there and visible. I know I can (try to) subclass NSTableView and override NSDraggingSource methods (and call super at the end of each override to make sure the data source object is being messaged as well) but I hope there's a simpler and shorter solution.
Thanks a lot for any solution, hint or a suggestion.
-- Dragan
I’m developing an application, which requires execution of authorized privileged operations. Hence, the application needs to install its helper tool in /Library/PrivilegedHelperTools using SMJobBless() API and so on… The standard procedure, explained in numerous examples and sample codes on Apple Developer web site and elsewhere. This is not the first time I do that, so I did everything necessary to make it work. And it works perfectly; the helper tool is successfully verified and installed, privileged operations are successfully being executed upon authorization.
However, one thing bothers me and that is General > Login Items in the latest (and renamed) System Settings.app in Ventura. It allows user to manually enable/disable installed login items and helper tools (background items). My problem is that my helper tool appears in the list with my full name (Dragan Milic), probably extracted from the signing Developer ID Application: certificate, not with the name (and icon) of the application which verified/installed it. At the same time, some other items appear with the application name and icon. Please take a look at the attached picture below:
I tried all I could think of to make the helper tool to appear with name/icon of the parent application, but without success. Using codesign and otool, I examined a bit some of the other applications and their helper tools, which correctly appear with application name/icon and I can't see much differences from my own, apart form different bundle identifiers and developer's signing certificates.
I'd be really, sincerely thankful if someone could help me solving this, as I've been banging my head agains it for more than a day. Thanks very much in advance.
-- Dragan
I’ve got a Mac application, which uses CoreData. The usage of the framework is rather moderate, nothing really fancy about it. The application is build with SDK 11 (1Big Sur), but the minimal deployment target is Sierra (10.12).
The last “successful” build was made using Xcode 12.4 (12D4e) and it used SDK version 11.1. After I updated Xcode to the latest version 12.5.1 (12E507) it apparently updated SDK version to 11.3 and I started getting problems dynamically linking to CoreData version on older versions of macOS. The application works okay on Mojave and later, but on High Sierra and earlier it crashes on launch with the following error:
Dyld Error Message: Library not loaded: /System/Library/Frameworks/CoreData.framework/CoreData Referenced from: /Applications/MyApp Reason: Incompatible library version: MyApp requires version 300.0.0 or later, but CoreData provides version 1.0.0
Now, the interesting thing is that I’ve got yet another macOS app, which also uses CoreData in a very similar fashion like the first one. It’s also built with Xcode 12.5.1 / SDK 11.3 and it runs fine on everything from Sierra to Monterey. The only difference related to CoreData usage is that the first one (the crashing one) uses options NSMigratePersistentStoresAutomaticallyOption: YES and NSInferMappingModelAutomaticallyOption: YES when creating persistent store, while the second application (the running one) doesn’t use any option. But I don’t think that actually matters in this case.
Can anybody advise me how to solve this problem? Thanks!
-- Dragan
I’ve got an application, which uses (a couple of) XPC service(s) to accomplish various tasks. Since recently, I don’t know when exactly but probably after some macOS update, I started seeing these messages coming out when XPC services are used:
[connection] nw_endpoint_handler_set_adaptive_read_handler [C1.1 140.82.121.6:443 ready socket-flow (satisfied (Path is satisfied), viable, interface: en1, ipv4, dns)] unregister notification for read_timeout failed
or
[connection] nw_endpoint_handler_set_adaptive_write_handler [C1.1 140.82.121.6:443 ready socket-flow (satisfied (Path is satisfied), viable, interface: en1, ipv4, dns)] unregister notification for write_timeout failed
This happens when the service want’s to use outgoing connection. Not that it only happens in Xcode during debugging, but the deployment version of the application/XPC emits these messages to the console as well. However, everything works correctly as it has before. I’d like to surpass those messages going into the console, but I’d also like to understand what they actually mean and why they appear in the first place. Searching the Internet didn’t really revealed any useful info, so I hope someone here can help me. Anyone else seeing those?
Reading Keychain Services docs on and on and I can’t seem to find a way to access the keychain, which in Keychain Access application appears as “iCloud”. I’ve got no idea what its path could be so I could use SecKeychainOpen(), it isn’t in the default list returned by SecKeychainCopySearchList(), I can’t get it using SecKeychainCopyDefault(), even though it’s listed as “Default Keychains” in the Keychain Access,…
I assume I should be looking completely elsewhere, but I’d appreciate any hint where that could be.
Thanks,- Dragan
Hello,I’m not very experienced in cryptography and related topics, so it may be possible I’m overlooking something quite obvious. The straightforward question is: is it possible to create OpenSSH compatible key pairs, like ssh-keyget utility does, using Security framework? Let’s say, I want to do the equivalent of the following terminal command:ssh-keygen -t rsa -b 4096 -C “me@mail.com"
I’m trying that with this simplified piece of code:
CFMutableDictionaryRef privAttrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(privAttrs, kSecAttrIsPermanent, kCFBooleanFalse); CFDictionarySetValue(privAttrs, kSecAttrLabel, CFSTR("me@mail.com")); CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(attrs, kSecAttrKeyType, kSecAttrKeyTypeRSA); CFDictionarySetValue(attrs, kSecAttrKeySizeInBits, CFSTR("4096")); CFDictionarySetValue(attrs, kSecPrivateKeyAttrs, privAttrs); CFErrorRef error = NULL; SecKeyRef privateKey = SecKeyCreateRandomKey(attrs, &error); if (privateKey) { CFDataRef data = NULL; OSStatus status = SecItemExport(privateKey, kSecFormatSSH, kSecItemPemArmour, NULL, &data); if (status == errSecSuccess) { // ... save private key data to a file ... } SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey); if (publicKey) { status = SecItemExport(publicKey, kSecFormatSSH, kSecItemPemArmour, NULL, &data); if (status == errSecSuccess) { // ... save public key data to a file ... } CFRelease(publicKey); } CFRelease(privateKey); } CFRelease(privAttrs); CFRelease(attrs); This seems to create valid RSA key pair, which I can add to the Keychain on creation if I choose to (setting permanent attribute to true), but the exporting operation doesn’t end up with files I expect. The PEM armour seems not to be correct, the text representation of the key begins and ends with -----BEGIN/END RSA PRIVATE KEY----- as opposed to -----BEGIN/END OPENSSH PRIVATE KEY----- and the key structure looks different in general. If I try to show key fingerprint usingssh-keygen -l -f <keyfile>I get response that “<keyfile> is not a key file. If I, for example, try to upload the public key to GitHub to use for SSH connection, it’s rejected, because “key is invalid, you must supply a key in OpenSSH public key format."I’d appreciate if anyone points out what I’m doing wrong and whether this is achievable with Security framework at all.Thanks,-- Dragan