Bavan
Bavan

Reputation: 1040

ViewControllers with TextViews in UIPageViewController

I was trying to learn UIPageViewControllers and hit an Issue which I couldn't resolve. This is what I tried to do:

Has anyone experience this ever?

@interface AMPageViewController : UIPageViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>

@end

The implementation:

#import "AMPageViewController.h"

@interface AMPageViewController ()
{
    UIViewController *mainController;
    UIViewController* socController;
}
@end

@implementation AMPageViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                             bundle: nil];

    mainController = (UIViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"First"];
    socController = (UIViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"Second"];
    [self setViewControllers:@[mainController]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:NO
                  completion:nil];
    self.dataSource = self;
    self.delegate = self;
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    if (viewController == socController )
        return mainController;
    else return nil;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    if (viewController == mainController )
        return socController;
    else return nil;
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    return 2;
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
    return 0;
}


@end

If you want to download and try the project

Upvotes: 11

Views: 1636

Answers (3)

user
user

Reputation: 3456

Build target iOS-7.0.

The scrollview trick wasn't working for me. Tried to embed the textview in a scrollview through storyboard and code but no luck.

Simply delaying the call to the textview did it. Not very elegant, but its the only thing I've gotten to work so far.

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.textView becomeFirstResponder];
    });
}

Tested, working on my iPhone 5 and my ultra-slow iPhone4. Although its totally possible that whatever implementation detail enables the textview to become the responder could take longer than the set time. So keep in mind this isn't exactly bulletproof.

--EDIT--

Well... it's working on my iPhone 4 beater with a delay of 0.0000000000000001

Upvotes: 1

LombaX
LombaX

Reputation: 17364

I've investigated a lot on this problem. It seems a bug related to the internal (private) UIScrollView of the UIPageViewController. If you search on StackOverflow you will find a lot of post with this problem and no solutions...

I seems that the UITextView (which is an UIScrollView and, AFAIR, has an internal UIWebView), sends some strange message to it's superviews chain, that makes the private UIScrollView of the UIPageViewController scrolling to the top-left corner.

I would have tried to block this message using method swizzling, but this is probably not ok for AppStore. So I tried other things.

The final solution is very simple: simply, embed your UITextView inside an UIScrollView!

This is a link to your project updated

If you do so, you'll solve the problem!

Try and let me know

EDIT:

How did I arrive to this solution:

An intuition.

A lot of debug and stack traces had make me think that the problem was related to a bug in the "nesting UIScrollView" system and some messages sent from the inner view to its superview.

UITextView inherits from UIScrollView and has inside an UIWebDocumentView (private) which is another UIScrollView. During the debug I saw a lot of messages (private methods) like "relayout superview" sent to the upper UIScrollView's. So, for some reason, the inner scroll view (UIWebDocumentView?) was sending a message/event to it's superview. This message/event (probably because of a bug) was not stopping to the external UITextView, and was forwarded to the UIScrollView handled by UIPageViewController.

Embedding the UITextView inside a simple UIView was not enough, because UIView forward the message to it's superview if it can't handle. I thought: UIScrollView probably doesn't (otherwise it wouldn't simple to nest UIScrollViews), so I tried and it worked.

This is all a supposition because I stopped inspecting, I will have a more in-depth look this week.

Upvotes: 7

Prabhat Kasera
Prabhat Kasera

Reputation: 1149

you did not set before and after view controllers and also look in to first responder for socController

Upvotes: 0

Related Questions