我在应用程序中有一个父->子导航设置。我使用导航通过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,并回到父,我只能再次改变状态,然后应用程序崩溃与exc_bad_access code=1。在与"僵尸"分析后,我发现例外的罪魁祸首是我可能处置的子memosViewController。
一个Objective-C消息被发送到一个被释放的'MemosViewController'对象(僵尸)在地址:0xdd52f10
似乎会在IOS内部事件中崩溃,因为在崩溃之前我的断点都没有被击中。
A你可以看到子节点在创建过程中被实例化了,我没有引用它。为什么编辑状态更改请求子对象?
我已经试过了:
将MemosViewController声明为一个类变量。(应用程序不再崩溃,但不再改变状态)。
-在viewDidLoad上初始化MemosViewController,没有改变任何东西。
-只调用子类init(不通过storyboard),加载没有UI的子,但结果是一样的。
项目是用ARC设置的,所以我对对象的处理有最小的控制。
我一直在寻找一个解决方案,很长一段时间,没有结果。如果我去看望孩子,任何帮助解决我编辑错误的人都将不胜感激。
我还发现,当我从child返回到parent时,引用self。navigationItem仍然指向child,任何对导航按钮的更新都会导致应用程序崩溃。
**附加自定义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
看来我找到解决问题的办法了。
UITableViewControllerEx类包含设置编辑按钮的功能。类变量"UIBarButtonItem *editButton;"然后在所有继承自"UITableViewControllerEx"的表单上用作编辑按钮解决方案是在继承UITableViewControllerEx与本地名称(如editButtonHull)的每个表单上实例化UIBarButtonItem,并作为参数给予超类的逻辑。
感谢@akashg的建议,导航栏的修改可能是问题所在