Resolved Accessing scrollView inside of a textView delegate

Discussion in 'iOS Programming' started by 1458279, Apr 13, 2016.

  1. 1458279 Suspended

    1458279

    Joined:
    May 1, 2010
    Location:
    California
    #1
    I have a UIScrollView and contextView. I add UITextViews to it and set the delegate to self so that I can use the textViewShouldBeginEditing method. The textViewShouldBeginEditing is inside the same ViewController.m file, so the VC should be the delegate.

    The textViewShouldBeginEditing method gets called and I want to check if the keyboard is blocking the textView and scroll it up if it's being blocked.

    I want to call: [scrollView setContentOffset:CGPointMake(x, y) animated:YES]; However scrollView is not seen in textViewShouldBeginEditing.

    I've seen where KVO can be used, but I want to use the delegate methods.

    How can I gain access to the scrollView that the textView is on?
    Code:
    - (void)viewDidLoad {
    
        [superviewDidLoad];
       UIScrollView *scrollView;
        scrollView=[[UIScrollViewalloc]initWithFrame:CGRectMake(0,0,320,480)];
        scrollView.showsVerticalScrollIndicator=YES;
        scrollView.scrollEnabled=YES;
        scrollView.userInteractionEnabled=YES;
        scrollView.contentSize = CGSizeMake(320, 1200);
        scrollView.backgroundColor = [UIColorgrayColor];
        [self.viewaddSubview:scrollView];
        UIView *contentView;
        contentView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,320,480)];
        contentView.userInteractionEnabled=YES;
        [scrollView addSubview:contentView];
    
           UITextView *myNewText = [UITextViewnew];
           myNewText.delegate = (id)self;
    }
    
    - (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
        NSLog(@"BeginEditing");
    
    // This is what I want to do, it doesn't show up in Xcode, but I'm in the same module and the VC is the delegate, because this method is being called.
    // I just need to access the scrollView from in here to make it scroll.
        //[scrollView setContentOffset:CGPointMake(x, y) animated:YES];
        //[scrollView.contentOffset.x +320];
        //scroll the view up if needed
        returnYES;
    }
    
    I didn't want to create a subclass of UITextView or use KVO.
     
  2. AxoNeuron macrumors 65816

    AxoNeuron

    Joined:
    Apr 22, 2012
    Location:
    The Left Coast
    #2
    You're creating the text view but you don't seem to be adding it in to the scrollview.

    You need to set the frame of the scroll view, then use the addSubview() method of the UIScrollView.

    Another piece of advise: I don't add subviews directly to the scrollview. Instead, I add a regular UIView to the scroll view, and I call it the 'contentView'. I then add everything in to that. If you are doing things visually in the storyboard this makes it significantly easier to use auto layout.

    Objective-C
    Code:
        UITextView *textView = [[UITextView alloc] init];
        textView.delegate = self;
        textView.frame = CGRectMake(20, 20, self.scrollView.frame.size.width - 40, self.scrollView.frame.size.width - 40);
        scrollView.addSubview(textView);  
    
    Swift
    Code:
        let textView = UITextView();
        textView.delegate = self;
        textView.frame = CGRectMake(20, 20, self.scrollView.frame.size.width - 40, self.scrollView.frame.size.width - 40);
        scrollView.addSubview(textView);
    
     
  3. 1458279, Apr 13, 2016
    Last edited: Apr 13, 2016

    1458279 thread starter Suspended

    1458279

    Joined:
    May 1, 2010
    Location:
    California
    #3
    Ok, I didn't post all the code.

    Code:
    - (void)viewDidLoad {
        [superviewDidLoad];
        // make a scrollView
        UIScrollView *scrollView;
        scrollView=[[UIScrollViewalloc]initWithFrame:CGRectMake(0,0,320,480)];
        scrollView.showsVerticalScrollIndicator=YES;
        scrollView.scrollEnabled=YES;
        scrollView.userInteractionEnabled=YES;
        scrollView.contentSize = CGSizeMake(320, 1200);
        scrollView.backgroundColor = [UIColorgrayColor];
        [self.viewaddSubview:scrollView];
        // make a UIView
        UIView *contentView;
        contentView=[[UIViewalloc]initWithFrame:CGRectMake(0,0,320,480)];
        contentView.userInteractionEnabled=YES;
        [scrollView addSubview:contentView];
        NSMutableArray *dataArray = [NSMutableArrayarray];
        NSMutableArray *labelArray = [NSMutableArrayarray];
        int leftData = 125;
        int leftLabel = 20;
        int height = 30;
        int length = 170;
        int labelLength = 90;
        int startTop = 0;
        int spacer = 15;
        for (int i = 0; i<30; i++){
            UITextView *myNewText = [UITextViewnew];
            startTop = startTop + height + spacer;
            myNewText.frame = CGRectMake(leftData, startTop, length, height);
            myNewText.text = [NSStringstringWithFormat:@"Item # %d StartTop: %d", i, startTop];
    
            // set the delegate so that we can control the keyboard events
            myNewText.delegate = (id)self;
            [dataArray addObject:myNewText];
            // make the label
            UILabel *myNewLabel = [UILabelnew];
            myNewLabel.frame = CGRectMake(leftLabel, startTop, labelLength, height);
            myNewLabel.text = [NSStringstringWithFormat:@"Item # %d StartTop: %d", i, startTop];
            [labelArray addObject:myNewLabel];
        }
    
        for (int i = 0; i<30; i++){
            [contentView addSubview:labelArray[i]];
            [contentView addSubview:dataArray[i]];
        }
    }
    
    - (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
        NSLog(@"BeginEditing");
    /*
    
    this method is called
    However, I can't call the scrollView or contentView
    
    */
    
        //[scrollView setContentOffset:CGPointMake(x, y) animated:YES];
        //[scrollView.contentOffset.x +320];
        //scroll the view up if needed
        return YES;
    }
    
    
    - (BOOL)textViewShouldEndEditing:(UITextView *)textView{
        NSLog(@"EndEditing");
        //hide the keyboard
        return YES;
    }
    
    
    The two methods (textvView delegates) but I can't call scrollView or contentView.

    You should be able to put all this code into one VC and run it. I'm pretty sure it has to do with adding on an interface from the VC into the textView.

    Mine are standard:
    Code:
    @interfaceViewController ()
    
    @end
    
    @implementation ViewController
    
    Wouldn't I need to tell the VC that it can get messages back from the textView delegates?
    --- Post Merged, Apr 13, 2016 ---
    Here's a link to what someone else did to handle this problem. He uses NSNotifications, but some say that's not the best approach. Delegates are supposed to be the proper way to do it.

    https://spin.atomicobject.com/2014/...cial&utm_campaign=uiscrollview-autolayout-ios

    I'll also need to kill the keyboard afterwards.

    The behavior I'm looking for is the same as seen in Apple's "contacts" app.

    SO has a solution, but it still doesn't use delegates.

    http://stackoverflow.com/questions/...ew-up-when-keyboard-appears/26237038#26237038

    This is really an object (instance) visibility issue. I can's see the object that's created inside the same module. That should mean it has to go thru the proper channels (interface / protocol). Just not sure how to set it up.

    Here's one SO member's suggestion. It looks good, but requires a pretty high version of iOS and still doesn't answer my question.
    https://github.com/hackiftekhar/IQKeyboardManager
     
  4. 1458279 thread starter Suspended

    1458279

    Joined:
    May 1, 2010
    Location:
    California
    #4
    Ok, well it looks like I found a cheap work around.

    I don't think it's the right way to do it, but it does work.

    I changed the scope of the subview and now the delegate can see it using _scrollView.

    There has to be a better way.

    Code:
    @interface ViewController()
    @property UIScrollView *scrollView;
     
  5. AxoNeuron macrumors 65816

    AxoNeuron

    Joined:
    Apr 22, 2012
    Location:
    The Left Coast
    #5
    It could be because you're not maintaining a strong reference to the text view and it might be getting deallocated along with its delegate property.
     
  6. 1458279 thread starter Suspended

    1458279

    Joined:
    May 1, 2010
    Location:
    California
    #6
    Ok, that sound reasonable. The scrollview, contextview, and textviews were all created on the fly, so they probably default to weak and can't be seen after control leaves the method.

    So I don't know how to make a var strong without putting in the @Property and that seemed to fix it.

    So as far as scope goes, if it's in the @Property of the .m, it's private to the methods in that .m. If it's in the @Property of the .h, it's public to all that create an instance.

    If that's the case, it's my fault for screwing up the scope.
     

Share This Page