内容概要:

  本文先讲解了UITableView概述,然后主要从应用方面讲解了UITableViewController(包括add、delete、move单元cell的操作,以及UITableViewDelegate和UITableViewDataSource的相关知识),然后讲解了UITableViewCell的相关知识,其中cell的重用机制在应用中最为重要,最后讲解了有关ScrollView的相关知识,并封装了一个支持"下拉刷新"和"上拉加载更多"的UITableView子类。

目录:

1.UITableView概述
(1.1) UITableView继承关系
(1.2) UITableView和UITableViewController的关系
(1.3)UITableView的2种header和footer
2.UITableViewController
(2.1)UITableViewController初始化方法
(2.2)UITableViewController常用设置
(2.3)编辑UITableView
(2.3.1) add (2.3.2) delete(2.3.3)move
  (2.4) UITableViewDelegate方法、UITableViewDataSource方法
3. UITableViewCell
(3.1)UITableViewCell组成
(3.2)UITableViewCell初始化方法
(3.3)UITableViewCellStyle
(3.4) UITableViewCells复用机制
(3.5) UITableViewCell的contentView与cell的2种模式的关系
4. UITableViewController的下拉刷新上拉加载
(4.1)UIScrollView的几个关键概念
(a)contentSize(b)contentInset(c)contentOffset
(4.2)下拉刷新、上拉加载
(4.2.1)类的设计
(4.2.2)下拉刷新、上拉加载用到的属性、方法
  (4.2.3)下拉刷新及其代码实现
(4.2.4)上拉加载及其代码实现
(4.2.5)github代码
5. reload
(5.1)刷新整个tableView
(5.2)刷新某个section
(5.3)刷新某个cell
6. MVVM模型在tableViewController中的使用

正文内容:

1.UITableView概述

  (1.1) UITableView继承关系:UITableView:UIScrollView : UIView : UIResponder : NSObject

(1.2) UITableView和UITableViewController的关系:

  UITableView属于MVC的View部分,另外它还需要自己的Model和Controller部分:(1)UITableView需要一个ViewController控制显示,UITableViewController负责此角色;(2)UITableView需要数据源data source(即Model部分),UITableViewController遵守UITableViewDataSource协议,因此UITableViewController也负责此角色;(3)UITableView需要代理通知其它对象关于UITableView的事件,这个代理需遵守UITableViewDelegate协议,因此UITableViewController也负责此角色。

  UITableView和UITableViewController的关系可用如下图表示:

图1.2 UITableView和UITableViewController的关系

(https://github.com/SheronLv/Images/blob/master/UITableView/UITableView和UITableViewController的关系.png)

(1.3)UITableView的2种header和footer (a)2种header:table header和section header;(b)2种footer:table footer和section header。

2.UITableViewController

(2.1)UITableViewController初始化方法

  UITableViewController的指定初始化方法是initWithStyle:

- (instancetype)initWithStyle:(UITableViewStyle)style;

  其中UITableView的style 有两种:UITableViewStylePlain、UITableViewStyleGrouped。当UITableView创建时,必须指定它为这两种style中的一种,而且指定之后,不能再改变。

UITableViewController用Nib加载方式:

-(id)init{ 
    return [self initWithNibName:@"NVShanHuiViewController" bundle:nil];
}
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{  
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) {
        self.dragRefresh = YES;
    }
    return  self;
}

 (2.2)UITableViewController常用设置:

//设置每行不可选:
self.tableView.allowsSelection = NO;
//设置分割线:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;//UITableViewCellSeparatorStyleSingleLine
self.tableView.separatorColor = [UIColor blueColor];
//设置cell选中状态
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// 清除tableview的选中状态
- (void)deselectTableView {
NSIndexPath *selected = [self.tableView indexPathForSelectedRow];
if(selected)
[self.tableView deselectRowAtIndexPath:selected animated:YES];
}

(2.3) 编辑UITableView:add、delete、move

  (2.3.1) add

