简体   繁体   中英

.xib file init UIView on ViewController User interaction not working

I have a Storyboard with a ViewController using a navigation controller and a TabBarController. I have been trying to resolve this for a few days now.

The problem:

Very often user I cannot interact with the view... that includes scrolling, tapping the text field and any buttons being pressed. Something is stopping me from interacting with the newly loaded UIView.

I have tried using the init method and tried using the init with frame method. The view is showing all the time though so maybe this is not the problem.

I have tried remaking the whole xib file, re-coding the .h and .m files and re-attaching all the outlets on the view.

I am stuck

In the view controller I am loading a UIView with separate .xib file and separate .h and .m file.

This is how I am doing it:

in my ViewController in the viewDidAppear method:

   int startPos = self.navigationController.navigationBar.frame.size.height+20;
    inviteFriendsView = [[InviteFriendsEmailAddressesView alloc] init];
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"InviteFriendsEmailAddressesView" owner:self options:nil];
    inviteFriendsView = (InviteFriendsEmailAddressesView*)[nib objectAtIndex:0];

    [self.view addSubview:inviteFriendsView];
    [inviteFriendsView setDelegate:self];
    [inviteFriendsView setUserInteractionEnabled:YES];
    [inviteFriendsView customizeView];
    [inviteFriendsView setAlpha:0.0];
    [inviteFriendsView setY:startPos];

IBAction method for showing the view:

- (IBAction)inviteFriendsButtonTapped:(id)sender {
    [self.view bringSubviewToFront:inviteFriendsView];
    [inviteFriendsView setUserInteractionEnabled:YES];
    [inviteFriendsView animate];
}

Here is the .h and .m files which show how I am loading the view:

InviteFriendsEmailAddressesView.h

#import <UIKit/UIKit.h>
#import "InviteFriendsViewDelegate.h"
#import "InviteFriendsNetworkContollerDelegate.h"
#import "InviteFriendsNetworkController.h"

@interface InviteFriendsEmailAddressesView : UIView <UITextFieldDelegate, UITextViewDelegate, InviteFriendsNetworkContollerDelegate, UIGestureRecognizerDelegate>

- (void) customizeView;
- (void) animate;

@property BOOL visible;
@property int y;
@property id<InviteFriendsViewDelegate> delegate;
@property (strong, nonatomic) NSArray *emails;
@property int height;

@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
@property (weak, nonatomic) IBOutlet UILabel *inviteFriendsTitle;
@property (weak, nonatomic) IBOutlet UILabel *inviteFriendsDescription;
@property (weak, nonatomic) IBOutlet UITextField *userEmailTextField;
@property (weak, nonatomic) IBOutlet UIImageView *userEmailImageView;
@property (weak, nonatomic) IBOutlet UIButton *addFriendsButtonOutlet;
@property (weak, nonatomic) IBOutlet UILabel *emailAddressesDescription;
@property (weak, nonatomic) IBOutlet UIImageView *viewBackground;

@property (weak, nonatomic) IBOutlet UIView *emailAddressesCellBackground;
@property (weak, nonatomic) IBOutlet UILabel *emailAddressCellTextUILabel;
@property (weak, nonatomic) IBOutlet UIButton *emailAddressCancelButton;
@property (weak, nonatomic) IBOutlet UIView *emailAddressView;

@property (weak, nonatomic) IBOutlet UIButton *sendInviteButtonOutlet;
@property (weak, nonatomic) IBOutlet UIButton *progressSoFarButtonOutlet;

@property (weak, nonatomic) IBOutlet UIScrollView *viewScrollView;

@property (strong, nonatomic) InviteFriendsNetworkController *inviteFriendsNetworkController;

#pragma mark - UITextFieldDelegate Methods

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;        // return NO to disallow editing.
- (void)textFieldDidBeginEditing:(UITextField *)textField;           // became first responder
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;          // return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
- (void)textFieldDidEndEditing:(UITextField *)textField;             // may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;   // return NO to not change text

- (BOOL)textFieldShouldClear:(UITextField *)textField;               // called when clear button pressed. return NO to ignore (no notifications)
- (BOOL)textFieldShouldReturn:(UITextField *)textField;              // called when 'return' key pressed. return NO to ignore.

@end

InviteFriendsEmailAddressesView.m

#import "InviteFriendsEmailAddressesView.h"
#import "UIFont+Theme.h"
#import "UIColor+Theme.h"
#import "UIImage+Theme.h"

@implementation InviteFriendsEmailAddressesView

@synthesize emails;
@synthesize visible;
@synthesize y;
@synthesize delegate;
@synthesize height;
@synthesize inviteFriendsNetworkController;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"InviteFriendsEmailAddressesView" owner:self options:nil];
        self = [nib objectAtIndex:0];
    }
    return self;
}

