search

Home  >  Q&A  >  body text

ios - OC编程时遇到:whose view is not in the window hierarchy!怎么办

做OC编程基础练习:通讯录,在新建联系人时为了避免在没有保存就返回上一页,所以设计一个警告控件,但是却无法触发?错误提示是:
Warning: Attempt to present <UIAlertController: 0x7fae087eac40> on <NewPersonItemViewController: 0x7fae08569b90> whose view is not in the window hierarchy!

新建联系人类:
.h

请#import <UIKit/UIKit.h>
//创建一个协议注意:在该类里写这个协议并不意味着该类继承了协议
@protocol PassValue
-(void)addName:(NSString*)name andAddTel:(NSString*)tel;

@end
@interface NewPersonItemViewController : UIViewController
{
    //创建一个布尔标记以确定是否已存入数据
    BOOL flag;
}
@property(strong,nonatomic)UITextField *name;
@property(strong,nonatomic)UITextField *tel;
//这里这个属性继承了该协议
@property(weak,nonatomic)id<PassValue> delegate;

@end

.m:问题出现在:-(void)viewWillDisappear:(BOOL)animated方法执行上

#import "NewPersonItemViewController.h"

@interface NewPersonItemViewController ()

@end

@implementation NewPersonItemViewController
@synthesize name,tel;

-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    
    self=[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        //标记一个标题
self.title=@"添加新联系人";
        self.view.backgroundColor=[UIColor whiteColor];
        //在导航栏上创建一个完成按钮,用于确定编辑结束
        //注意:只能先创建一个特殊的按钮,然后赋值给导航视图控制器的右按钮;
        UIBarButtonItem *BarButton=[[UIBarButtonItem alloc]initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(DoneTap:)];
        self.navigationItem.rightBarButtonItem=BarButton;
        
        
        //创建两个文本框:分别是姓名和电话 中间加一条线
        name=[[UITextField alloc]initWithFrame:CGRectMake(10, 74, 300, 40)];
        name.placeholder=@"姓名";
        name.backgroundColor=[UIColor greenColor];
        [self.view addSubview:name];
        //加一条分割线
        UIView * line1=[[UIView alloc]initWithFrame:CGRectMake(0, 124, 320, 2)];
        line1.backgroundColor=[UIColor  blackColor];
        [self.view addSubview:line1];
        //电话文本框
        tel=[[UITextField alloc]initWithFrame:CGRectMake(10, 134, 300, 40)];
        tel.placeholder=@"电话";
        tel.backgroundColor=[UIColor greenColor];
        [self.view addSubview:tel];
        //加一条分割线
        UIView * line2=[[UIView alloc]initWithFrame:CGRectMake(0, 184, 320, 2)];
        line2.backgroundColor=[UIColor  blackColor];
        [self.view addSubview:line2];
        //设计:当使用对应文本框时的return时关闭键盘:该方法并不需要使用resignFirstResponder
        [name addTarget:self action:@selector(onExit:) forControlEvents:UIControlEventEditingDidEndOnExit];
        [tel addTarget:self action:@selector(onExit:) forControlEvents:UIControlEventEditingDidEndOnExit];
        //使两个文本框输入时,关闭自动首字母大写
        name.autocapitalizationType=UITextAutocapitalizationTypeNone;
        tel.autocapitalizationType=UITextAutocapitalizationTypeNone;
        
        NSLog(@"1");
        }

    return self;
}
- (void)viewDidLoad {
    //[super viewDidLoad];
    NSLog(@"2");
    
}
//当视图即将载入时将flag设置为假;
-(void)viewWillAppear:(BOOL)animated{
    flag=NO;
    NSLog(@"3");
}
-(void)viewDidAppear:(BOOL)animated{
    
   NSLog(@"4");
}

***//问题貌似出在这里:***
//当时图即将消失时也将flag设置为假
-(void)viewWillDisappear:(BOOL)animated{
    //因为点击完成时
    
    if(!flag){
        // if (name.text!=nil||tel.text!=nil ) {
        //当填写了内容时,退出当前视图时出现警告提示
        
        UIAlertController * a=[UIAlertController alertControllerWithTitle:@"注意了!!" message:@"大爷的你还没保存!" preferredStyle: UIAlertControllerStyleActionSheet];
        UIAlertAction *ac1=[UIAlertAction actionWithTitle:@"你知道到了么?" style:UIAlertActionStyleDefault handler:nil];
        
        [a addAction:ac1];
        
        [self presentViewController:a animated:YES completion:nil];
        //}
        NSLog(@"5");
        return ;
    }
}



//并不需要什么语句触摸return后就可以使键盘退出
-(void)onExit:(UITextField*)sender{
   
    NSLog(@"6");
}
/*
  当点击“完成”时:
  1.验证数据;
 */
