玩转iOS开发:iOS 11 新特性《UICollectionView的拖拽》
文章分享至我的个人技术博客: cainrun.github.io/15102983446…
还记得在WWDC 2017的时候, 苹果爸爸展示的拖拽功能是多么的牛逼, 实现了可夸应用的数据分享.
如果你有看过之前的, 那么你应该有一个基础的认识, 如果没有也没关系, 因为你正在看着这篇文章.
这里我们会用一个针对iPad Pro 10.5英寸的小项目进行演示.
转载声明:如需要转载该文章, 请联系作者, 并且注明出处, 以及不能擅自修改本文.
工程的配置
这里我打算使用Storyboard来作为主开发的工具, 为了省下过多的布局代码.
1这是模仿一个顾客去买水果的场景, 这里面的布局也不算难, 主要逻辑:
- 主容器控制器嵌入两个比较小的视图控制器, 通过
ListController分别管理. ListController主要是显示一个UICollectionView, 而我们拖拽也是在ListController里实现的.
简单的写了一下数据模型, 并且控制一下对应的数据源, 我们就可以看到简单的界面了:
2配置拖拽的功能
配置UICollectionView其实是非常容易的, 我们只需要将一个声明UICollectionViewDragDelegate代理的实例赋值给UICollectionView, 然后再实现一个方法就可以了.
接下来这里, 我们设置一下拖拽的代理, 并且实现必要的拖拽代理方法:
self.collectionView.dragDelegate = self;
self.collectionView.dropDelegate = self;#pragma mark - Collection View Drag Delegate
- (NSArray<UIDragItem *> *)collectionView:(UICollectionView *)collectionView
itemsForBeginningDragSession:(id<UIDragSession>)session
atIndexPath:(NSIndexPath *)indexPath {
NSItemProvider *itemProvider = [[NSItemProvider alloc] init];
UIDragItem *item = [[UIDragItem alloc] initWithItemProvider:itemProvider];
return @[item];
}这样子我们就可以看到长按CollectionView时会有长按拖拽效果了:
3配置拖放的"放"效果
拖拽效果有了, 但问题来了, 当我们拖拽到另一个UICollectionView松手时, 会发现并不能将数据拖拽过去, 其实是我们并没有配置UICollectionViewDropDelegate代理, 这个和刚刚的配置方法一样, 这里就不多说了.
首先我们来实现一个方法:
- (BOOL)collectionView:(UICollectionView *)collectionView
canHandleDropSession:(id<UIDropSession>)session {
return session.localDragSession != nil ? YES : NO;
}这个可选方法是在咨询你会否愿意处理拖放, 我们可以通过实现这个方法来限制从同一个应用发起的拖放会话.
这个限制是通过UIDropSession中的localDragSession进行限制, 如果为YES, 则表示接受拖放, 如果为NO, 就表示不接受.
讲完这个之后, 我们来看看UICollectionViewDropDelegate唯一一个要实现的方法, 这个方法要有相应, 是根据上面的那个方法是返回YES还是返回NO来判断的:
- (void)collectionView:(UICollectionView *)collectionView
performDropWithCoordinator:(id<UICollectionViewDropCoordinator>)coordinator {
}然后我们配置好UICollectionViewDropDelegate的代理对象, 再试试拖拽效果, 机会发现拖到隔壁的UICollectionView的右上角会有一个绿色的加好:
4配置你的意图
我们在UICollectionView里拖动一个对象的时候, UICollectionView会咨询我们的意图, 然后根据我们不同的配置, 就会做出不同的反应.
这里我们要分成两个部分, 第一个部分是一个叫做UIDropOperation:
typedef NS_ENUM(NSUInteger, UIDropOperation) {
UIDropOperationCancel = 0,
UIDropOperationForbidden = 1,
UIDropOperationCopy = 2,
UIDropOperationMove = 3,
} API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);- UIDropOperationCancel: 表示取消拖动操作, 如果是使用这个枚举的话, 会导致
-dropInteraction:performDrop:这个方法不被调用. - UIDropOperationForbidden: 表示该操作被禁止, 如果你是使用这个枚举的话, 在拖拽时会显示一个