iOS extension and restricted API - ios

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.

Related

dart/flutter: How to ship iOS apps using flutter frontend vs. C/C++ backend to App Store?

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.

iOS: How to remove the reference to API that is not in use?

I have submitted ionic app to App store but it asks me to add reference to the info.plist file. Following is the error.
ITMS-90683: Missing Purpose String in Info.plist - Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSBluetoothAlwaysUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data are required to include a purpose string. If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs.
But my project doesn't use Bluetooth.
How to get rid of this error and how to remove api reference that is not in use. I am new to xcode and iOS.
Check if any of your external libraries are using Bluetooth. Search for "NSBluetoothAlwaysUsageDescription" in the whole project, normally if a library uses Bluetooth, you will find it in its Info.plist
If you have to use that library, just add that purpose string to the Info.plist of the main project to make Apple happy.
I have the same problem with an app and added the NSBluetoothAlwaysUsageDescription; Apple has subsequently rejected it saying they could not identify any Bluetooth functionality in the app and to remove the permission key. So now I'm stuck.
In my case (an Ionic 3 app), despite not explicitly including cordova.plugins.diagnostic, its bluetooth dependency was being brought into my iOS build and resulting in the same warning on submission to apple.
To correct I first added this line to config.xml (which basically says we don't want to bring in any of the diagnostic modules):
<preference name="cordova.plugins.diagnostic.modules" value="" />
Then ran the following to add it to my project:
ionic cordova plugin add cordova.plugins.diagnostic
And after removing and re-adding the ios platform the generated Xcode project no longer had the bluetooth dependency and I was able to submit to Apple without any problems.

Error Appstore connect : Missing Purpose String in Info.plist File (NSBluetoothPeripheralUsageDescription)

Dear Developer,
We identified one or more issues with a recent delivery for your app,
. Please correct the following issues, then upload again.
Missing Purpose String in Info.plist File - Your app's code references
one or more APIs that access sensitive user data. The app's Info.plist
file should contain a NSBluetoothPeripheralUsageDescription key with a
user-facing purpose string explaining clearly and completely why your
app needs the data. Starting Spring 2019, all apps submitted to the
App Store that access user data will be required to include a purpose
string.If you're using external libraries or SDKs, they may reference
APIs that require a purpose string. While your app might not use these
APIs, a purpose string is still required. You can contact the
developer of the library or SDK and request they release a version of
their code that doesn't contain the APIs. Learn more
(https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).
Best regards,
The App Store Team
Actually, I am not trying to use to access bluetooth. But somehow App Store reject my app like this.
If you added CoreBluetooth.framework in linked libraries and frameworks section in Build phases , remove it.
Also, check if any third party libraries that you are using in the project uses bluetooth. Check if any files import CoreBluetooth.framework
Are you using advertising frameworks ?
Ad frameworks sometime use bluetooth information.

How does SourceDNA track SDKs used by apps

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.

Is NSPortMessage in the iOS API?

I am trying to write a demo according to Thread Programming Guide about run loops.
When I implement NSPortDelegate's - (void)handlePortMessage:(NSPortMessage *)portMessage; method it prompts an error:
Receiver type 'NSPortMessage' for instance message is a forward declaration
So I try to import by "Foundation/NSPortMessage.h", after which it says:
Foundation/NSPortMessage.h file not found.
So I wonder whether we can use NSPortMesssage in iOS?
NSPortMessage doesn't seem to be in the iOS documentation so is presumably a private API. Xcode does code completion of NSPortMessage for me when I try to use it, presumably because of the forward declaration. However, if I ask Xcode to show me the definition of NSPortMessage it says the symbol is not found which would confirm that it is a private API.
The class exists in the Objective-C Runtime on my iPhone 4s so it is on the device. However NSPortMessage allows inter-process communication which I assume would be against the iOS sandboxing security. Perhaps it will work for inter-thread communications though.
I certainly wouldn't try and use it in an app that is intended for the App Store.
Since the iOS version of distributed object programming guide and certain APIs are also deprecated, it seems that all stuff related to port-based input source are discouraged to be used for iOS development. But setting up a port-based channel to communicate between threads using Core Foundation function still be an available choice.

Resources