Re: UIImageView Scaling


Steve Christensen <punster@...>
 

Hi Rick,

Sorry I didn't reply sooner but the day job got in the way. I just tried out your test app on my iPhone. I ended up adding overrides of viewWillLayoutSubviews() and viewDidLayoutSubviews() and printing the imageView bounds before and after the layout pass. Here's what I saw:

Case 1:
- select a photo
- imagePickerController(_ didFinishPickingMediaWithInfo:) -> loadData(): loads image + sizeToFit()
- viewWillAppear() -> loadData(): loads image + sizeToFit()
- viewWillLayoutSubviews(): imageView size = (3024.0, 4032.0)
- viewDidLayoutSubviews(): imageView size = (296.0, 318.0)

Case 2:
- select a photo
- viewWillAppear() -> loadData(): loads image + sizeToFit()
- viewWillLayoutSubviews(): imageView size = (3024.0, 4032.0)
- viewDidLayoutSubviews(): imageView size = (3024.0, 4032.0)
- imagePickerController(_ didFinishPickingMediaWithInfo:) -> picker.dismiss() -> loadData(): loads image + sizeToFit()

Case 3:
- select a photo
- viewWillAppear() -> loadData(): loads image + sizeToFit()
- viewWillLayoutSubviews(): imageView size = (3024.0, 4032.0)
- viewDidLayoutSubviews(): imageView size = (296.0, 300.5)
- imagePickerController(_ didFinishPickingMediaWithInfo:) -> loadData(): loads image + sizeToFit()
- viewWillLayoutSubviews(): imageView size = (3024.0, 4032.0)
- viewDidLayoutSubviews(): imageView size = (296.0, 320.5)


As you descibed, case 2 didn't resize the imageView. Since we talked about timing, I got to wondering if hopping between the image picker and the case image views was causing a layout pass to *effectively* get lost due to the timing so I added imageView.superview!.setNeedsLayout() right after the imageView.sizeToFit() and it resized correctly. (Actually even removing the sizeToFit() and just doing the setNeedsLayout() worked as well.)

I don't have better insight into the actual details but this might, at least, provide a starting point.

Steve

On Jul 24, 2018, at 1:25 PM, Rick Aurbach via Groups.Io <rlaurb@...> wrote:

Your comment about timing being an issue disturbs me since, ideally, the behavior should be consistent irrespective of "timing" since everything is funneled through a single thread. Assuming that one of your paths isn't accidentally setting imageView.image on a background thread, are you making any layout adjustments in -viewWillLayoutSubviews, for example? I have had problems where, ultimately, it was my fault but it took a long time to figure out that I was effectively trying to position something at the wrong time.
Yup. It disturbs me too.

But unless UIImagePickerController is doing something funky behind the scenes, then no, I am not doing anything on a background thread, nor am I explicitly making any changes to layout except for setting imageView.image and calling imageView.sizeToFit().

In fact, I’ve tried calling my loadData() method from
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in
self?.loadData()
}

and it doesn’t help.

What it “feels like” (whatever that means) is that there is some race condition or timing condition between code being executed in the UIImagePickerControllerDelegate’s done-handler and the layout/display subsystem for the imageView in the presenter’s view scene.

If you’re inclined to play with this, I put a sample app together yesterday afternoon. https://www.dropbox.com/s/avx6y6kkb9mpwhh/ImageViewScaling.zip?dl=0
Please note that Case #1 appears to work in the Sample App, but not in my real app. I’m currently using Case #3 in my real app. Case #2 fails in both places.

Cheers,

Rick

Join {cocoa@apple-dev.groups.io to automatically receive all group messages.