一、UIcollectionView介绍

1.1、简介

首先看苹果官方文档 UICollectionView Class Reference 的介绍:

The UICollectionView class manages an ordered collection of data items and presents them using customizable layouts. Collection views provide the same general function as table views except that a collection view is able to support more than just single-column layouts. Collection views support customizable layouts that can be used to implement multi-column grids, tiled layouts, circular layouts, and many more. You can even change the layout of a collection view dynamically if you want.

在WWDC2012中的Introducing Collection Views,苹果首次介绍了UICollectionView,类似UITableView的用法使人很容易接受,但强大的自定义布局,又使其相较于UITableView有了选择它的更多理由,UITableView中的表格只支持单排列表,没有办法支持网格列表模式。

一句话总结就是:UICollectionView与UITableView相似,却提供了可自定义多列网格(Grild)的功能。

下面通过一张图片来了解UICollectionView的构成:

 
text

1.2、UICollectionView用来做什么

 
 

UICollectionView 类用于管理有序的数据单元,并且可以定制化的显示他们。UICollectionView 除了提供和tableview相同的一般的方法外,还支持一列以上的布局。UICollectionView 支持的定制化布局能够实现网格或是瓷砖的布局效果。你甚至可以动态的改变Collectionview的布局。

二、UICollectionView与UITableView比较

2.1、UICollectionViewDataSource

UICollectionViewDelegate-负责提供展示的数据,实现下面两个必须的委托方法,其实与UITableView并无二意

  • numberOfItemsInsection: 某个Section里面有多少item
  • cellForItemAtIndexPath: 对于某个位置应该显示什么样的cell,里面会涉及到cell的复用,可参考UITableView

2.2、UICollectionViewDelegate

UICollectionViewDelegate-负责用户的交互、cell的外形,委托方法和UITableView相似,可以选择性实现以下委托方法。

  • collectionView:shouleHighlightItemAtIndexPath:是否支持高亮?
  • collectionView:didHighlightItemAtIndexPath:如果支持高亮,那么高亮;
  • collectionView:shouldSelectItemAtIndexPath:询问是否可以被选中?
  • collectionView:didUnhighlightItemAtIndexPath:如果支持高亮,那么现在取消高亮;
  • collectionView:didSelectItemAtIndexPath:如果支持可以被选中,那么选中 cell;

2.3、UICollectionViewLayout

在布局上,与UITableView直接使用系统提供的样式,UICollectionView使用的是UICollectionViewLayout来自定义布局样式。

  • UICollectionViewLayout是一个抽象基类,需要继承它来为CollectionView生成Layout信息。Layout对象的作用是决定Cells,Supplementary Views和Decoration Views在CollectionView中的布局位置。系统也提供了UICollectionViewFlowLayout-l流水式布局效果
  • UICollectionView的显示效果几乎全部由UICollectionViewLayout负责,而真正存储着每一个cell的位置、大小等属性的是UICollectionViewLayoutAttributes。每一个cell对应着一个属于自己的UICollectionViewLayoutAttributes,而UICollectionViewLayout正是利用UICollectionViewLayoutAttributes里存在的信息对每一个cell进行布局。

三、UICollectionView层次结构

UICollectionView类负责管理数据的有序集合以及以自定义布局的模式来呈现这些数据,它提供了一些常用的表格功能,此外还增加了许多单栏布局。UICollectionView支持可以用于实现多列网格、平铺的布局、圆形的布局和更多的自定义布局,甚至可以动态的改变它的布局。

 
 

3.1、UICollectionView基本使用

我们要使用UICollectionView得实现UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout这三个协议。UICollectionViewDataSource是它的数据源,UICollectionDelegate是它的呈现样式,UICollectionViewDelegateFlowLayout是它的布局样式。

3.1.1 初始化

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

UICollectionView *colView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];

3.1.2 注册UICollectionView使用的cell类型

[colView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"myCell"];

3.1.3 设置代理

colView.delegate = self;

colView.dataSource = self;

3.1.4 实现协议UICollectionViewDataSource

//配置UICollectionView的每个section的item数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [[self loadData] count];
} //配置section数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
} //呈现数据
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"myCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}

3.1.5 UICollectionViewDelegateFlowLayout

//配置每个item的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100, 60);
} //配置item的边距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(20, 20, 0, 20);
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(200, 60);
}

3.1.6 UICollectionViewDelegate

