
Apple starts rejecting apps that use UIWebBrowserView - simplyinfinity
https://forum.ionicframework.com/t/ios-application-rejected-with-reason-non-public-apis/46717
======
Sephiroth87
Just to be clear, UIWebBrowserView is a private class, not the public
UIWebView people should use, so it's not like Apple started rejecting random
apps for no good reasons...

~~~
Sujan
Thanks for the info.

Is your obj-c good enough to explain what Ionic is actually doing in the file
that triggers the problem? [https://github.com/driftyco/ionic-plugin-
keyboard/blob/maste...](https://github.com/driftyco/ionic-plugin-
keyboard/blob/master/src/ios/UIWebViewExtension.m) Are they really doing it in
a 'bad' way?

~~~
afoxtron
Just wanted to chime in and say that's actually really bad code. Accessing a
views subviews like that and looking for a specific instance of a class is
just begging for a crash.

~~~
kennywinker
Counterpoint: they have all the nil checks needed for this to fail silently if
no UIWebBrowserView is found. It's a fragile implementation in that it might
stop working if Apple changes the internal implementation of UIWebView, but it
doesn't look like it'll crash because of it.

That said, clearly it's not good for Apple to have large numbers of apps
relying on private implementation details. It hamstrings them when it comes
time to improve the OS. That translates to a harm for users. I'm not
advocating for this hack.

I wonder if this could be avoided by switching to WKWebView?

~~~
masklinn
> I wonder if this could be avoided by switching to WKWebView?

Nope, the keyboard UI is pretty much the same and the API does not provide any
more support for disabling the accessory bar.

------
dopernicus
Hey all, author of the plugin for Ionic here. What a way to start a Friday
morning!

So this was apparently a ticking time bomb, since we were directly using the
name "UIWebBrowserView" to override that method at runtime, which is trivially
found by Apple.

For anyone asking, "Why not use public APIs?", the answer is: because there
are none for removing the keyboard accessory bar in a web view. At least not
when the plugin was written, and as far as I know, that is still the case.

For hybrid apps, removing the keyboard accessory bar to look like native is
fairly common practice. At the time the code was "written" (I'll use that term
loosely), I didn't know much about Objective C and went with what worked. And
it has worked, for the past couple of years, until today.

For the time being, I've removed the private API use until we find a solution
that doesn't get automatically rejected (by not using the name of a private
API directly, for example).

Thanks to everyone who brought this to our attention, and sorry for the
headache!

~~~
dheera
Why does this affect you but not affect Meteor and Phonegap, both of which
also use a hybrid approach?

~~~
dopernicus
Just to clarify, this is not an Ionic-specific issue: It's a Cordova plugin
maintained by Ionic, so it will affect all apps using the plugin, including
Meteor-Cordova and PhoneGap apps. The fix is the same for everyone: update the
plugin!

It's installed by default on all Ionic apps, so it's safe to say a majority of
Ionic apps will be affected by it.

------
TazeTSchnitzel
Using private APIs in a plugin that other people embed into their apps, and
not warning them in advance, strikes me as a reckless thing to do.

~~~
LeoNatan25
Worst of all, not even attempt to hide it. It is very easy to hide such
trivial uses of "private" API.

~~~
masklinn
I'd say attempting to hide it would be way worse, it would have been better if
they'd clearly noted they're making use of private APIs which could break at
any moment in the readme/documentation, but at least you can see it's dodgy by
just going through the code.

~~~
LeoNatan25
The way I see it, there are two types of private API use - malign and benign.
Malign would be attempting to circumvent iOS security, such as attempting to
access disallowed services, attempting to retrieve personal information,
abuse, etc. Bening would be use for overcoming Apple bugs or shortcomings in
public API. If for the latter, as here, it is not that bad in my book.

~~~
masklinn
Motivation is irrelevant to my comment.

If you're using private APIs in a library, any user of the library is at risk
of submission rejection _because of the library_ , the least you can do for
them is let them make an at least somewhat informed choice about it, and
ideally (if your library is multi-purpose) have them opt in the behaviour
requiring private API access.

It's not a question of purpose or of "badness", and really has nothing to do
with your book.

~~~
LeoNatan25
Oh, I agree with that completely. Just wanted to distinct between "good" and
"bad" use of private API.

