Giter VIP home page Giter VIP logo

Comments (11)

dzenbot avatar dzenbot commented on June 19, 2024

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.

winkelsdorf avatar winkelsdorf commented on June 19, 2024

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.

farcaller avatar farcaller commented on June 19, 2024

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.

winkelsdorf avatar winkelsdorf commented on June 19, 2024

@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.

farcaller avatar farcaller commented on June 19, 2024

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.

winkelsdorf avatar winkelsdorf commented on June 19, 2024

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.

dzenbot avatar dzenbot commented on June 19, 2024

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.

winkelsdorf avatar winkelsdorf commented on June 19, 2024

@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.

dzenbot avatar dzenbot commented on June 19, 2024

This check is not for the UIBarButtonItem, but it's private UIView property optained using valueForKey: aka KVC (not KVO)
Snippet here

from dznwebviewcontroller.

dzenbot avatar dzenbot commented on June 19, 2024

That view property of UIBarButtonItem is actually an UIButton instance really, which inherits from UIControl/UIView

from dznwebviewcontroller.

winkelsdorf avatar winkelsdorf commented on June 19, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.