复制代码
//点击item时触发
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"您点击了item:%@", [[self loadData] objectAtIndex:indexPath.row]);
[collectionView cellForItemAtIndexPath:indexPath].backgroundColor = [UIColor redColor]; } //当前item是否可以点击
- (BOOL) collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
if (indexPath.row % 2)
{
return YES;
} return NO;
}
//cell点击时是否高亮,点击cell时的样式和点击后cell的样式
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
} - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
} - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor grayColor];
}
 
 

3.2、自定义UICollectionViewFlowLayout

使用UICollectionViewFlowLayout之前,我们来了解它内部常用的属性

//同一组当中,垂直方向:行与行之间的间距;水平方向:列与列之间的间距
@property (nonatomic) CGFloat minimumLineSpacing;
//垂直方向:同一行中的cell之间的间距;水平方向:同一列中,cell与cell之间的间距
@property (nonatomic) CGFloat minimumInteritemSpacing;
//每个cell统一尺寸
@property (nonatomic) CGSize itemSize;
//滑动反向,默认滑动方向是垂直方向滑动
@property (nonatomic) UICollectionViewScrollDirection scrollDirection;
//每一组头视图的尺寸。如果是垂直方向滑动,则只有高起作用;如果是水平方向滑动,则只有宽起作用。
@property (nonatomic) CGSize headerReferenceSize;
//每一组尾部视图的尺寸。如果是垂直方向滑动,则只有高起作用;如果是水平方向滑动,则只有宽起作用。
@property (nonatomic) CGSize footerReferenceSize;
//每一组的内容缩进
@property (nonatomic) UIEdgeInsets sectionInset;
 
 

3.2.1 NYWaterflowLayout(瀑布流样式)

NYWaterflowLayout继承与UICollectionViewLayout 重写部分方法

核心代码

- (void)prepareLayout
{
[super prepareLayout]; // 清楚以前计算的所有高度
[self.columnHeights removeAllObjects];
for (NSInteger i = 0; i < self.columnCount; i++) {
[self.columnHeights addObject:@(self.edgeInsets.top)];
} // 清楚之前所有的布局属性
[self.attrsArray removeAllObjects];
// 开始创建每一个cell对应的布局属性
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger i = 0; i < count; i++) {
//创建位置
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attrsArray addObject:attributes];
}
}
// 决定cell的排布
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
return self.attrsArray;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 创建布局属性
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; // collectionView的宽度
CGFloat collectionViewWidth = self.collectionView.frame.size.width; // 设置布局属性的frame
CGFloat width = (collectionViewWidth - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
CGFloat h = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:width];
// CGFloat h = 50 + arc4random_uniform(100); // 找出高度最短的那一列
__block NSInteger destColumn = 0;
__block CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
[self.columnHeights enumerateObjectsUsingBlock:^(NSNumber *columnHeightNumber, NSUInteger idx, BOOL * _Nonnull stop) {
CGFloat columnHeight = columnHeightNumber.doubleValue;
if (minColumnHeight > columnHeight) {
minColumnHeight = columnHeight;
destColumn = idx;
}
}]; // 获取最短列的xy
CGFloat x = self.edgeInsets.left + destColumn * (width + self.columnMargin);
CGFloat y = minColumnHeight;
if (y != self.edgeInsets.top) {
y += self.rowMargin;
} attributes.frame = CGRectMake(x, y, width, h); //更新最短那列的高度
self.columnHeights[destColumn] = @(CGRectGetMaxY(attributes.frame)); return attributes;
}
// 设置CollectionViewContentSize
- (CGSize)collectionViewContentSize
{
__block CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];
[self.columnHeights enumerateObjectsUsingBlock:^(NSNumber *columnHeightNumber, NSUInteger idx, BOOL * _Nonnull stop) {
CGFloat columnHeight = columnHeightNumber.doubleValue;
if (maxColumnHeight < columnHeight) {
maxColumnHeight = columnHeight;
}
}];
return CGSizeMake(0, maxColumnHeight + self.edgeInsets.bottom);
}

NYWaterflowLayoutDelegate

