内容概要:

  本文先讲解了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. BZOJ4294 : [PA2015]Fibonacci

    斐波那契数列模$10^m$的循环节为$6\times10^m$,于是从低位到高位dfs即可. #include<cstdio> #include<cstring> #defin ...

  2. 【wikioi】1553 互斥的数(hash+set)

    http://wikioi.com/problem/1553/ 一开始我也知道用set来判a[i]/p是否在集合中,在的话就直接删掉. 但是我没有想到要排序,也没有想到当存在a,b使得a/p==b时到 ...

  3. 【COGS】714. USACO 1.3.2混合牛奶(贪心+水题)

    http://cojs.tk/cogs/problem/problem.php?pid=714 在hzwer的刷题记录上,默默地先跳过2题T_T...求凸包和期望的..T_T那是个啥..得好好学习 看 ...

  4. javamail发送邮件的简单实例

    今天学习了一下JavaMail,javamail发送邮件确实是一个比较麻烦的问题.为了以后使用方便,自己写了段代码,打成jar包,以方便以后使用.呵呵 以下三段代码是我的全部代码,朋友们如果想用,直接 ...

  5. jquery easyui datagrid 分页详解

    由于项目原因,用了jquery easyui 感觉界面不错,皮肤样式少点,可是官网最近打不开了,资料比较少,给的demo没有想要的效果,今天在用datagrid 做分页显示的时候,折腾了半天,网上的资 ...

  6. 封装同步的UIActionSheet

    封装同步的UIActionSheet 发问题 做 iOS 开发的同学想必都用过 UIActionSheet.UIActionSheet 可以弹出一个选择列表,让用户选择列表中的某一项操作.使用 UIA ...

  7. Cite a Website in Paper 论文中引用网页的格式

    Template: 1.A. Author Surname, 'Title', Year Published, <http://Website-Url> (accessed 10 Octo ...

  8. How to override create,write,unlink method in Odoo v8

    As we all know, Odoo 8 has new api which is different with v7. So how to override the create,write,u ...

  9. Shtml妙用

    shtml用的是SSI指令, SSI指令虽然不多 但是功能相对而言还是很强大的, 在PHP禁止了命令执行函数和开了安全模式的时候可以试试看 也可以在服务器允许上传shtml后缀脚本的时候试试 PS:只 ...

  10. emacs+ensime+sbt打造spark源码阅读环境

    欢迎转载,转载请注明出处,徽沪一郎. 概述 Scala越来越流行, Spark也愈来愈红火, 对spark的代码进行走读也成了一个很普遍的行为.不巧的是,当前java社区中很流行的ide如eclips ...