父子导航UIViewController导致编辑表单的异常

时间:2014-05-19 12:11:45

标签: ios objective-c uiviewcontroller exc-bad-access

我在应用程序中有一个parent->子导航设置。我通过 pushViewController 功能使用导航。

-(void)loadMemosViewController:(id)sender{
    if(activeHullGuid != nil && activeHullGuid.length > 0)
    {
        NSString *storyboardName = @"MainStoryboard_iPhone1";


        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
        MemosViewController *loginVC = [storyboard instantiateViewControllerWithIdentifier:@"sid_Memos"];
        loginVC.keyReference = [[KeyValuePairIS alloc] initWithData:&controllerID:activeHullGuid];


        [self.navigationController pushViewController:loginVC animated:YES];
    }
}

用于后退导航我只使用IOS中的默认实现(即单击后退按钮)。 此设置适用于大多数情况,但最近的实施导致问题。

问题是:
我有父视图控制器名为" hullViewController"和一个孩子" memosViewController"。他们之间的导航工作。儿童不会向父母报告任何信息。 HullViewController也是一个可编辑的表单,它通过导航栏中的按钮更改编辑状态。
现在,如果我在hullViewController上更改此编辑/读取状态,则不间断工作。如果我访问子memosViewController,并返回到parent,我只能再次更改状态,然后应用程序崩溃 exc_bad_access code = 1
在使用" Zombies"我发现异常的罪魁祸首是我可能处理的子memosViewController  将Objective-C消息发送到已解除分配的MemosViewController'对象(僵尸)地址:0xdd52f10

它会在IOS内部事件中崩溃,因为在崩溃之前我的所有断点都没有被击中。

你可以看到孩子在创作过程中被实例化,我不会将其引用到其他任何东西。为什么编辑状态更改会请求子对象?

我已经尝试过了:
-declaring MemosViewController作为类变量。 (应用程序不再崩溃,但不会再改变状态) -initialising在viewDidLoad上的MemosViewController,什么都没改变。
- 仅使用类init(不通过故事板)调用子进程,加载没有UI的子进程,但结果相同。

使用ARC设置项目,因此我对处理对象的控制最小。

我一直在寻找解决方案,但没有结果。如果我访问孩子,任何帮助解决我的错误编辑将不胜感激。

更新 我还发现,当我从孩子那里回到父母那里时,参考 self.navigationItem 仍然指向孩子,并且对导航按钮的任何更新都会使应用程序崩溃。

**附加自定义ViewController,因为它可能与问题**相关

#import "UITableViewControllerEx.h"
#import "UITextFieldEx.h"
#import "UITextViewEx.h"
#import "GlobalValues.h"
#import "UITableViewEx.h"


@interface UITableViewControllerEx ()

@end

@implementation UITableViewControllerEx
UIBarButtonItem *bbi_navigateToMaster;
UIBarButtonItem *editButton;
UIButton *cmdEdit;


- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }

    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;


    [self setNavigationBackground];


    [self setApplicationTintColor];
    [self setApplicationTitleFont];

    [self setupLeftBarButtonItem];


    [self setBackButton];
}





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

//UITextFieldEx delegate to control the length of fields
- (BOOL)textField:(UITextFieldEx *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return (newLength > textField.maxLength) ? NO : YES;
}

//UITextViewEx delegate to control the length of fields
-(BOOL)textView:(UITextViewEx *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    NSUInteger newLength = [textView.text length] + [text length] - range.length;
    return (newLength > textView.maxLength) ? NO : YES;
}

//function to set left button to always pop to root controller
- (void)setBackButtonToReturnToMaster {
    UIButton *cmdHome = [[UIButton alloc] initWithFrame:CGRectMake(0,0,30,30)];
    [cmdHome setImage:[UIImage imageNamed:@"home"] forState:UIControlStateNormal];
    bbi_navigateToMaster = [[UIBarButtonItem alloc] initWithCustomView:cmdHome];
    [cmdHome addTarget:self action:@selector(backToMaster:) forControlEvents:UIControlEventTouchUpInside ];
    self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:bbi_navigateToMaster , nil];
    /*
     bbi_navigateToMaster = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:self action:@selector(backToMaster:)];
     self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:bbi_navigateToMaster , nil];
     [bbi_navigateToMaster setImage:[UIImage imageNamed:@"home"]];
     [bbi_navigateToMaster setImageInsets:UIEdgeInsetsMake(2, 2, 2, 2)];*/
}

//pop to root controller
-(void)backToMaster:(id)sender {

    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    }
    else { [self.navigationController popToRootViewControllerAnimated:YES]; }


}



//find superview element of given type
- (UIView *)findSuperViewWithClass:(Class)superViewClass uiViewToSearch:(UIView*)bottomView{

    UIView *superView = bottomView.superview;
    UIView *foundSuperView = nil;

    while (nil != superView && nil == foundSuperView) {
        if ([superView isKindOfClass:superViewClass]) {
            foundSuperView = superView;
            break;
        } else {
            superView = superView.superview;
        }
    }
    return foundSuperView;
}