- (id) init {

//    self = [[[NSBundle mainBundle] loadNibNamed:@"InviteFriendsEmailAddressesView" owner:self options:nil] objectAtIndex:0];


    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(themeChanged)
                                                 name:@"New Theme Applied"
                                               object:nil];

    NSUserDefaults *properties = [NSUserDefaults standardUserDefaults];
    if([properties objectForKey:@"emails"]){
        emails = [properties objectForKey:@"emails"];
    } else {
        emails = [[NSArray alloc] init];
    }

    [self.viewScrollView setDelegate:self];

    [self.activityIndicator setHidden:YES];

    [self.viewScrollView setScrollEnabled:YES];


    //CGRect newScrollViewFrame = self.viewScrollView.frame;
    //newScrollViewFrame.origin.y = 0;
    //newScrollViewFrame.size.height = keyWindowFrame.size.height;
    //[self.viewScrollView setFrame:newScrollViewFrame];


    // get the size of the screen and set the content size to the size of the screen plus the bottom bar.
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    screenRect.size.height = screenRect.size.height-200;
    [self.viewScrollView setContentSize:CGSizeMake(screenRect.size.width, 1200)];
    [self.viewScrollView setFrame:screenRect];
    [_viewScrollView setScrollEnabled:YES];
    // 100 is the size of the tool bar.



    [self updateEmailListView];

    self.userEmailTextField.delegate = self;

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureCaptured:)];
    [self.viewScrollView addGestureRecognizer:singleTap];

    //reactionNetworkController
    inviteFriendsNetworkController = [[InviteFriendsNetworkController alloc] init];
    [inviteFriendsNetworkController setDelegate:self];

    return self;
}


/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

- (void) updateEmailListView {

    // With some valid UIView *view:
    for(UIView *subview in [self.emailAddressView subviews]) {
        if([subview isHidden] == NO){
            [subview removeFromSuperview];
        }
    }

    // if we have email addresses in the email address list.
    if([emails count] > 0){
        // display and populate scrollview with email addresses.
        for(int i =0; i < [emails count]; i++){
            // every other view set it white so that it creates a grey, white, grey, white pattern.
            if(i % 2 == 0){
                [self.emailAddressesCellBackground setBackgroundColor:[UIColor whiteColor]];
            } else {
                [self.emailAddressesCellBackground setBackgroundColor:[UIColor grayColor]];
            }

            // generate our background
            UIView *newBackground = [[UIView alloc] initWithFrame:CGRectMake(
                                                                             self.emailAddressesCellBackground.frame.origin.x,
                                                                             self.emailAddressesCellBackground.frame.origin.y+self.emailAddressesCellBackground.frame.size.height*i,
                                                                             self.emailAddressesCellBackground.frame.size.width,
                                                                             self.emailAddressesCellBackground.frame.size.height)];
            [newBackground setTag:i];


            // generate our email addresses label.
            UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectMake(
                                                                          self.emailAddressCellTextUILabel.frame.origin.x,
                                                                          self.emailAddressCellTextUILabel.frame.origin.y+self.emailAddressesCellBackground.frame.size.height*i,
                                                                          self.emailAddressCellTextUILabel.frame.size.width,
                                                                          self.emailAddressCellTextUILabel.frame.size.height)];
            [newLabel setTag:i];
            [newLabel setText:[emails objectAtIndex:i]];




            // generate the delete button and add a target for the selector when it is pressed.
            UIButton *newButton = [[UIButton alloc] initWithFrame:CGRectMake(
                                                                             self.emailAddressCancelButton.frame.origin.x,
                                                                             self.emailAddressCancelButton.frame.origin.y+self.emailAddressCancelButton.frame.size.height*i,
                                                                             self.emailAddressCancelButton.frame.size.width,
                                                                             self.emailAddressCancelButton.frame.size.height)];
            [newButton setTag:i];
            [newButton addTarget:self  action:@selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchDown];
            [newButton setImage:self.emailAddressCancelButton.imageView.image forState:UIControlStateNormal];

            // attach the new views to the scrollview
            [self.emailAddressView addSubview:newBackground];
            [self.emailAddressView addSubview:newButton];
            [self.emailAddressView addSubview:newLabel];





        }

        [self.emailAddressView setHidden:NO];
    }
    // if we do not have any emails added yet.
    else {
        [self.emailAddressView setHidden:YES];
    }
}

- (void) deleteButtonPressed:(id)sender{
    int tag = [sender tag];
    NSLog(@"delete button pressed with sender tag: %i", [sender tag]);
    NSMutableArray *mutableEmails = [emails mutableCopy];
    [mutableEmails removeObjectAtIndex:tag];
    emails = mutableEmails;
    NSUserDefaults *properties = [NSUserDefaults standardUserDefaults];
    [properties setObject:emails forKey:@"emails"];
    [properties synchronize];
    [self updateEmailListView];

}