------
nolanl
In case anyone is wondering, this plugin hides the "accessibility bar," i.e.
the keyboard bar that appears when you tap on a form element in iOS:
[https://nolanwlawson.files.wordpress.com/2016/03/accessibili...](https://nolanwlawson.files.wordpress.com/2016/03/accessibility_bar.png)

The accessibility bar is really annoying for hybrid app developers, because
it's often not needed, and just takes up valuable screen real estate. As one
of my coworkers put it, it has no purpose other than to announce, "Hi! I'm a
WebView!"

~~~
minikites
I'm having trouble thinking of cases when it isn't needed, do you have a
simple example?

~~~
nolanl
Let's say you have one big contenteditable, so there's only one field, and
it's pointless to have "previous," "next", and "done" buttons. Or just any
situation where you don't think the user needs to be able to switch left and
right and can tap instead. Or situations where you want to make your own UI
instead of using the default Safari UI.

~~~
minikites
But the "Done" button would hide the keyboard so you can see more of the text
to review it, right? It just seems user-hostile to remove system features that
otherwise always appear.

------
masklinn
Note that it's not _starting to_ , quickly googling it shows they were
rejecting applications back in October 2015 on that ground:
[https://forums.developer.apple.com/thread/22110](https://forums.developer.apple.com/thread/22110)

The difference may be in the way it's accessed, and that apple added new
detectors which trigger on ionic's access pattern.

~~~
duaneb
I suspect that just a simple search for the class name would be sufficient for
99% of existing cases.

------
Sujan
Actually, it rejects apps that use some private methods of UIWebView.
Unfortunately this is done in one of the 'main' Ionic plugins and was fine
until now and was used in thousands of apps...

------
afoxtron
Third party developers should conform their code to Apple's public API's,
plain and simple. Hacking around in Apple's private APIs is just begging for a
crash or an incompatibility when Apple changes something under the hood.

~~~
techdragon
For developers not actually writing code that does this but rely on the
developers of tools like Cordova/Ionic.., are they expected to learn the
language the apple code is written in in order to do that?

At some point the burden falls to the abstraction author for the mistake, and
the abstraction user chalks one up in "well I couldn't have foreseen that
happening"

~~~
c1sc0
I'd say the take-away message here is: yes, learn a little about the
environment you are working with & my guess the take-away is rather going to
be "Next time I'll void abstraction layer X".

------
sopooneo
One thing I've never understood about situations like this: why doesn't the
platform manufacturer just make it technically impossible to call private
classes/methods without some kind of signed key? White list the OS
classes/methods that all apps are generally allowed to call, and require some
kind of signed key to call anything else.

Why try to fix this with policy rather than some technical block? I am sure I
am missing something here, so any insight is greatly appreciated.

~~~
schrodinger
I'm sure that'd be preferable, there's just no easy way to do that with
objective-c, because of how dynamic it is. You can pass any message (call any
function by name) on any object. Changing that would be a really significant
effort.

~~~
Benjammer
Yeah it's kind of impossible when you basically have full control of the
method dispatch system at runtime.

------
Sujan
Title should probably include information that "UIWebBrowserView" is a private
API and not UIWebView.

~~~
LeoNatan25
Or, people should read the article. It's as simple as that.

~~~
Sujan
Not really.

Most users won't read all the finer points in the linked forum thread and
comments here and will so remember the wrong, incorrect or incomplete
information from the title and maybe make decisions influenced by that in the
future.

------
Etheryte
Another day, another misleading title.

~~~
LeoNatan25
Title is accurate. People don't know what a UIWebBrowserView is, it's their
problem.

Hint: It's completely different than UIWebView.

~~~
Etheryte
Accurate but misleading, I never said the title was inaccurate.

~~~
LeoNatan25
I cannot see how it is misleading by being accurate. People just need to read
the article, then do some research (like a simple Google search).

~~~
marknutter
It's misleading because most people will read it as Apple rejecting hybrid
apps like those that use Cordova, which is completely false. In fact, in this
very thread someone commented "Good riddance. If your "app" fits entirely in
an UIWebBrowserView, it should be a website." Seeing as how a good portion of
HN users don't bother clicking through to the actual articles, this title can
definitely be categorized as misleading. I myself initially thought it meant
Apple was starting to reject hybrid apps, but only upon reading the comments
did I realize what the title actually meant.

------
leoh
AFAIK there is another way to do this using categories that has not been
banned yet.

~~~
Sephiroth87
Well, you CAN doesn't mean you SHOULD :)

------
joeblau
There are ways to get around this technically where Apple couldn't detect what
you're doing, but definitely not recommend. I wonder if these rejections are a
nod to Apple doing something with the underlying Web Browser View? Apple may
be trying to prevent what would potentially become crashes by changing that
private API. Start the heads up no so by the time Sept comes around with iOS
10, they can remove / refactor that class.

------
masters3d
Apple is trying to make it more difficult to link to private API in Xcode 7.3
but objc doesn't help [https://github.com/kif-
framework/KIF/issues/770](https://github.com/kif-framework/KIF/issues/770)

~~~
Sephiroth87
It wouldn't have done much in this case anyway, since that's just removing the
ability to link private frameworks, while this is a private class of UIKit
which is public...

------
johansch
Why is this enforced by a policy rather than code? Why aren't "private APIs"
even accessible for third party apps?

(I guess what I'm asking: why hasn't a security mechanism been built in the
language/linker/OS for this purpose?)

~~~
userbinator
Do we really need more "security mechanisms" just because people might find
something they could do which you didn't expect, but is actually _useful_ for
them and allows them to do what they want? A bit of a philosophical point, but
I don't think it's a good thing at all if everything anyone ever did required
explicit approval from some entity.

Then again, I don't get the culture of strict conformance around iOS (and
Apple in general) either...

~~~
realusername
The problem of doing this is you end-up with something like the Win32 API,
with decade of undocumented methods people called that you must support 10
years after because some critical applications are crashing.

~~~
asveikau
It's amusing to me that people defending very restrictive development
frameworks will often talk as if any easement of the policy is a slippery
slope to Windows 98. There is no middle ground! Can't do that because PCs
sucked in the 90s! (Also implicitly ignores that NT based Windows got a lot
better.)

------
_Codemonkeyism
Will this affect React Native?

~~~
jeanregisser
No, React Native is not using any private API. Also it's not using web views
for rendering.

~~~
_Codemonkeyism
Thanks!

------
pearjuice
Good riddance. If your "app" fits entirely in an UIWebBrowserView, it should
be a website.

~~~
Etheryte
Did you even read the link?

