Using `valueForKey` to access view in UIBarButtonItem, private API violation?
Asked Answered
J

2

9

Since UIBarButtonItem doesn't subclass UIView, it's impossible to get at the normal characteristics like its frame.

One way to do this is [barButtonItem valueForKey:@"view"]

This works perfectly, and allows you to add a GestureRecognizer (for instance) to the underlying UIView.

However, is this a private UIKit API violation?

Jana answered 12/8, 2012 at 16:1 Comment(2)
See this answer https://mcmap.net/q/16329/-get-the-width-of-a-uibarbuttonitem for more info.Construction
Hi @Joe, yeah, I saw that one, but didn't know what to make of it. Now I think that it's going to be fine. The reason they KVC it is that the view gets swapped a lot.Jana
W
18

This is not private in terms of immediate rejection upon validation, but it's private enough to be considered fragile (that is, new iOS version can break your existing app in the app store that's using the code).

I can say, that a similar code (fetching backgroundView ivar of UIToolbar via KVC) has passed app store validation and is being used in production.

In case of possible bad things, you must wrap the method in @try { ... } @catch, so that you intercept KVC possibly failing in newer iOS release.

Wolf answered 12/8, 2012 at 16:37 Comment(3)
App was just approved with this code in just about every corner of the app. I mean, in terms of execution, the code is just on one place :) So thanks again!Jana
@farcaller, what do you think about using setValue:forKey: on a "private" api? I want to set _customRightViews property to nil for a UINavigationItem.Goahead
My answer is mostly applicable for any "private" ivar.Wolf
J
9

Five Pieces of Evidence for "It's Not Private"

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

Jana answered 12/8, 2012 at 17:58 Comment(2)
What a timeless answer. Probably still applicable to iOS 9.Subroutine
I guess this is the difference between private ("don't use it, we need to be free to change this internal implementation detail at any time") and undocumented ("use at your own risk, we are not responsible").Heller

© 2022 - 2024 — McMap. All rights reserved.