//“增加item”的按钮
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width-, )];
UIButton *addButton = [[UIButton alloc] initWithFrame:CGRectMake(, , , )];
[addButton setTitle:@"add Item to section 1" forState:UIControlStateNormal];
[addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[addButton addTarget:self action:@selector(addItem) forControlEvents:UIControlEventTouchUpInside];
[addButton.layer setMasksToBounds:YES];
[addButton.layer setBorderWidth:1.0];
addButton.backgroundColor = [UIColor colorWithRed: green: blue: alpha:0.1];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef colorref = CGColorCreate(colorSpace,(CGFloat[]){ , , , 0.25 });
[addButton.layer setBorderColor:colorref];
[headerView addSubview:addButton];
self.tableView.tableHeaderView = headerView; // 点击按钮,为第1个Section添加row。此时会去执行cellForRowAtIndexPath中的对应IndexPath创建cell并添加
- (void)addItem {
NSInteger num = [self.dataArray[] count];
NSMutableArray *array = [NSMutableArray arrayWithArray:self.dataArray[]];
[array addObject:@"new"];
self.dataArray[] = array;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:num inSection:];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}

  (2.3.2)delete

//如果没有写此方法,就自动不会出现“delete”的操作;实现了此方法,就会自动出现“delete”的操作
- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
[self changeDataArrayForDelete:indexPath];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
-(void)changeDataArrayForDelete:(nonnull NSIndexPath *)indexPath {
if( indexPath.section == ) return;
NSInteger section = indexPath.section;
NSMutableArray *array = [NSMutableArray arrayWithArray:self.dataArray[section]];
[array removeObjectAtIndex:indexPath.row];
self.dataArray[section] = array;
}

  (2.3.3)move

//设置为可编辑状态
[self.tableView setEditing:YES animated:YES]; // 移动时之行此dataSource方法,并不会触发相应的cellForRowAtIndexPath方法
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(nonnull NSIndexPath *)sourceIndexPath toIndexPath:(nonnull NSIndexPath *)destinationIndexPath {
[self changeDataArrayForMoveFromIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
} - (void)changeDataArrayForMoveFromIndexPath:(nonnull NSIndexPath *)sourceIndexPath toIndexPath:(nonnull NSIndexPath *)destinationIndexPath {
if(sourceIndexPath.section == || sourceIndexPath == destinationIndexPath){
return;
}
NSInteger sourceSection = sourceIndexPath.section;
NSMutableArray *array = [NSMutableArray arrayWithArray:self.dataArray[sourceSection]];
NSString *theString = [array objectAtIndex:sourceIndexPath.row];
[array removeObjectAtIndex:sourceIndexPath.row];
self.dataArray[sourceSection] = array; NSInteger destinationSection = destinationIndexPath.section;
array = [NSMutableArray arrayWithArray:self.dataArray[destinationSection]];
[array insertObject:theString atIndex:destinationIndexPath.row];
self.dataArray[destinationSection] = array;
}

(2.4) UITableViewDelegate方法、UITableViewDataSource方法

//UITableViewDelegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; //UITableViewDataSource
@required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView __TVOS_PROHIBITED;                     

3. UITableViewCell

(3.1)UITableViewCell组成:

UITableViewCell由contentView和Accessory indicator组成,其中contentView包含3个subView:imageView、textLabel和detailTextLabel,各view的包含关系如下图:

图3.1 UITableViewCell的组成元素

(3.2)UITableViewCell初始化方法:

UITableViewCell用如下指定初始化方法初始化UITableViewCell:

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier;

(3.3)UITableViewCellStyle

UITableViewCell的contentView包含3个subView:imageView、textLabel和detailTextLabel,上面代码中指定初始化的style决定了contentView中是否展示某个subView以及各个subView展示的位置,style一共有4种:

(1)UITableViewCellStyleDefault

(2)UITableViewCellStyleSubtitle

(3)UITableViewCellStyleValue1

(4)UITableViewCellStyleValue2

效果依次如下:

图3.3 UITableViewCellStyle的4种形式的效果图

(3.4) UITableViewCells复用机制

使用以下2种方法即使用cell的复用机制创建cell:

(1)- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;  // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
(2)- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered

当用户滑动table时,一些cell会滑出屏幕,滑出屏幕的cells会被放入cell池中以供复用。当用上面两种方法创建cell时,data source会首先在cell池中查看是否有可供复用的cell存在,当存在时,就直接从cell池中取,当cell池中没有可用的cell时,才创建新的。

注意事项:

// 用(1)创建cell后,必须判断cell是否为nil。
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// 用(2)创建cell前,必须要对cell进行注册:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellIdentifier_1"];
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([NVBankCardInfoCell class]) bundle:nil] forCellReuseIdentifier:@"cellIdentifier_2"];

(3.5) UITableViewCell的contentView与cell的2种模式的关系

UITableViewCell的subView要添加到cell.contentView里,因为:cell有两种模式:standard mode和editing mode, 如图所示:

图3.5 cell两种模式

contentView在这两种模式下会自动调整。

4. UITableViewController的下拉刷新上拉加载

(4.1)UIScrollView的几个关键概念:

UITableView继承自UIScrollView,UIScrollView有几个关键属性:contentSize、contentOffset、contentInset。

   (a)contentSize是UIScrollView可以滑动的范围的大小;tabelview的contentsize是由它的下列方法共同实现的:

- (NSInteger)numberOfSections;
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

它会自动计算所有的高度和来做为它的contentsize的height.

   (b)contentInset的单位UIEdgeInsets定义如下:

typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right;  // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;

比如设置contentInset如下:

self.tableView.contentInset = UIEdgeInsetsMake(5, 6, 7, 8);//top  left bottom right

这句代码的意思是说,self.tableView的内容距离self.view的边缘的距离分别是top:50,  left:60, bottom:70, right:80.

(c)contentOffset的单位是CGPoint。它不是用来设置contentView,是衡量scrollview当前显示区域顶点相对于self.view原点的偏移量.比如,下拉加载时,contentOffset.y就是负值(显示区域的顶点在原点之上);当往上滑动tableView则显示的内容是相对原点往下20个偏移量,那个它的contentOffset就是(0, 20),即contentOffset.y是正值(显示区域的顶点在原点之下).

(4.2)下拉刷新、上拉加载

(4.2.1)类的设计

      LVTableViewController:实现下拉刷新、上拉加载功能的tableViewController;

LVRefreshHeaderView:下拉刷新时,展示各种下拉刷新状态的headerView;

LVLoadingCell:上拉加载Cell。

(4.2.2)下拉刷新、上拉加载用到的属性、方法:

(a) property:dragRefresh
BOOL型,在整个NVTableViewController初始化时设置是否启用下拉刷新功能。
如果设置了dragRefresh为YES,则NVTableViewController在加载视图(viewDidLoad)时会创建EGORefreshTableHeaderView的实例作为当前tableView的子视图。EGORefreshTableHeaderView随着手势的不同展示三种状态:正常状态、下拉状态、数据加载状态。
(b)- (UITableViewCell *)dequeueMoreCell;
返回可复用的载入更多的CELL:首先返回loading Cell,随后会调用[loadNext]方法
(c) -(void)loadNext;
需子类复写,当显示载入更多的CELL时会触发该方法,子类在该方法中进行网络请求需要加载的更多的数据。
(d)- (BOOL)refreshData;需子类复写,下拉刷新时子类中重新进行刷新的数据请求,父类会在scrollViewDidEndDecelerating:中根据[refreshData]的返回值设置刷新状态显示。

(4.2.3)下拉刷新及其代码实现

图4.2 下拉刷新三种状态

主要实现如下:

LVRefreshHeaderView里的主要代码:

typedef NS_ENUM(NSUInteger, LVPullRefreshState){
LVPullRefreshNormal = , //refreshHeaderView隐藏的状态
LVPullRefreshPulling, // 下拉状态
LVPullRefreshLoading, // 加载状态
}; - (void)setState:(LVPullRefreshState)aState {
switch (aState) {
case LVPullRefreshNormal:
self.statusLabel.text = @"下拉可以刷新...";
NSLog(@"下拉可以刷新...");
[self.indicatorView stopAnimating];
self.arrowImageView.hidden = NO;
break;
case LVPullRefreshPulling:
self.statusLabel.text = @"松开即可刷新...";
NSLog(@"松开即可刷新...");
[self setImageAnimated];
break;
case LVPullRefreshLoading:
self.statusLabel.text = @"加载中...";
NSLog(@"加载中...");
[self.indicatorView startAnimating];
self.arrowImageView.hidden = YES;
break;
default:
break;
}
}

LVTableViewController的主要代码:

#pragma mark Drag & Refresh

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(!self.dragRefresh) {
return;
}
if(scrollView.isDragging) { if(self.refreshHeaderView.state == LVPullRefreshPulling && scrollView.contentOffset.y > -65.0f && scrollView.contentOffset.y < 0.0f && !_reloading) {
//拉动距离小于65
[self.refreshHeaderView setState:LVPullRefreshNormal];
} else if(self.refreshHeaderView.state == LVPullRefreshNormal && scrollView.contentOffset.y < -65.0f && !_reloading) {
//拉动距离大于65
[self.refreshHeaderView setState:LVPullRefreshPulling];
}
}
} - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if(!self.dragRefresh) {
return;
}
NSLog(@"c:%f",scrollView.contentOffset.y);
if (scrollView.contentOffset.y <= - 65.0f && !_reloading) {
_reloading = YES;
if([self refreshData]) {
[self.refreshHeaderView setState:LVPullRefreshLoading];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
self.tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f);
[UIView commitAnimations];
} else {
[self refreshFinished];
}
}
}
- (void)refreshFinished{
if (!self.dragRefresh) return; if (_reloading) {
_reloading = NO;
[UIView animateWithDuration:. animations:^{
[self.tableView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)];
} completion:^(BOOL finished) {
[self.refreshHeaderView setState:LVPullRefreshNormal];
}];
}
}
- (BOOL)refreshData {
return NO;
}

(4.2.4)上拉加载及其代码实现

- (void)loadNext {
}
- (UITableViewCell *)dequeueMoreCell { UITableViewCell * cell = [self dequeueLoadingCell];
cell.backgroundColor = [UIColor clearColor];
[self performSelector:@selector(loadNext) withObject:nil afterDelay:0.0];
return cell;
}

(4.2.5)github代码

https://github.com/SheronLv/LVTableViewController.git

  其中包括了LVTableViewController实现了tableView的下拉刷新和上拉加载,MyBusinessTableViewController里面实现对tableViewController的一些验证,如有不当之处,欢迎提出批评指正。

5. reload
  (5.1)刷新整个tableView
[self.tableView reloadData];
  (5.2)刷新某个section
//一个section刷新
NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:];
[tableview reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
  (5.3)刷新某个cell
//一个cell刷新  
NSIndexPath *indexPath=[NSIndexPath indexPathForRow: inSection:];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];
//或者:
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

6. MVVM模型在tableViewController中的使用

MVVM模型中的viewModel使用三个信号控制tableView中的显示,这三个信号分别是接口是否正在请求(loading信号)、接口请求成功(loadingSuccess信号)和接口请求失败(errorMsg信号)。关键代码如下所示:

(1)viewModel中的信号和数据请求

//数据请求情况
@property (nonatomic, assign) BOOL loading;
@property (nonatomic, assign) BOOL loadingSuccess;
@property (nonatomic, strong) NSString * errorMsg;
//数据请求
- (void)queryData {
self.loading = YES;
@weakify(self);
[[[NVNetworkClient client] queryData] subscribeNext:^(DataQueryed * data) {
@strongify(self);
//释放请求的data给外部使用
self.loading = NO;
self.loadingSuccess = YES;
} error:^(NSError * error) {
@strongify(self);
self.loading = NO;
self.loadingSuccess = NO;
self.errorMsg = [error nv_message];
}];
}

(2)tableViewController中初始化使用

-(void) viewDidLoad {
[super viewDidLoad];
self.viewModel = [[MyViewModel alloc] init];
[self bindEvent];
[self.viewModel queryData];
}
- (void)bindEvent{
//提示网络错误
@weakify(self);
[RACObserve(self.viewModel, errorMsg) subscribeNext:^(NSString * errorMsg) {
@strongify(self);
[self setShowLoading:NO];
if(errorMsg&&errorMsg.length>){
[self showSplash:dgErrorMsg];
}
[self.tableView reloadData];
[self refreshFinished];
}];
//请求成功
[RACObserve(self.viewModel, loadingSuccess) subscribeNext:^(NSNumber * loadingSuccess) {
@strongify(self);
if ([loadingSuccess boolValue] == YES) {
[self setShowLoading:NO];
[self.tableView reloadData];
[self refreshFinished];
}
}];
}

(3)tableView各delegate对viewModel的运用

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if (self.viewModel.rcLoadingSuccess == YES) {
//返回正常需要的section个数
} else if (self.viewModel.loadingSuccess == NO && self.viewModel.errorMsg != nil) {
return ;
}
return ;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (正常情况) {
return 正常cell;
}
return ; // 包括特殊的没请求成功的情况,1个cell
} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == && !self.viewModel.rcLoadingSuccess) {
return NVErrorPageViewHeight;
}
return 正常需要的高度;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (!self.viewModel.loadingSuccess) {
UITableViewCell * cell = [self dequeueEmptyWithAnnounceCell:@"网络不给力,下拉刷新重试!" hintMessage:nil emptyType:kNothing_Empty];
return cell;
}
if (正常情况) {
return 正常cell;
}
return [UITableViewCell new];
}

