Guideline 2.5.1 - Performance - Software Requirements
Your app uses or references the following non-public APIs:
PrivateFrameworks/Pegasus.framework (PGHostedWindow)
The use of non-public APIs is not permitted on the App Store because
it can lead to a poor user experience should these APIs change.
Continuing to use or conceal non-public APIs in future submissions of
this app may result in the termination of your Apple Developer
account, as well as removal of all associated apps from the App Store.
Next Steps
If you are using third-party libraries, please update to the most
recent version of those libraries. If you do not have access to the
libraries' source, you may be able to search the compiled binary using
the "strings" or "otool" command line tools. The "strings" tool can
output a list of the methods that the library calls and "otool -ov"
will output the Objective-C class structures and their defined
methods. These tools can help you narrow down where the problematic
code resides. You could also use the "nm" tool to verify if any
third-party libraries are calling these APIs.
Can anyone please tell how I solve this error? I am not using Pegasus framework at all.
And also which apis consider as non-public?
I think you have used the private framework. The file PGHostedWindow is of Pegasus.framework and may be this file has been used in your app.
You can see the following link which show which file are available in Pegasus.framework:-
https://github.com/JaviSoto/iOS10-Runtime-Headers/tree/master/PrivateFrameworks/Pegasus.framework
You can also see the list of Private Framework on GitHub in the following link:-
https://github.com/nst/iOS-Runtime-Headers/tree/master/PrivateFrameworks
The non-public API refers to Apple API methods that are not documented and offered to the programmer.
Apple does not guarantee that this part of the API will work in future upgrades. These API can freely change this part.
Related
Goal
I'm building an iOS app using flutter for frontend, and C/C++ as backend. They must interoperate through FFI, which is a language binding scheme through C dynamic libraries. I intend to submit it to iOS App Store.
Problems
The Dart FFI sample on accessing C-struct works on macOS through dynamic liking and binding. Now dynamic linking is technically possible on iOS according to Xcode 9 - No option to create dylib project iOS, however, it's unclear to me how to ship the app to AppStore, because dynamic linking is not allowed according to Apple Guidelines Section 2.5.2.
2.5.2 Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they
download, install, or execute code which introduces or changes
features or functionality of the app, including other apps.
Educational apps designed to teach, develop, or allow students to test
executable code may, in limited circumstances, download code provided
that such code is not used for other purposes. Such apps must make the
source code provided by the Application completely viewable and
editable by the user.
Quite a few SO questions confirm this problem, such as:
can I use dynamic library(shared object) in my iphone app?
Will Appstore reviewers allow us to use dynamic library in iOS8?
Then official flutter documentation says
Dynamically linked libraries are automatically loaded by the dynamic
linker when the app starts. Their constituent symbols can be resolved
using DynamicLibrary.process. You can also get a handle to the library
with DynamicLibrary.open to restrict the scope of symbol resolution,
but it’s unclear how Apple’s review process handles this.
Questions
As of the date when I post this (2020), does this say that I could never ship an app using this architecture to App Store?
Is it possible that I static link my C/C++ code into a single binary of a flutter app? Take Unity as an example, their iOS plugin system recompiles the plugin into native app. If flutter has a similar mechanism, how?
The answers saying you can't use dynamic libraries on iOS date to before iOS 8, when support for user-provided dynamic libraries was added.
Nothing in 2.5.2 days you can't use dynamic libraires as long as they are shipped as part of your app. So:
As of the date when I post this (2020), does this say that I could never ship an app using this architecture to App Store?
No it doesn't, as long as "this architecture" refers to using a dynamic library that you link to at build time and bundle into your application.
Adding inputs from Reddit's FlutterDev channel
#escamoteur
As I understand it you are not allowed to load any library from
outside your installation folder. Especially not downloading something
at a later point of time. Could you make this a Stackoverflow question
and tag it with Flutter?
#airflow_matt
Since iOS 8 there can be shared libraries in the bundle, when properly
codesigned I don't see why dlopen wouldn't work. Or you can link the
library with main executable itself (just like flutter does) and
dlopen self (DynamicLibrary.process()). I think it's worth a shot.
Apple rejected our app with this message:
Guideline 2.5.1 - Performance - Software Requirements
Your app uses or references the following non-public APIs:
prefs:root="GraphicsServices.framework"
The use of non-public APIs is not permitted on the App Store because it can lead to a poor user experience should these APIs change.
Continuing to use or conceal non-public APIs in future submissions of this app may result in the termination of your Apple Developer account, as well as removal of all associated apps from the App Store.
Next Steps
If you are using third-party libraries, please update to the most recent version of those libraries. If you do not have access to the libraries' source, you may be able to search the compiled binary using the "strings" or "otool" command line tools. The "strings" tool can output a list of the methods that the library calls and "otool -ov" will output the Objective-C class structures and their defined methods. These tools can help you narrow down where the problematic code resides. You could also use the "nm" tool to verify if any third-party libraries are calling these APIs.
Resources
For information on the "nm" tool, please review the "nm tool" Xcode manual page.
If there are no alternatives for providing the functionality your app requires, you can file an enhancement request.
It's unclear how to fix this.
The issue was generated by https://github.com/erica/uidevice-extension
more specifically: https://github.com/erica/uidevice-extension/blob/master/UIDevice-Capabilities.m
There is even a description in the code, our app was not rejected for more than 1 year now.
/*
THIS CATEGORY IS NOT APP STORE SAFE AT THIS TIME. DO NOT USE IN PRODUCTION CODE.
YOU CAN, HOWEVER, USE THIS TO HELP BUILD YOUR OWN CUSTOM CODE TO PRE_COMPUTE CAPABILITIES.
*/
#define GRAPHICS_SERVICES_PATH "/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices"
We'll removed the use of the library.
Reasons Program License Agreement PLA 3.3.12
We found your app uses the iOS Advertising Identifier but does not include ad functionality. This does not comply with the terms of the iOS Developer Program License Agreement, as required by the App Store Review Guidelines.
Specifically, section 3.3.12 of the iOS Developer Program License Agreement states:
"You and Your Applications (and any third party with whom you have contracted to serve advertising) may use the Advertising Identifier, and any information obtained through the use of the Advertising Identifier, only for the purpose of serving advertising. If a user resets the Advertising Identifier, then You agree not to combine, correlate, link or otherwise associate, either directly or indirectly, the prior Advertising Identifier and any derived information with the reset Advertising Identifier."
Please check your code - including any third-party libraries - to remove any instances of:
class: ASIdentifierManager
selector: advertisingIdentifier
framework: AdSupport.framework
If you are planning to incorporate ads in a future version, please remove the Advertising Identifier from your app until you have included ad functionality.
To help locate the Advertising Identifier, use the “nm” tool. For information on the “nm” tool, open a terminal window and enter, “man nm.”
If you do not have access to the libraries source, you may be able to search the compiled binary using the "strings" or "otool" command line tools. The "strings" tool lists the methods that the library calls, and "otool -ov" will list the Objective-C class structures and their defined methods. These techniques can help you narrow down where the problematic code resides.
I checked who uses IDFA through following command:
grep -r advertisingIdentifier .
I knew that Facebook SDK (3.1.1 version) uses this.
How can I solve this?
The solution for me was that the facebook 3.20 SDK is indeed okay, but I had to remove the FBAudience framework that they include with the FacebookSDK.framework.
Once I removed the FBAudience framework, and ran
otool -L myAppName.app/myAppName
I no longer saw the AdSupport library bundled into my build, printed in the terminal like so:
/System/Library/Frameworks/AdSupport.framework/AdSupport
If you do not find a way to remove the usage of IDFA from the Facebook SDK, then another solution would be to say you're using the IDFA to attribute the installation to a previously served ad (which is actually fairly simple to enable in the Facebook SDK).
This option should be available to you when creating a new build in iTunesConnect if I remember correctly.
This issue has been taken care by Facebook in their latest versions. Update your Facebook sdk to the latest version and this will solve your problem.
I just got done reading the press hysteria around AFNetworking exposing apps to a man in the middle attack. I was surprised that sourcedna.com claims
SourceDNA analyzes the code in thousands of iOS & Android apps.
sourcedna.com even has a search engine to report whether a vendor's apps use the AFNetworking SDK.
Considering they don't have access to paid apps, how do they claim to do this? Do SDKs like AFNetworking log SDK use in some form? If so, to who?
I am curious about this too. Here is what I gather:
SourceDNA only checks whether the library is linked into the app binary. They do not check how or whether the library is actually used by the app.
Objective-C is a dynamic language and keeps a lot of metadata in the binary. You can trivially run tools like class-dump or otool -ov on any unencrypted binary and it will list the names and inheritance of all classes, and the names and signatures of all methods and instance variables in each class, among other things.
Libraries like AFNetworking have many distinctive class names that they can check for in the list of classes in the app. Each version will have some added or removed methods and/or instance variables, so by checking the class dump from the app against the class declarations from each version of the library, they can figure out the version of the library used.
However, apps downloaded from the App Store are encrypted; and the App Store is the only way that SourceDNA could have gotten these apps. It is possible to decrypt / crack encrypted apps (that is how people pirate paid apps -- they buy them, crack them, and post the unencrypted binaries on pirate websites), but the common way to do this I believe involves buying and running the app on a jailbroken device.
I assume that the SourceDNA people must have automated this process somehow, so that they can automatically report on thousands of apps.
As I replied to #janselrx, I believe it's as I suspected and they can only analyze free apps. From their website:
SourceDNA analyzes the code in thousands of iOS & Android apps. This report lets you explore recent data about the mobile SDKs and tools found in the top 500 free apps.
I share a framework between an app and it's action extension. The framework uses API that is not available to extensions.
My question is: Is the app going to get rejected if I keep there references to APIs such as UIApplication.sharedApplication without actually calling them (setting “Require Only App-Extension-Safe API” to NO), or do I need to completely remove any references from the code (i.e. using #ifdef)?
Yes it will be rejected even if it references restricted APIs. We are going through the same process to remove such calls in our framework, alternatively you can have two targets for your framework, one extension-safe and one not with #ifdef guards.
Apple docs: (https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html)
If you have a custom framework that does contain such APIs, you can
safely link to it from your containing app but cannot share that code
with the app’s contained extensions. The App Store rejects any app
extension that links to such frameworks or that otherwise uses
unavailable APIs."
Update for iOS 9: Apple is removing access to invalid frameworks for specific targets, so you won't be able to reference unavailable APIs regardless, and will have to follow what the accepted answer states.
-- Original Answer --
If it's not a huge inconvenience, it's probably best to #ifdef around the references. It will make your code more forward-compatible in the event Apple ever decides in the future to break compilation if your extension references the restricted API (much like they did with trying to get the UUID of the device).
In addition, this will make your framework usable in other scenarios where you might not have UIKit access, like on OS X.