Comments (11)
I have used this library for several production apps, and never had any issues with it. Accessing hidden properties from objects isn't really that illegal; I've never had any app rejected because of doing it at least.
from dznwebviewcontroller.
Thanks for the heads up! That's what I hoped to hear, so thanks for the confirmation :)
For other people stumbling upon this thread:
After years I never jumped into the water of accessing private APIs, sub-classing and in ObjC days sometimes method swizzling were all I needed. But at some point, like detecting long-press on a UIBarButtonItem for back/forward history, you have to rethink if there is another way. Welcome to the dark side ;)
Your solution uses KVO to access the view, which is probably the most elegant approach.
For reference this post titled "Five Pieces of Evidence for "It's Not Private" on SO sums it up, why I might not be that "illegal":
http://stackoverflow.com/a/11924449/844907
- It's a property that you can get to in other ways. Try this and one of those views is, in fact, the _view ivar of the UIBarButtonItem in question. This indicates that access to this UIView is not prohibited itself, though the KVO way in might be questionable (but I doubt it).
NSArray *array = self.toolBar.subviews;
for (UIView *view in array) {
view.backgroundColor = UIColor.greenColor;
}
- They actually trigger the KVO for this property. ivars do not have to trigger the KVO API, right?
- @farcaller mentions a similar case which is for sale in the App Store. Since he/she answered within the first 20 minutes of the question being up there, it's reasonable (but not safe!) to assume that there might be thousands of apps in the App Store that do this.
- This UIView gets subbed out each time the button is pressed, so you cannot just, for example, set a gesture recognizer on it and be done. You can, however, keep setting the same gesture recognizer every time the view gets replaced. To me, this is actually more evidence that it's not a private API thing, but rather you have to be very careful when using it (and use KVO to make sure you have the latest one).
- My app is for sale in the App Store and does this.
One could argue if this approach needs more work when speaking of the current implementation in DZNWebViewController, like observing the KV for view and re-inject the gesture recognizer as Yar pointed out on SO, but currently the only thing that would happend without is, that the gesture would simply not work. Nothing spectacular.
@dzenbot Thanks for the nice solution!
from dznwebviewcontroller.
Mind that I answered it like three years ago and the Apple policy on that changed. Still, I guess the code in here is reasonably safe.
from dznwebviewcontroller.
@farcaller Thanks for joining! Absolutely, many things have changed. But agreed, the approach taken is still valid.
If someone is really picky about: with Swift 2 a simple do-try-catch sandwich around the exchange will ensure that accessing this private View has no consequences if Apple decides to make some changes in future.
from dznwebviewcontroller.
Nothing swift-specific there, you can have @try
block in ObjC for the same purpose (you should actually have it there, as that's common sense for using any unstable api).
from dznwebviewcontroller.
Right, I'd been working through the changes of Swift 2 in the past days, and mixed that up.
That's probably because the ObjC @try
block was very rarely used in projects I saw in the past years. Very rarely. Instead of the slower try blocks with their encapsulation overhead you would likely have seen people checking for class functionality (selector checking), that's what is best practice anyway when not dealing with unstable (external) APIs but the probably changing ones from Apple.
Anyway the exception handling changed when compared to objc.
from dznwebviewcontroller.
I guess we could do something like this instead:
if ([backwardButton isKindOfClass:[UIView class]] && backwardButton.gestureRecognizers.count == 0) {
// interact with the gestures safely
}
This way, we're 100% sure we're dealing with an UIView
instance which responds to the gestureRecognizers
selector. valueForKey:
is totally safe since it just returns nil without exceptions if the object doesn't respond to the selector.
I personally avoid @try @catch
wrapping as much as possible, not only because I also believe it's an overhead, it's just not flexible enough. Checking for class existence [ThisClass class]
or check for respondsToSelector:
is usually good enough and backwards compatible.
from dznwebviewcontroller.
@dzenbot Fully agreed regarding the best approach where available. But I am pretty sure that isKindOfClass would not work here: The UIBarButtonItems do not subclass UIView. They are subclassed from > UIBarItem > NSObject. The UIView is just a private (Sub-)View of the Buttons that's inaccessible without KVO or iterating through the Views.
So the current approach seems still to be the best.
from dznwebviewcontroller.
This check is not for the UIBarButtonItem
, but it's private UIView
property optained using valueForKey:
aka KVC (not KVO)
Snippet here
from dznwebviewcontroller.
That view
property of UIBarButtonItem
is actually an UIButton
instance really, which inherits from UIControl
/UIView
from dznwebviewcontroller.
Both is right. KVO came from having my current KVO code for WKWebView in mind. Ok, time to get some sleep, it's in the middle of the night here ;)
from dznwebviewcontroller.
Related Issues (20)
- Turbolinks not enabling back/forward buttons HOT 1
- HTTP urls not working please help me on this HOT 2
- Dismissing during page load causes KVO crash HOT 10
- Loading URLs HOT 1
- Carthage support? HOT 5
- How to use a custom User Agent? HOT 4
- Required load request method HOT 3
- Support for popupwindow in few websites HOT 3
- toolbarHidden HOT 1
- EXC_BAD_ACCESS
- How to dismiss the view? HOT 4
- how to play video in website HOT 1
- Undefined symbols for architecture x86_64: HOT 1
- Warnings in Xcode 8.3 and Swift 3.1
- Carthage install not working
- toolbar block bottom of website content
- post method
- URL loads but don't get callback of didFinish Navigation method or other callback methods HOT 1
- iOS 11 status bar overlaps with DZWebViewController top bar HOT 1
- Problems with Apple Review
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dznwebviewcontroller.