-(void)DoneTap:(UIBarButtonItem *)sender{
   
   //获得文本框中的文本内容

    NSString *strName=name.text;
    NSString *strTel=tel.text;
   //剔除文本两端空格
   //从NSCharacterSet的集合中得到whitespaceCharacterSet;
    strName=[strName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    
    strTel=[strTel stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
  
  //判断文本框内是为空字符串
    
    
    //   strName==nil
    if ([strName isEqualToString:@""]) {
        
        //使用警报
        UIAlertController * alert=[UIAlertController alertControllerWithTitle:@"你大爷的请注意!" message:@"你得整点内容啊!" preferredStyle:UIAlertControllerStyleAlert];
      
        UIAlertAction * alertAction=[UIAlertAction actionWithTitle:@"你知道了么?" style:UIAlertActionStyleDefault handler:nil];
        
        [alert addAction:alertAction];
        
        [self presentViewController:alert animated:YES completion:nil];
        //为了使程序更加人性化,此时还应该将清空当前字符串,然后所的焦点(就是将光标自动点入当前文本框内)
          //注意:这里包括你输入的空格,将光标指向最左端
        name.text=@"";
        
        [name becomeFirstResponder];
        
        //因为这里如果是空字符串,就不用验证下一个,需要显示这里的警报,并退出
        return;
    }
    
    if ([strTel isEqualToString:@""]) {
        
        UIAlertController * alert=[UIAlertController alertControllerWithTitle:@"你娘的请注意" message:@"你得整点内容啊!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction * alertAction1=[UIAlertAction actionWithTitle:@"你晓得了么?" style: UIAlertActionStyleDefault handler:nil];
        [alert addAction:alertAction1];
        
        [self presentViewController:alert animated:YES completion:nil];
        //为了使程序更加人性化,此时还应该将清空当前字符串,然后所的焦点(就是将光标自动点入当前文本框内)
        //注意:这里包括你输入的空格,将光标指向最左端
        tel.text=@"";
        [tel becomeFirstResponder];
        //因为这里如果是空字符串,就不用验证下一个,需要显示这里的警报,并退出
        return;
    }
    
 //执行协议方法:存入数据:由于将代理指向RootTableViewController类的对象,在这里发送消息
 //就等于在RootTableViewController发送消息
    
    [self.delegate addName:strName andAddTel:strTel];
    
    //存入数据应该flag设置为真
    flag=YES;
    
 //存入数据后应该返回至上一层页面(实际上是退回根视图对象上):注意要使用导航的栈退出的方法
    [self.navigationController popViewControllerAnimated:YES];
    NSLog(@"7");
    
}

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

补充表格式图控制器代码(貌似没有出错)

.h:

请
#import "WKPerson.h"
#import <UIKit/UIKit.h>
#import "NewPersonItemViewController.h"
@interface RootTableViewController : UITableViewController<PassValue>
@property(strong,nonatomic)NSMutableArray * persons;
@end输入代码
.m:

import "RootTableViewController.h"

import "NewPersonItemViewController.h"

@interface RootTableViewController ()

@end

@implementation RootTableViewController

-(instancetype)initWithStyle:(UITableViewStyle)style{

self=[super initWithStyle:style];
if (self) {
    //在这里可以设置导航栏的颜色和样式
    [[UINavigationBar appearance] setBarTintColor:[UIColor blueColor]];
   //设置导航栏上的按钮的颜色;
    [[UINavigationBar appearance] setTintColor:[UIColor redColor]];
    
    //当使用导航视图时这里可以为导航视图设置标题
    self.title=@"通讯录";
   //为导航栏设计一个“+”按钮
    UIBarButtonItem * BarButtonItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addTap:)];
    //将设计的按钮指向导航栏的右按钮上;
    self.navigationItem.rightBarButtonItem=BarButtonItem;
    
    
    
    
    
}

return self;

}

-(void)addTap:(UIBarButtonItem *)sender{
//使用导航栏的推栈的方式,展示“添加联系人”的页面

NewPersonItemViewController * new=[[NewPersonItemViewController alloc]init];
//将新增联系人视图的代理指向当前类的对象
new.delegate=self;


//注意:因为该视图是导航视图的根视图,且视图控制器是本身就含有导航视图控制器的属性
//所以,这里必须使用当前类中的导航视图属性,利用推栈的方式加入新视图
[self.navigationController pushViewController:new animated:YES];

}
//实现协议
-(void)addName:(NSString )name andAddTel:(NSString )tel{
//因为有两个参数所以,最好将这两个参数存入一个类中,再将该类的对象存入一个数组
//注意数据添加了就应该将视图重载数据,以此让数据和视图同步

WKPerson *p=[[WKPerson alloc]init];
p.name=name;
p.tel=tel;
//哪里增修改了数据哪里重载数据
[self.persons addObject:p];

[self.tableView reloadData];

}

巴扎黑巴扎黑2773 days ago697

reply all(1)I'll reply

  • PHPz

    PHPz2017-04-17 17:45:09

    In willdisapper, self will be destroyed, so you cannot present. If you are using navigation, it is recommended to customize the return button (leftButtonItem). In the return button method, judge whether to pop up the alartView or execute the return effect

    reply
    0
  • Cancelreply