@required
- (CGFloat)waterflowLayout:(NYWaterflowLayout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth; @optional
// 瀑布流布局的列数
- (NSInteger)columnCountInWaterflowLayout:(NYWaterflowLayout *)waterflowLayout;
// 列间距
- (CGFloat)columnMarginInWaterflowLayout:(NYWaterflowLayout *)wateflowLayout;
// 行间距
- (CGFloat)rowMarginInWaterflowLayout:(NYWaterflowLayout *)waterflowLayout;
// 边沿间距
- (UIEdgeInsets)edgeInsetsInWaterflowLayout:(NYWaterflowLayout *)waterflowLayout;

效果图

 
 

3.2.2 NYCircularLayout(环形布局)

核心代码

- (void)prepareLayout
{
[super prepareLayout]; // 获取item的个数
_itemCount = (int)[self.collectionView numberOfItemsInSection:0];
_attributeArray = [[NSMutableArray alloc] init]; // 先设定大圆的半径取长和宽最短的
CGFloat radius = MIN(self.collectionView.frame.size.width, self.collectionView.frame.size.height)/2;
// 计算圆心的位置
CGPoint center = CGPointMake(self.collectionView.frame.size.width/2, self.collectionView.frame.size.height/2);
// 设置每个item的大小为50*50 则半径为25
for (int i = 0; i < _itemCount; i++) {
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; // 设置item的大小
attributes.size = CGSizeMake(50, 50); // 计算每个item中心的坐标 算出的x,y值还要减去item自身的半径大小
float x = center.x + cosf(2*M_PI/_itemCount * i)*(radius - 25);
float y = center.y + sinf(2*M_PI/_itemCount * i)*(radius - 25); attributes.center = CGPointMake(x, y);
[_attributeArray addObject:attributes];
}
}
// 设定区域大小
- (CGSize)collectionViewContentSize
{
return self.collectionView.frame.size;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
return _attributeArray;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 创建布局属性
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
return attributes;
}

效果图

 
 

3.2.3 CarouselViewLayout(旋转布局)

核心代码

- (void)prepareLayout {
[super prepareLayout];
if (self.visibleCount < 1) {
self.visibleCount = 3;
}
if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
_viewHeight = CGRectGetHeight(self.collectionView.frame);
_itemHeight = self.itemSize.height;
self.collectionView.contentInset = UIEdgeInsetsMake((_viewHeight - _itemHeight) / 2, 0, (_viewHeight - _itemHeight) / 2, 0);
} else {
_viewHeight = CGRectGetWidth(self.collectionView.frame);
_itemHeight = self.itemSize.width;
self.collectionView.contentInset = UIEdgeInsetsMake(0, (_viewHeight - _itemHeight) / 2, 0, (_viewHeight - _itemHeight) / 2);
}
}
- (CGSize)collectionViewContentSize {
NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];
if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
return CGSizeMake(CGRectGetWidth(self.collectionView.frame), cellCount * _itemHeight);
}
return CGSizeMake(cellCount * _itemHeight, CGRectGetHeight(self.collectionView.frame));
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];
CGFloat centerY = (self.scrollDirection == UICollectionViewScrollDirectionVertical ? self.collectionView.contentOffset.y : self.collectionView.contentOffset.x) + _viewHeight / 2;
NSInteger index = centerY / _itemHeight;
NSLog(@"第几个-----%ld",(long)index);
NSInteger count = (self.visibleCount - 1) / 2;
// 取第一个和当前位置减1的最大值
NSInteger minIndex = MAX(0, (index - count));
// 取最后一个和当前位置加1的最小值
NSInteger maxIndex = MIN((cellCount - 1), (index + count));
NSMutableArray *array = [NSMutableArray array];
//更新可视范围内的布局
for (NSInteger i = minIndex; i <= maxIndex; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[array addObject:attributes];
}
return array;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attributes.size = self.itemSize; CGFloat cY = (self.scrollDirection == UICollectionViewScrollDirectionVertical ? self.collectionView.contentOffset.y : self.collectionView.contentOffset.x) + _viewHeight / 2;
CGFloat attributesY = _itemHeight * indexPath.row + _itemHeight / 2;
attributes.zIndex = -ABS(attributesY - cY); CGFloat delta = cY - attributesY;
CGFloat ratio = - delta / (_itemHeight * 2);
CGFloat scale = 1 - ABS(delta) / (_itemHeight * 6.0) * cos(ratio * M_PI_4);
// attributes.transform = CGAffineTransformMakeScale(scale, scale); CGFloat centerY = attributesY;
switch (self.carouselAnim) {
case HJCarouselAnimRotary:
attributes.transform = CGAffineTransformRotate(attributes.transform, - ratio * M_PI_4);
centerY += sin(ratio * M_PI_2) * _itemHeight / 2;
break;
case HJCarouselAnimCarousel:
centerY = cY + sin(ratio * M_PI_2) * _itemHeight * INTERSPACEPARAM;
break;
case HJCarouselAnimCarousel1:
centerY = cY + sin(ratio * M_PI_2) * _itemHeight * INTERSPACEPARAM;
if (delta > 0 && delta <= _itemHeight / 2) {
attributes.transform = CGAffineTransformIdentity;
CGRect rect = attributes.frame;
if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
rect.origin.x = CGRectGetWidth(self.collectionView.frame) / 2 - _itemSize.width * scale / 2;
rect.origin.y = centerY - _itemHeight * scale / 2;
rect.size.width = _itemSize.width * scale;
CGFloat param = delta / (_itemHeight / 2);
rect.size.height = _itemHeight * scale * (1 - param) + sin(0.25 * M_PI_2) * _itemHeight * INTERSPACEPARAM * 2 * param;
} else {
rect.origin.x = centerY - _itemHeight * scale / 2;
rect.origin.y = CGRectGetHeight(self.collectionView.frame) / 2 - _itemSize.height * scale / 2;
rect.size.height = _itemSize.height * scale;
CGFloat param = delta / (_itemHeight / 2);
rect.size.width = _itemHeight * scale * (1 - param) + sin(0.25 * M_PI_2) * _itemHeight * INTERSPACEPARAM * 2 * param;
}
attributes.frame = rect;
return attributes;
}
break;
case HJCarouselAnimCoverFlow: {
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1.0/400.0f;
transform = CATransform3DRotate(transform, ratio * M_PI_4, 1, 0, 0);
attributes.transform3D = transform;
}
break;
default:
break;
} if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
attributes.center = CGPointMake(CGRectGetWidth(self.collectionView.frame) / 2, centerY);
} else {
attributes.center = CGPointMake(centerY, CGRectGetHeight(self.collectionView.frame) / 2);
} return attributes;
}
//当滑动停止时使得item的位置位于中心
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
CGFloat index = roundf(((self.scrollDirection == UICollectionViewScrollDirectionVertical ? proposedContentOffset.y : proposedContentOffset.x) + _viewHeight / 2 - _itemHeight / 2) / _itemHeight);
if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
proposedContentOffset.y = _itemHeight * index + _itemHeight / 2 - _viewHeight / 2;
} else {
proposedContentOffset.x = _itemHeight * index + _itemHeight / 2 - _viewHeight / 2;
}
return proposedContentOffset;
}

