thiagoperes / IDMPhotoBrowser

Photo Browser / Viewer inspired by Facebook's and Tweetbot's with ARC support, swipe-to-dismiss, image progress and more
MIT License
2.71k stars 642 forks source link

isDisplayingPageForIndex: creates 2 pages for a single index #163

Open NicosKaralis opened 9 years ago

NicosKaralis commented 9 years ago

I have in my code a view collection that have each one image. When the user selects the collection cell I open a IDMPhotoBrowser and set its InitialPageIndex to match the selected cell.

This is the code I'm using to display the IDMPhotoBrowser

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.deselectItemAtIndexPath(indexPath, animated: false)

    guard let photosArray = GalleryManager.sharedInstance.images else {
      return
    }

    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! GalleryCollectionViewCell
    let galleryBrowser = IDMPhotoBrowser(photos: photosArray, animatedFromView: cell)

    galleryBrowser.displayCounterLabel = true
    galleryBrowser.displayArrowButton = true
    galleryBrowser.displayActionButton = true
    galleryBrowser.useWhiteBackgroundColor = true

    galleryBrowser.leftArrowImage          = UIImage(named: "PhotoBrowser_arrowLeft")
    galleryBrowser.rightArrowImage         = UIImage(named: "PhotoBrowser_arrowRight")
    galleryBrowser.leftArrowSelectedImage  = UIImage(named: "PhotoBrowser_arrowLeftSelected")
    galleryBrowser.rightArrowSelectedImage = UIImage(named: "PhotoBrowser_arrowRightSelected")
    galleryBrowser.doneButtonImage         = UIImage(named: "PhotoBrowser_doneButton")
    galleryBrowser.view.tintColor          = UIColor.orangeColor()
    galleryBrowser.progressTintColor       = UIColor.orangeColor()
    galleryBrowser.trackTintColor          = UIColor(white: 0.8, alpha: 1)

    galleryBrowser.delegate = self

    galleryBrowser.setInitialPageIndex( UInt(indexPath.row) )

    presentViewController(galleryBrowser, animated: true, completion: nil)
  }

img_1546 img_1547

As you can see on the previous shots, it works fine to open a image. But when I try to drag the initial image to dismiss, I can see a second image in the background. This only happens on the InitialPageIndex image. If I drag from the initial image to any other, the new image presented will not have the "after image", but if I go back to the initial image it has the "after image"

img_1548

Debugging the view hierarchy I found that the IDMPhotoBrowser has 2 IDMZoomingScrollView assigned to index 1 (or the selected index)

One is created from:

-[IDMPhotoBrowser setInitialPageIndex:]
  -[IDMPhotoBrowser tilePages]
    -[IDMPhotoBrowser configurePage:forIndex:]

And the other is from:

-[IDMPhotoBrowser viewWillAppear:]
  -[IDMPhotoBrowser reloadData]
    -[IDMPhotoBrowser performLayout]
      -[IDMPhotoBrowser tilePages]
        -[IDMPhotoBrowser configurePage:forIndex:]

Inspecting even more I found that the method isDisplayingPageForIndex: return false if you set the InitialPageIndex before the view is rendered.

Can someone confirm this is intended? Because I don't want to make the view appear first to then change the image displayed.

I've tried to overload the isDisplayingPageForIndex: method, but I'm using swift and I could not find a way to do it.

NicosKaralis commented 9 years ago

Found a solution, the problem happens because isViewLoaded returns YES and the PhotoBrowser assumes it is being presented.

I created a subclass and override the isViewLoaded because the vars _initalPageIndex and _currentPageIndex are internal and we can't alter them on a subclass.

This is a very dirty code and I will not put in production.

IDMPhotoBrowserFix.h

#import <IDMPhotoBrowser/IDMPhotoBrowser.h>

@interface IDMPhotoBrowserFix : IDMPhotoBrowser {
  BOOL temporaryDisableViewLoaded;
}

-(void) mySetInitialPageIndex:(NSInteger)index;

@end

IDMPhotoBrowserFix.m

#import "IDMPhotoBrowserFix.h"

@implementation IDMPhotoBrowserFix

-(BOOL)isViewLoaded {
  if (temporaryDisableViewLoaded) {
    return NO;
  } else {
    return [super isViewLoaded];
  }
}

-(void) mySetInitialPageIndex:(NSInteger)index {
  temporaryDisableViewLoaded = YES;
  [super setInitialPageIndex:index];
  temporaryDisableViewLoaded = NO;
}

@end

Just a quick help, if you make a public library like this you have to assume people want to customise the code to their needs. When you have the time, consider moving the variables that can change appearance (colors, fonts, sizes, etc) to the .h, you can still mark it as private and we can't change on your class, but we can change on subclasses we create.