玩转iOS开发:iOS 11 新特性《UICollectionView的拖拽》
文章分享至我的个人技术博客: cainrun.github.io/15102983446…
还记得在WWDC 2017
的时候, 苹果爸爸展示的拖拽功能是多么的牛逼, 实现了可夸应用的数据分享.
如果你有看过之前的, 那么你应该有一个基础的认识, 如果没有也没关系, 因为你正在看着这篇文章.
这里我们会用一个针对iPad Pro 10.5
英寸的小项目进行演示.
转载声明:如需要转载该文章, 请联系作者, 并且注明出处, 以及不能擅自修改本文.
工程的配置
这里我打算使用Storyboard
来作为主开发的工具, 为了省下过多的布局代码.
这是模仿一个顾客去买水果的场景, 这里面的布局也不算难, 主要逻辑:
- 主容器控制器嵌入两个比较小的视图控制器, 通过
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
时会有长按拖拽效果了:
配置拖放的"放"效果
拖拽效果有了, 但问题来了, 当我们拖拽到另一个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
的右上角会有一个绿色的加好:
配置你的意图
我们在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: 表示该操作被禁止, 如果你是使用这个枚举的话, 在拖拽时会显示一个