效果图

 

3.2.4 banner轮播器

3.2.4.1 UIScrollView实现

核心代码

//初始化ImageView
- (void)initLayoutSubview
{
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}]; CGSize size = self.scrollView.bounds.size;
_preImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
[_scrollView addSubview:_preImageView]; _currentImageView = [[UIImageView alloc] initWithFrame:CGRectMake(size.width, 0, size.width, size.height)];
[_scrollView addSubview:_currentImageView]; _nextImageView = [[UIImageView alloc] initWithFrame:CGRectMake(size.width * 2, 0, size.width, size.height)];
[_scrollView addSubview:_nextImageView]; self.scrollView.contentSize = CGSizeMake(3 * self.scrollView.bounds.size.width, 0); WS(weakSelf);
[self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(weakSelf.mas_bottom).offset(-10);
make.width.equalTo(weakSelf.mas_width);
make.height.equalTo(@(60));
}]; self.currentPage = 0;
self.pageControl.numberOfPages = self.bannersArray.count;
self.pageControl.currentPage = _currentPage; [self startTimer]; }
//准备加载页
- (void)pageLoad
{
_preImageView.image = nil;
_currentImageView.image = nil;
_nextImageView.image = nil;
_pageControl.currentPage = _currentPage; #pragma mark -设置图片
NSString *str = self.bannersArray[_currentPage == 0 ? self.bannersArray.count - 1 : _currentPage - 1];
_preImageView.image = [UIImage imageNamed:str];
str = self.bannersArray[_currentPage];
_currentImageView.image = [UIImage imageNamed:str];
str = self.bannersArray[_currentPage == self.bannersArray.count-1 ? 0 : _currentPage + 1];
_nextImageView.image = [UIImage imageNamed:str]; _scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self scrollViewDidEnd];
[self startTimer];
} - (void)scrollViewDidEnd
{
int index = _scrollView.contentOffset.x / self.window.bounds.size.width;
if (index == 0) {
_currentPage = _currentPage == 0 ? self.bannersArray.count - 1 : _currentPage - 1;
} else if (index == 2)
{
_currentPage = _currentPage + 1 == self.bannersArray.count ? 0 : _currentPage + 1;
} [self pageLoad];
}

SDCycleScrollViewhttp://www.oschina.net/p/sdcyclescrollview

效果图

 
 

附录

作者:方向_4d0d
链接:https://www.jianshu.com/p/7ffa012f34a4
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

