ios - OC编程时遇到:whose view is not in the window hierarchy!怎么办
巴扎黑
巴扎黑 2017-04-17 17:43:09
0
1
698

做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];

}

  • (void)viewDidLoad {

    [super viewDidLoad];
    
    self.persons=[[NSMutableArray alloc]initWithCapacity:100];
    
    
    }
    
  • (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.

    }

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
    }

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.persons.count;
    }

  • (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString * cellId=@"A";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId ];
    if (cell==nil) {

       cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];

    }
    WKPerson *p=self.persons[indexPath.row];

    cell.textLabel.text=p.name;

    cell.detailTextLabel.text=p.tel;

    return cell;
    }

巴扎黑
巴扎黑

全部回复(1)
PHPzhong

在willdisapper里 self 将要销毁,所以你不能 present,如果你用的是导航的话,建议自定义返回按钮(leftButtonItem),在返回按钮的方法里,进行判断是弹出 alartView还是执行返回 效果

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板