2

I'm migrating some code to XCode 8 Beta 6, that was working pretty well until XCode 8 Beta 1 inclusively (it was migrated previously from 7.3). Everything is working, except for a new strange behavior with the sliders when using a custom thumb image bigger than the original slider's built-in one:

override func viewDidLoad() {
    super.viewDidLoad()
    sliderBuggy.setThumbImage(UIImage(named: "actionRobotDelay.png"), for: UIControlState())
}
  • Correct behavior: Before Beta 6, once I set the new thumb image, the tracking area was automatically adjusted and the user can slide it from any point inside the image (note: I'm testing on a real iPad mini, not a simulator, and I did not try with iPhone at all).

  • What's happening now: After changing the image, it looks just fine, but the tracking area that allows the user to slide it is still the small one from the original slider's built-in image. This is absolutely annoying from a users's perspective.

What I have tried so far:

  1. Subclassing and overriding thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect. Sadly, after debugging, I found that the method was returning the correct new CGRect, so changing it has not effect.

  2. Overriding touchesBegan to evaluate where the slider is seeing the touch event, so as a possible workaround I could start the tracking manually. But touchesBegan showed clearly that the touch event was only received on the small area that belonged to the original image.

Any idea about a different possible workaround, before I just go and write my own slider class from scratch will be welcome.

nbloqs
  • 3,152
  • 1
  • 28
  • 49
  • Did you file a bug report with Apple? – matt Aug 24 '16 at 16:13
  • 1
    By the way the expression `for: UIControlState()` is wrong. You should be saying `for: .normal`. – matt Aug 24 '16 at 16:14
  • Yes, I did: Bug #27888877. But it has been exactly a week ago, so I'm here asking for a good idea :). Also, that very same day, I post something similar in the Developer Forum. – nbloqs Aug 24 '16 at 16:15
  • Excellent, thanks for the bug number. If I submit the same thing, I'll be able to pile on... :) – matt Aug 24 '16 at 16:16
  • So, it seems to me that an obvious workaround is to subclass UISlider and implement your own hit-testing. You say "But touchesBegan showed clearly that the touch event was only received on the small area that belonged to the original image"; that is exactly what custom hit-testing would fix. – matt Aug 24 '16 at 16:16
  • @matt, you are right, thanks! (although it was working in my projects previously like a charm). Anyway, I just changed it on my code now on Beta 6 and the bug is still there... – nbloqs Aug 24 '16 at 16:17
  • Yes, but I doubt I will subclass, because I even experimented by adding my own Gesture stuff, and nothing worked. So I think that I will start a complete new bare bones slider. – nbloqs Aug 24 '16 at 16:18
  • Hmmm, I don't think you're listening. If my guess is right, this should be a one-liner, very easy (especially if, as you say, `thumbRect` is already giving the right answer). But whatever. (Though it's a little odd that you're asking this question if you don't actually want to hear a possible answer.) – matt Aug 24 '16 at 16:19
  • Hi @matt. I'm really interested in hearing! It's just that I did not get it, since my subclassing experiments did fail systematically. Can you post an answer/comment with some code? Thanks! – nbloqs Aug 24 '16 at 16:21

1 Answers1

4

Subclass and munge hit-testing to do what the slider should have been doing (who knows why it isn't doing it?):

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let tr = self.trackRect(forBounds: self.bounds)
    if tr.contains(point) { return self }
    let r = self.thumbRect(forBounds: self.bounds, trackRect: tr, value: self.value)
    if r.contains(point) { return self }
    return nil
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I have no idea why this is not exactly what UISlider is already doing; it certainly ought to be. Also, sorry it turned out not to be a one-liner; I didn't mean to exaggerate. – matt Aug 24 '16 at 16:30
  • 1
    Holy cats, it's not a bug! I just tried this in a totally fresh project and there's no problem. The issue is merely that you forgot to increase the slider's height to accommodate the size of the larger thumb. – matt Aug 24 '16 at 17:31
  • Wow. But it was working in previous versions up to X8 Beta 1 without doing that. I will try anyway to increase the size on the storyboard, since it seems that they have changed things... Do you think I should drop the submitted bug report? – nbloqs Aug 24 '16 at 17:43
  • 1
    I think what changed is merely that they no longer compensate for this mistake. And I don't think that counts as a bug. You can leave the bug report but I'm betting it will come back "works as expected". Moreover, my "workaround" is still perfectly good, as it enables touchability outside the slider's bounds, which is exactly what you need. :) – matt Aug 24 '16 at 17:47
  • Well, in the past, my view is that the slider was "autoadjustable to the thumb image", so we did not need to both change the image in the code and then go and change the size in the storyboard. Since I'm rotating the slides and moving them by code in order to self-align everything with other controls with custom images, that was a huge help from the development environment. Thus, I think that your workaround is pretty good, since it gives us back that "automatic" behavior that we use to enjoy until Beta 1. Thanks! – nbloqs Aug 24 '16 at 17:52