内容概要:

  本文先讲解了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. POJ1797 Heavy Transportation(SPFA)

    题目要求1到n点的最大容量的增广路. 听说是最短路求的,然后乱搞就A了.. 大概能从Bellman-Ford的思想,dk[u]表示从源点出发经过最多k条边到达u点的最短路,上理解正确性. #inclu ...

  2. 正则表达式学习日记zz

    1."."为通配符,表示任何一个字符,例如:"a.c"可以匹配"anc"."abc"."acc": ...

  3. BZOJ1075 : [SCOI2007]最优驾车drive

    设$f[i][j][k]$为到达$(i,j)$,用时为$\frac{k}{5lcm}$小时的最低耗油量,然后DP即可. #include<cstdio> const int N=12,M= ...

  4. POJ 2342 (树形DP)

    题目链接: http://poj.org/problem?id=2342 题目大意:直属上司和下属出席聚会.下属的上司出现了,下属就不能参加,反之下属参加.注意上司只是指直属的上司.每个人出席的人都有 ...

  5. asp.net 微信企业号办公系统-流程设计--保存与发布

    如果流程未设计完时可以先保存,以后再打开接着设计.点击工具栏上的保存按钮即可保存当前流程设计: 如果下次要接着设计,则可以打开该流程继续设计: 如果流程设计完成,可以点击安装按钮来发布流程,流程安装成 ...

  6. hdu Pie

    这道题是一道二分搜索的题,首先计算出最大的平均体积:mx=V总/f:然后去left=0,right=mx,mid=(left+right)/2进行二分搜索,当所有pi分割出的mid的个数是大于等于f时 ...

  7. fastjson 常用api

    一.json字符串的数据解析      1.json字符串 ---> JSONObject或者JSONArray[好处就是当你没有bean的model类时,可以直接获取相关数据]         ...

  8. SDR和DDR1/2/3全系列频率对照表

  9. ZooKeeper应用场景介绍

    ZooKeeper是一个高可用的分布式数据管理与系统协调框架.维护着一个树形层次结构,书中的节点被称为znode.znode可以用来存储数据,并且有一个与之相关联的ACL(权限),znode不能大于1 ...

  10. navicat从下载到使用

    ☆准备工作 确保电脑安装了mysql数据库 确定my.ini下的字符集设置为utf8 ☆下载navicat 输入网址 https://www.navicat.com 点击Downloads 点击Dow ...