UITableView的原理,编辑及UIViewController的建立

来源:互联网 发布:源码大师官网 编辑:程序博客网 时间:2024/06/16 15:45

一, UITableView原理

1.appDelegate的协议方法中,创建应用程序的窗口对象

2.创建MainViewController对象
MainViewController *mainVC= [[MainViewController alloc] init];

3.创建导航控制器并将第二步创建的视图控制器对象作为导航控制器的根视图控制器
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:mainVC];

4.将第三步创建的导航控制器作为window的根视图控制器
self.window.rootViewController = navi;

5.MainViewController通过调用自己viewgetter方法来获取自己的视图对象.此时会调用懒加载的view方法,viewgetter方法内部loadViewviewDidLoad方法会被先后调用
//window中的方法
- (
void)setRootViewController:
   (UIViewController *)rootViewController
   {
      
if(_rootViewController != rootViewController){
           [_rootViewController release];
           [ _rootViewController = rootViewController retain];
          
//第一次调用viewgetter方法(懒加载)
           [
selfaddSubview:_rootViewController.view]
       }
   }
//控制器中的方法
- (UIView *)view{
   
if(!_view){
        [
selfloadView];
        [
selfviewDidLoad];
    }
   
return _view;
}



6.在视图控制器的viewDidLoad方法内部:创建CustomTableView对象,并指定customDelegate为对应的根视图控制器,在由视图控制器的view调用addSubview将创建的表视图添加显示

MainViewController.m文件中
- (
void)viewDidLoad{
    [
superviewDidLoad];
CustomTableView *aTableView = [[CustomTableView alloc] initWithFrame:
self.view.bounds];
aTableView.rowHeight =
60;
aTableView.customDelegate =
self;
[
self.view addSubview:aTableView];
[aTableView release];
}



7.当视图控制器的视图通过addSubview添加表视图时,表视图重写的didMoveToSuperview方法就会被调用


8.在执行表视图的didMoveToSuperview方法时,会调用表视图的私有方法layoutCells来布局表视图所要管理显示的单元格视图们

CustomTableView.m
文件中
<
1>创建私有方法layoutCells
@interfaceCustomTableView ()
- (
void)layoutCells;//为表视图布局单元格
@end

<
2>被移到父视图上自动调用
- (
void)didMoveToSuperview{
    [
superdidMoveToSuperview];
    [
selflayoutCells];
}



9.layoutCells方法内部,做如下操作:
<
1>numberOfRowsInCustomTable方法来由代理对象指定表视图的行数
- (NSUInteger)numberOfRowsInCustomTable:(CustomTableView *)tableView{
   
return 100;}//MainViewController.m方法中实现代理方法,及传返回值
<
2>借助行数以循环的形式有代理对象通过调用tableView:cellForRowAtIndex:来获取对应下表的单元格视图
- (CGFloat)tableView:(CustomTableView *)tableView heightForRowAtIndex:(NSInteger )index{
return60;}//MainViewController.m方法中实现代理方法,及传返回值
<
3>重新根据代理对象调用tableView:heightForRowAtIndex:获取到的对应行的行高来设定单元格的frame
- (TableViewCell *)tableView:(CustomTableView *)tableView cellForRowAtIndex:(NSInteger)index{}
/*MainViewController.m方法中实现代理方法,及创建一个TableViewCell,然后传回给委托方*/ (@optional)
<
4>为当前得到的单元格添加轻拍手势识别器
<
5>最后将单元格通过addSubview添加在表视图上
<
6>根据总行高计算表视图的contentSize

CustomTableView.m
文件中
- (
void)layoutCells{
   
//通过代理对象获得行数
<
1> NSUInteger rows = [self.customDelegate numberOfRowsInCustomTable:self];


   
//定义一个变量记录总高度
    CGFloat totalHeight =
0;
    CGFloat currentHeight =
0;
   
   
for (inti = 0; i < rows; i++){
<
2>TableViewCell *aCell = [self.customDelegate tableView:selfcellForRowAtIndex:i];

<
3>if([self.customDelegate respondsToSelector:@selector(tableView:heightForRowAtIndex:)]) {
        currentHeight = [
self.customDelegate tableView:selfheightForRowAtIndex:i];
    }

    aCell.index = i;
   
    aCell.frame = CGRectMake(
0, totalHeight, CGRectGetWidth(self.bounds), currentHeight);

<
4>  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleTap:)];
    [aCell addGestureRecognizer:tap];
    [tap release];
   
<
5> [selfaddSubview: aCell];
     totalHeight += currentHeight;
    }
   
<
6>//根据总高度在设定contensize
   
self.contentSize = CGSizeMake(CGRectGetWidth(self.bounds), totalHeight);
}
   
   
10.当我们轻拍某一行单元格时,该单元格上轻拍手势识别器就会响应,在其对应的handleTap:方法内部,并没有直接处理轻拍,而是通过代理对象执行
tableView:didSelectRowAtIndex:
方法来处理单元格的点击