-(void)setNavigationBackground{
    if ([self.navigationController.navigationBar respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)] ) {
        UIImage *image = [UIImage imageNamed:@"navigationBackground"];
        [self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];

        UIView* uv = [[UIView alloc] initWithFrame:CGRectMake(0, self.navigationController.navigationBar.frame.size.height-1,self.navigationController.navigationBar.frame.size.width, 1)];
        [uv setBackgroundColor:[GlobalValues getTintColor]];
        [self.navigationController.navigationBar insertSubview:uv atIndex:10];
    }
}

//sets the tint color of szstem items (title, szstem buttons, ...)
-(void)setApplicationTintColor {
    NSArray *ver = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    if ([[ver objectAtIndex:0] intValue] >= 7) {
        self.navigationController.navigationBar.barTintColor = [GlobalValues getTintColor];
        self.navigationController.navigationBar.tintColor = [GlobalValues getTintColor];
        self.navigationController.navigationBar.translucent = NO;
        [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];

        UIColor *color = [GlobalValues getTintColor];
        self.view.tintColor = color;
    }else {
        //self.navigationController.navigationBar.tintColor = [GlobalValues getTintColor];

        /*NSDictionary *textTitleOptions = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil];
         [[UINavigationBar appearance] setTitleTextAttributes:textTitleOptions];*/
    }
}

//sets the navigation title
-(void)setApplicationTitleFont {
    NSArray *ver = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    if ([[ver objectAtIndex:0] intValue] >= 7) {
        [self.navigationController.navigationBar setTitleTextAttributes:
         [NSDictionary dictionaryWithObjectsAndKeys:
          [UIFont fontWithName:@"HelveticaNeue-Light" size:21],
          NSFontAttributeName, [UIColor whiteColor], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil]];
    }else {
        [self.navigationController.navigationBar setTitleTextAttributes: @{
                                                                           UITextAttributeTextColor: [UIColor whiteColor],
                                                                           UITextAttributeFont: [UIFont fontWithName:@"Helvetica-Light" size:21.0f]
                                                                           }];
    }
}

-(void)setupLeftBarButtonItem{
    cmdEdit = [[UIButton alloc] initWithFrame:CGRectMake(0,0,30,30)];
    [cmdEdit setImage:[UIImage imageNamed:@"locked"]  forState:UIControlStateNormal];
    editButton = [[UIBarButtonItem alloc] initWithCustomView:cmdEdit];
    [cmdEdit addTarget:self action:@selector(setEditState) forControlEvents:UIControlEventTouchUpInside];


}

- (UIBarButtonItem *)leftBarButtonItem
{
    if (self.tableView.editing) {
        [cmdEdit setImage:[UIImage imageNamed:@"unlocked"]  forState:UIControlStateNormal];
        return editButton;
    }
    else {
        [cmdEdit setImage:[UIImage imageNamed:@"locked"]  forState:UIControlStateNormal];
        return editButton;
    }


}

-(void)updateEditButton{
    if (self.tableView.editing) {
        [cmdEdit setImage:[UIImage imageNamed:@"unlocked"]  forState:UIControlStateNormal];
    }
    else {
        [cmdEdit setImage:[UIImage imageNamed:@"locked"]  forState:UIControlStateNormal];
    }

}

-(void)setEditState{
    if (!self.tableView.editing) {
        [self setEditing:YES animated:YES];
    } else {
        [self setEditing:NO animated:YES];
    }
    [self updateEditButton];
}


 }*/

-(void) setBackButton{
    UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    UIImage *backBtnImage = [UIImage imageNamed:@"back"]  ;
    [backBtn setBackgroundImage:backBtnImage forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(goback) forControlEvents:UIControlEventTouchUpInside];
    backBtn.frame = CGRectMake(0, 0, 30, 30);
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:backBtn] ;
    self.navigationItem.leftBarButtonItem = backButton;
}

- (void)goback
{
    [self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Table view data source



#pragma mark - Table view delegate

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 0;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell.backgroundView=[[UIView alloc] initWithFrame:CGRectZero];
    cell.backgroundColor = [UIColor clearColor];
    cell.layer.backgroundColor = [UIColor clearColor].CGColor;
}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UIView *customTitleView = [ [UIView alloc] initWithFrame:CGRectMake(10, 0, 300, 44)];

    UIView *customTitleLineView = [ [UIView alloc] initWithFrame:CGRectMake(10, 43, self.view.frame.size.width -20, 0.5f)];
    customTitleLineView.backgroundColor = [GlobalValues getTintColor];


    UILabel *titleLabel = [ [UILabel alloc] initWithFrame:CGRectMake(20, 0, 300, 44)];

    titleLabel.text = [self tableView:tableView titleForHeaderInSection:section];
    titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:18];

    titleLabel.textColor = [GlobalValues getTintColor];

    titleLabel.backgroundColor = [UIColor clearColor];

    if (titleLabel.text.length != 0) {
        [customTitleView addSubview:customTitleLineView];
    }

    [customTitleView addSubview:titleLabel];

    return customTitleView;

}

@end

1 个答案:

答案 0 :(得分:0)

似乎我找到了解决问题的方法。

类UITableViewControllerEx包含设置编辑按钮的功能。类变量" UIBarButtonItem * editButton;"然后用作继承自" UITableViewControllerEx"

的所有表单上的编辑按钮

解决方案是在每个表单上实例化UIBarButtonItem,并使用本地名称(如editButtonHull)继承UITableViewControllerEx,并将其作为超类逻辑的param。

感谢@akashg建议导航栏修改可能是问题