UITableView & UITableViewController的更多相关文章

  1. iOS UITableView , UITableViewController ,UITableViewCell实现全国各省市遍历,选择相应的地区

    我们先看一下效果                   代码如下 首先是第一个页面 rootTableViewController.h #import <UIKit/UIKit.h> #im ...

  2. iOS programming UITableView and UITableViewController

    iOS programming  UITableView and UITableViewController A UITableView displays a single column of dat ...

  3. iOS 开发快速导引:TableView 和 CoreData【草】

    所有列表式的数据都是用 TableView 显示的 预览 待补充 原料 NSFetchedResultsController 用来操作 NSFetchRequst,有执行查询,监听变化,数据缓存等功能 ...

  4. iOS 底层框架的浅析

    1.简介 IOS是由苹果公司为iPhone.iPod touch和iPad等设备开发的操作系统. 2.知识点 iPhone OS(现在叫iOS)是iPhone, iPod touch 和 iPad 设 ...

  5. IOS计划 分析

    1.基本介绍 IOS苹果公司iPhone.iPod touch和iPad操作系统和其他设备的发展. 2.知识点 1.IOS系统 iPhone OS(现在所谓的iOS)这是iPhone, iPod to ...

  6. iOS底层框架浅析

    1.简介 IOS是由苹果公司为iPhone.iPod touch和iPad等设备开发的操作系统. 2.知识点 iPhone OS(现在叫iOS)是iPhone, iPod touch 和 iPad 设 ...

  7. iOS UITableView 与 UITableViewController

    很多应用都会在界面中使用某种列表控件:用户可以选中.删除或重新排列列表中的项目.这些控件其实都是UITableView 对象,可以用来显示一组对象,例如,用户地址薄中的一组人名.项目地址. UITab ...

  8. UITableView 和 UITableViewController

    UITableView:显示有多行数据的一个列. 新建一个过程:Xcode -> File -> New -> Project...,然后选择iOS -> Applicatio ...

  9. iOS学习笔记之UITableViewController&UITableView

    iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论 ...

随机推荐

  1. 【wikioi】1281 Xn数列(矩阵乘法)

    http://wikioi.com/problem/1281/ 矩阵真是个神奇的东西.. 只要搞出一个矩阵乘法,那么递推式可以完美的用上快速幂,然后使复杂度降到log 真是神奇. 在本题中,应该很快能 ...

  2. 【wikioi】1269 匈牙利游戏(次短路+spfa)

    http://www.wikioi.com/problem/1269/ 噗,想不到.. 次短路就是在松弛的时候做下手脚. 设d1为最短路,d2为次短路 有 d1[v]>d1[u]+w(u, v) ...

  3. new在c#方法中的使用

    new在c#中有三种用法: 1.实例化对象 2.泛型约束 3.用在方法前.new和override的区别在于:override用于重写父类的方法:new用于隐藏方法,它调用的方法来自于申明的类,如果申 ...

  4. linux 快捷键

    截图: 打印: 全屏截图 alt+打印:窗口截图 shift+打印:区域截图 ctrl+打印:截图到剪贴板 显示桌面: ctrl+super+d 最大化最小化窗口 ctrl+alt+up/down 转 ...

  5. ubuntu apt源

    deb http://archive.ubuntu.com/ubuntu/ vivid main restricted universe multiversedeb http://archive.ub ...

  6. iOS移动开发周报-第24期

    iOS移动开发周报-第24期 [摘要]:本期iOS移动开发周报带来如下内容:苹果更新了iTunes Connect的设计.UIKit Dynamics 教程:抛掷 Views.iOS APP 架构漫谈 ...

  7. Ubuntu 下误修改用户组导致sudo命令无效

    1.手贱地修改了当前用户的权限组,导致sudo命令无法使用,且root用户的密码尚未修改,登陆不了root用户. 2.切换到recoverymode ,使用root用户登陆 3.执行mount -o ...

  8. [转] - QBuffer类参考

    QBuffer类参考 QBuffer类是一个操作QByteArray的输入/输出设备. 详情请见…… #include <qbuffer.h> 继承了QIODevice. 所有成员函数的列 ...

  9. Html - 对话箭头

    对话箭头 <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="U ...

  10. php如何把文件上传到服务器上

    conn.php: <?php $id=mysql_connect('localhost','root','root'); mysql_select_db("db_database12 ...