CustomTableView.m
文件中
- (
void)handleTap:(UITapGestureRecognizer *)sender{
   
//当单元格的轻拍手势被识别后,当前表视图并不直接处理轻拍,而是交由代理对象通过执行协议方法作出最终处理
    TableViewCell *aCell = (TableViewCell *)[sender view];
//获取被轻拍的单元格(轻拍手势自带view属性)
   
   
   
if (self.customDelegate && [self.customDelegate respondsToSelector:@selector(tableView:didSelectRowAtIndex:)]) {
        [
self.customDelegate tableView:selfdidSelectRowAtIndex:aCell.index];
    }
}


MainViewController.h中实现方法(@optional)
- (
void)tableView:(CustomTableView *)tableView didSelectRowAtIndex:(NSInteger)index{
}









最先创建一个封装好的TableViewCell
@interfaceTableViewCell : UIView
@property(nonatomic,retain) UIImageView *imageView;
@property(nonatomic,retain) UILabel *textLable;
@property(nonatomic,assign)NSInteger index;//单元格在表视图中的下标
@end


TableViewCell.m
中实现

@implementationTableViewCell


- (
void)dealloc{
    [_imageView release];
    [_textLable release];
    [
superdealloc];
}


- (
instancetype)initWithFrame:(CGRect)frame{
   
self = [superinitWithFrame:frame];
   
if (self) {
       
    }
   
return self;
   
}



- (UIImageView *)imageView{
   
if (!_imageView) {
       
self.imageView = [[[UIImageView alloc] initWithFrame:CGRectZero] autorelease];
        [
selfaddSubview:_imageView];
    }
   
return _imageView;
}


- (UILabel *)textLable{
   
if (!_textLable){
       
self.textLable = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
        _textLable.font = [UIFont systemFontOfSize:
17];
        [
selfaddSubview:_textLable];
    }
   
return _textLable;
}

//在外调用imageView,_textLablegetter方法时,self.bounds/frame还没创建
- (
void)didMoveToSuperview{
    [
superdidMoveToSuperview];
    CGFloat x =
5;
   
if (_imageView) {
       
self.imageView.frame = CGRectMake(5,5, CGRectGetHeight(self.bounds) - 10, CGRectGetHeight(self.bounds) - 10);
        x = _imageView.frame.origin.x + CGRectGetWidth(_imageView.frame) +
5;
    }
   
if (_textLable) {
       
self.textLable.frame = CGRectMake(x,5, CGRectGetWidth(self.bounds) - x - 5, CGRectGetH                                                                                                                                                                                                                                                                    eight(self.bounds) -10);
    }
   
   
    UIView *seperator = [[UIView alloc] initWithFrame:CGRectMake(
0, CGRectGetHeight(self.frame) - 1, CGRectGetWidth(self.frame) - 1,1)];
    seperator.backgroundColor = [UIColor lightGrayColor];
    [
selfaddSubview:seperator];
    [seperator release];
   
   
}




二,UITableView编辑

1.创建UITableViewController子类MainViewController
MainViewController.m文件中

//UITableViewController自动创建UITableView,实现UITableViewDataSource,UITableViewDelegate协议
 
@interfaceMainViewController ()


@property(nonatomic,retain)NSMutableArray *dadaSource;

@end

@implementationMainViewController

- (
void)dealloc{
    [_dadaSource release];
    [
superdealloc];
}



- (NSMutableArray *)dadaSource{
   
if (!_dadaSource) {
       
self.dadaSource = [NSMutableArray array];
       
    }
   
return _dadaSource;
}



2.不用创建tableView,父类在viewDidLoad中已创建好
- (
void)viewDidLoad {
    [
superviewDidLoad];
    [
self.tableView registerClass:[UITableViewCellclass] forCellReuseIdentifier:@"CELL"];
   
   
// 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.
   
//如果表视图需要通过编辑按钮来切换其编辑状态,则只需要调用editButtonItem方法来获取一个编辑按钮,添加在导航条上
   
   
self.navigationItem.rightBarButtonItem =self.editButtonItem;
   
    [
self.dadaSource addObject:@"第一行"];
    [
self.dadaSource addObject:@"添加最新一行"];
}


3.指定分区和行数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
   
//#warning Potentially incomplete method implementation.
   
// Return the number of sections.
   
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
   
//#warning Incomplete method implementation.
   
// Return the number of rows in the section.
   
return self.dadaSource.count;
}


4.UITableViewCell懒加载
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
@"CELL"forIndexPath:indexPath];
   
   
// Configure the cell...
   
    cell.textLabel.text =
self.dadaSource[indexPath.row];
   
//cell.textLabel.text = [NSString stringWithFormat:@"%ld行单元格",indexPath.row + 1];
   
return cell;
}




5.表视图删除,添加步骤
UITableViewDelegate
中的协议
<
1>tableView处于编辑状态
- (
void)setEditing:(BOOL)editing animated:(BOOL)animated{
    [_tableView setEditing:!_tableView.isEditing animated:
true];

}

<
2>指定tableView哪些行可以编辑
// Override to support conditional editing of the table view.
- (
BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
   
// Return NO if you do not want the specified item to be editable.
   
//该协议方法是询问代理对象对应行是否允许被进行编辑操作.(通过重写协议方法可以让表视图支持条件编辑,默认为全部允许编辑)
   
//if (indexPath.row == 0) {
   
//     return NO;
   
//}
   
return YES;
}


<
3>指定tableView编辑的样式(添加、删除)
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
   
//为表视图的对应行指定编辑样式,样式有:插入,删除,选中,和无
   
   
if (indexPath.row ==self.dadaSource.count -1) {
       
return UITableViewCellEditingStyleInsert; //添加样式
    }
   
return UITableViewCellEditingStyleDelete; //删除样式
   
   
//return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert; //选择样式
}



<
4>编辑完成(先操作数据源,再修改UI
// Override to support editing the table view.
- (
void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
   
//在完成编辑的协议方法中,无论是删除样式还是插入样式都需要先操作数据源中的数据,在通过表视图的相关方法删除对应行或者插入新的行
   
   
   
if (editingStyle == UITableViewCellEditingStyleDelete) {
       
//1. Delete the row from the data source 删除对应行在数组中数据
        [
self.dadaSource removeObjectAtIndex:indexPath.row];
       
//2.删除单元格  UITableViewRowAnimationFade这里用哪个枚举值都是一个效果
[tableView deleteRowsAtIndexPaths:
@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
    }
else if (editingStyle == UITableViewCellEditingStyleInsert) {
       
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
       
//1.数组里插入新的数据
        [
self.dadaSource insertObject:@"新插入的数据"atIndex:indexPath.row];
       
//2.插入对应行
        [tableView insertRowsAtIndexPaths:
@[indexPath]withRowAnimation:UITableViewRowAnimationFade];
       
       
    }
}











6.表视图移动
<
1>tableView处于编辑状态
- (
void)setEditing:(BOOL)editing animated:(BOOL)animated;

<
2>指定tableView哪些行可以移动
// Override to support conditional rearranging of the table view.
- (
BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
   
// Return NO if you do not want the item to be re-orderable.
   
if (indexPath.row ==0) {
       
return NO;}
   
return YES;
}

<
3>移动完成
// Override to support rearranging the table view.
- (
void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
   
//在界面移动完成时,通过次协议方法来更新数据源中的元素顺序
   
//1.先获取被移动的数据
   
id object = [self.dadaSource[fromIndexPath.row] retain];
   
//2.将该对象从数组中移除
    [
self.dadaSource removeObjectAtIndex:fromIndexPath.row];
   
//3.将该对象插入到指定下标
    [
self.dadaSource insertObject:object atIndex:toIndexPath.row];
   
//4.释放对象的所有权
    [object release];
}

<
4>监测移动过程,实现限制跨区移动
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath



三,UIViewController建立



#import<Foundation/Foundation.h>

@protocol_____ <NSObject>


UIViewController

一个应用程序分配80M内存

回收内存:dealloc

UIViewController
MVC设计模式的核⼼。
MVC
是一个框架级的设计模式。
M
Model,主要用于建⽴数据模型(即数据的结构)
V
View,我们能看到的所有控件都是view,view主要的功能是展示数据。
C
是控制器,主要是控制MV的通信。是视图管理者和代理对象,响应需要得到view的指示.Model层要数据,View分发数据


系统的可维护性、可扩展性增强


视图控制器-> 模块化管理当前视图界面(是靠里面自带view的属性来管理)
        -> view
属性-> (创建-> 1.通过view属性的懒加载2.loadView方法) ->创建子视图viewDidLoad方法
        ->
被管理的子视图需要target/action视图控制器来提供
        ->
被管理的子视图需要delegate视图控制器成为代理对象并实现相关方法


UIViewController
生命周期-> init
                        -> loadView
                        -> viewDidLoad
                        -> viewWillAppear
视图将要出现
                        -> viewDidAppear
                        -> viewWillDisappear
视图将要从界面移除
                        -> viewDidDisappear
                        -> dealloc



exceptin_bad_access
出现异常访问(野指针)



2015-09-0210:08:49.076UILesson07[624:25724] Application windows are expected to have a root view controller at the end of application launch
应用程序的窗口对象在应用程序加载完成后应该加一个视图控制器



1.定义UIViewController的子类
UIViewController
自带用于布局子视图的视图

2.如果要自己建立一个视图控制器的view视图:loadView

MainViewController.h
@interfaceMainViewController : UIViewController
@end

MainViewController.m
子类重写父类的方法(相当于对父类实现的方法做以扩展),先调用子类方法(子类方法要先把父类方法继承过来)
//loadView负责加载一个与屏幕尺寸一样大的UIView对象,当视图控制器的view属性的getter方法第一次调用时会调用loadView方法加载一个视图
- (
void)loadView{
   
//加载视图(父类方法会加载一个window一样大的全屏视图)
    [
superloadView];
   
//父类中的方法
   
//self.view = [[[UIView alloc ] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
   
   
//如果要自定义视图控制器自带的view,则不需要通过super调用父类实现的loadView方法,而是直接给view属性赋值一个视图对象
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
   
//打开imageView的交互
    imageView.userInteractionEnabled =
YES;
    imageView.image = [UIImage imageNamed:
@"1.jpg"];
   
self.view = imageView;
    [imageView release];
   
    NSLog(
@"%s",__FUNCTION__);
}


3.//加载完成,viewDidLoad方法中为视图控制器的视图添加要被管理的子视图
-(
void)viewDidLoad{
    [
superviewDidLoad];
   
//Do any additional setup after loading the view;
   
    UIButton *aButton = [UIButton buttonWithType:UIButtonTypeSystem];
    aButton.frame = CGRectMake(
0,0,100,60);
    aButton.center =
self.view.center;
    aButton.backgroundColor = [UIColor redColor];
    [aButton setTitle:
@"按钮"forState:UIControlStateNormal];
   
//self是当前视图控制器对象
   
   
//如果视图是由视图控制器来管理的,那么如果这个视图需要对事件做出响应时,对应的视图控制器就是其响应者,并提供响应方法
    [aButton addTarget:
selfaction:@selector(handleButtonAction:) forControlEvents:UIControlEventTouchUpInside];
   
   
   
//视图控制器管理的视图如果需要通过target/action或者delegate来处理对应的操作时,有该视图控制器提供处理方法,或者称为代理对象实现对应的协议方法
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:
selfaction:@selector(handleTap:)];
    [
self.view addGestureRecognizer:tap];
    [
self.view addSubview:aButton];
   
}



//另一种按按钮中的return键完成收回键盘的方法
谁管理视图谁给视图提供响应方法或者代理
@interfaceMainViewController ()<UITextFieldDelegate>
@end
text.keyboardType = UIReturnKeyDone;
text.delegate =
self;
- (
BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
   
return YES;
}





UIViewController.m
中有意私有属性view
父类中view属性是私有的,不能继承,不能重写方法,但是父类中方法是可以重写的,并优先调用子类重写的方法,如果上面子类的loadView方法中不[superloadView],就不会实现父类中loadView方法,不会创建view,一直!_view会使其子类一直调用父类中viewgetter方法造成死循环;
MainViewController
的父类UIViewControllerviewgetter方法:
- (UIView *)view{
   
if(!_view){
        [
selfloadView];
        [
selfviewDidLoad];
    }
   
return _view;
}


4.创建视图控制器对象,作为window的根视图控制器
AppDelegate.m


//创建视图控制器对象
MainViewController *mainVC = [[MainViewController alloc] init];
//指定给window,作为window的根视图控制器
self.window.rootViewController = mainVC;
[mainVC release];



以上self.window调用RootViewCintrollersetter方法
- [(
void)setRootViewController:
   (UIViewController *)rootViewController
   {
      
if(_rootViewController != rootViewController){
           [_rootViewController release];
           [ _rootViewController = rootViewController retain];
          
//第一次调用viewgetter方法(懒加载)
           [
selfaddSubview:_rootViewController.view]
       }
   }


不能写成[self.window addSubview:mainVC.view]
//点击text text.delegate指向一个已经被释放内容的地址







 
生命周期
  
   - (
void)viewWillAppear:(BOOL)animated{
       [
superviewWillAppear:animated];
       NSLog(
@"%s",__FUNCTION__);
   }
  
  
   - (
void)viewDidAppear:(BOOL)animated{
       [
superviewDidDisappear:animated];
       NSLog(
@"%s",__FUNCTION__);
   }
  
  
   - (
void)viewWillDisappear:(BOOL)animated{
       [
superviewWillDisappear:animated];
       NSLog(
@"%s",__FUNCTION__);
   }
  
  
   - (
void)viewDidDisappear:(BOOL)animated{
       [
superviewDidDisappear:animated];
       NSLog(
@"%s",__FUNCTION__);
   }
  
  
   -(
void)dealloc{
       NSLog(
@"%s",__FUNCTION__);
       [
superdealloc];
   }
  
  
  
     
  
  
  






@end



0 0
原创粉丝点击