UICollectionView框架总结的更多相关文章

  1. Instagram/IGListKit 实践谈(UICollectionView框架)

    简单介绍 IGListKit是Instagram推出的新的UICollectionView框架,使用数据驱动,旨在创造一个更快更灵活的列表控件. github地址:https://github.com ...

  2. fir.im Weekly - Swift 3.0 的迁移适配指南

    无论你是移动开发者,还是桌面端开发者,或者正在IoT领域探索的技术人员,那么应该更加关注 iDev 全平台开发者大会,也许是后半年 iOS 开发者最盛大的技术盛宴.既有知名公司带来专业视野,又有从 S ...

  3. 【转】33 个 2017 年必须了解的 iOS 开源库

    1.IGListKit,作者是Instagram Engineering Instagram 程序员做的,IGListKit 是数据驱动的 UICollectionView 框架,为了构建快速和可扩展 ...

  4. 2017 33 款iOS开源库

    IGListKit https://github.com/Instagram/IGListKit 由 Instagram 开发人员制作,IGListKit 是用于构建快速灵活列表的数据驱动型的 UIC ...

  5. 33 个 2017 年必须了解的 iOS 开源库

    本文翻译自Medium,原作者为Pawe? Bia?ecki 照片版权:(Unsplash/Markus Pe) 你好,iOS 开发者们!我的名字叫 Pawe?,我是一个独立 iOS 开发者,并且是  ...

  6. Swift 学习指引

    以下指引是基于最新的 Swift 4.0 为基础为而言. 如你在参考3.0以下版本, 那你就不要说你会 Swift, 3.0 之前是 Objective-C 的搬迁(80%),是不成熟的语言, 看着很 ...

  7. 33 个 2017 年必须了解的 iOS/swift 开源库第三方库

    本文翻译自Medium,原作者为 Paweł Białecki&lt;img src="https://pic3.zhimg.com/v2-c786777447261347b0d97 ...

  8. 开源月刊《HelloGitHub》第 62 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这里有实战项目.入门教程.黑科技.开源书籍.大厂开源项目等,涵盖多种编程语言 Pyt ...

  9. UIKit 框架之UICollectionView

    1.自定义UICollectionViewCell 在myCollectionViewCell.h中声明两个属性 // // myCollectionViewCell.h // UICollectio ...

随机推荐

  1. - > 贪心基础入门讲解四——独木舟问题

    n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? 分析: 一个显然的策略 ...

  2. Ubuntu下使用Sysvinit实现自定义服务(简单研究)

    通过上一篇文章http://www.cnblogs.com/EasonJim/p/7168216.html可以大概了解到Sysvinit的历史. 其实在自定义服务上,使用Sysvinit是最简单的,本 ...

  3. Ubuntu 16.04安装XMind 8

    下载: http://www.xmind.net/download/linux/ 解压 sudo unzip xmind-8-update2-linux.zip -d xmind8 移动到/opt目录 ...

  4. Oracle Multitenant Environment (四) Create One or More CDBs

    Using the CREATE DATABASE Statement to Create a CDB This section describes creating a CDB using the  ...

  5. C#: 旋转图片到正确位置

    当从iPhone等手机上传图片到服务器后,通常需要进行旋转处理,否则在进行图片压缩.缩放处理后会丢失正确的位置信息,导致显示的图片不处于正确的位置上. 处理的做法就是读取照片的Exif信息,并旋转到正 ...

  6. 从尾到头打印链表——剑指Offer

    https://www.nowcoder.net/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tqId=11156&tPage= ...

  7. 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用

    先看第一种情况:返回一个局部对象的引用.它的问题在于,局部对象 ----- 顾名思义 ---- 仅仅是局部的.也就是说,局部对象是在被定义时创建,在离开生命空间时被销毁的.所谓生命空间,是指它们所在的 ...

  8. SpriteBuilder&amp;Cocos2D使用CCEffect特效实现天黑天亮过度效果

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 假设认为写的不好请多提意见,假设认为不错请多多支持点赞.谢谢! hopy ;) 在动作或RPG类游戏中我们有时须要天黑和天亮过度的效果来完毕场 ...

  9. U4687 不无聊的序列

    U4687 不无聊的序列 0通过 85提交 题目提供者飞翔 标签 难度尚无评定 提交 最新讨论 暂时没有讨论 题目背景 如果一个序列的任意一个连续的子序列中没有只出现一次的元素,辣么kkk就认为这个序 ...

  10. Timus 1009. K-based Numbers

    1009. K-based Numbers Time limit: 0.5 secondMemory limit: 64 MB Let’s consider K-based numbers, cont ...