- (void) customizeView{
    [self.inviteFriendsTitle setFont:[UIFont themeFontNamed:@"viewTitleFont" ofSize:18]];
    [self.viewBackground setImage:[UIImage themeImageNamed:@"backgroundImage"]];
    [self.inviteFriendsDescription setFont:[UIFont themeFontNamed:@"normalTextFont" ofSize:13]];
    [self.emailAddressesDescription setFont:[UIFont themeFontNamed:@"normalTextFont" ofSize:13]];


    if(height == 0 &&[delegate respondsToSelector:@selector(getHeight)]){
        height = [delegate getHeight];
        [self setFrame:CGRectMake(0,
                                  -height,
                                  self.frame.size.width,
                                  height)];
    }

}


- (void) animate{
    if(visible == YES){
        [self slideOut];
        visible = NO;
    }
    else{
        [self customizeView];
        [self slideIn];
        visible = YES;
    }
    NSLog(@"is user interaction enabled in InviteFriendsView?: %hhd", self.isUserInteractionEnabled);
}


- (void) themeChanged {
    [self customizeView];
}



- (void) slideIn {
    NSLog(@"Slide in");

    [[self superview]  setUserInteractionEnabled:NO];

    [self.activityIndicator setAlpha:1.0];
    [self.activityIndicator startAnimating];

    self.alpha = 1.0;


    [UIView animateWithDuration:0.5
                     animations:^{
                         [self setFrame:CGRectMake(0,
                                                   y,
                                                   self.frame.size.width,
                                                   height)];
                     }
                     completion:^(BOOL finished) {
                         NSLog(@"DID finish slide in");
                     }];

}

- (void) slideOut{
    NSLog(@"Slide out");

    if([delegate respondsToSelector:@selector(getY)]){
        y = [delegate getY];
    }

    [self setViewScrollView:self.viewScrollView];
    [self setUserInteractionEnabled:YES];
    [self.viewScrollView setUserInteractionEnabled:YES];
    [self.viewScrollView setScrollEnabled:YES];
    [self.viewScrollView setScrollsToTop:YES];



    [UIView animateWithDuration:0.5
                     animations:^{
                         [self setFrame:CGRectMake(0,
                                                   -height+y,
                                                   self.frame.size.width,
                                                   height)];
                     }
                     completion:^(BOOL finished) {
                         self.alpha = 0.0;
                         [[self superview]  setUserInteractionEnabled:YES];
                     }];
}

#pragma mark - UITextFieldDelegate Methods

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    return true;
}
// return NO to disallow editing.

- (void)textFieldDidBeginEditing:(UITextField *)textField{

}
// became first responder

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
    return true;
}
// return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end

- (void)textFieldDidEndEditing:(UITextField *)textField{

}
// may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    return true;
}
// return NO to not change text

- (BOOL)textFieldShouldClear:(UITextField *)textField{
    return true;
}
// called when clear button pressed. return NO to ignore (no notifications)

- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [self addFriendToInviteButtonPressed:self];
    [textField setText:@""];
    return true;
}
// called when 'return' key pressed. return NO to ignore.


#pragma mark - Button Action Pressed Methods

- (IBAction)addFriendToInviteButtonPressed:(id)sender {
    NSMutableArray *mutableEmails = [emails mutableCopy];
    [mutableEmails addObject:self.userEmailTextField.text];
    NSLog(@"mutableEmails: %@", mutableEmails);

    NSUserDefaults *properties = [NSUserDefaults standardUserDefaults];
    [properties setObject:mutableEmails forKey:@"emails"];
    [properties synchronize];
    emails = mutableEmails;
    [self updateEmailListView];
    [self.userEmailTextField setText:@""];
    [self.userEmailTextField resignFirstResponder];
}

- (IBAction)sendInviteButtonPressed:(id)sender {
    // send a POST request to the server with the emails.
    NSString *stringEmails = [[emails valueForKey:@"description"] componentsJoinedByString:@""];
    NSLog(@"stringEmails: %@", stringEmails);
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    int site = 0;
    if([[defaults objectForKey:@"Theme"] isEqualToString:@"BOMG"]){
        site = 1;
    }

    [self.inviteFriendsNetworkController inviteFriendsWithAddressList:emails AndSite:site];
}

- (IBAction)progressButtonPressed:(id)sender {
}

#pragma mark - InviteFriendsNetworkControllerDelegateMethods

- (void) didSendAddressList:(NSDictionary *)response{

}

- (void) failedTosendAddressList{

}

#pragma mark - UIGestureRecognizerDelegate methods

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
    [self.userEmailTextField resignFirstResponder];
}


@end

This might be an issue with the frames, where the controls are rendered (partially) outside the superview frame. This can be caused by invalid autoresizing masks or autolayout constraints.

To debug this you can set 'clip subviews' to YES for the relavant controls. When you see some of the controls are not visible anymore (or just partially), check the frames and resizingmasks or constraints of the superview.

Check whether the view controller is added in the build phase compile source. If you not added the view controller in the compiler source (if its not added automatically) it will some effect in xib integration.

I found the answer. I had to comment out the line

[[self superview]  setUserInteractionEnabled:NO];

inside slideIn(){..}

So disabling user interaction for the superview would of course stop all user interaction from happening in a subview (such as the scrollview).

Oh dear.

Thanks guys!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM