玩转iOS开发:iOS 11 新特性《UIKit新特性的基本认识》
来源:互联网 发布:the mac is invalid. 编辑:程序博客网 时间:2024/05/22 08:30
文章分享至我的个人技术博客: https://cainluo.github.io/15099354591154.html
前两篇, 我们讲了Xcode 9
的一些新特性, 可以更加方便我们去写"bug
".
如果没有看的朋友可以去看看:
- 玩转iOS开发:iOS 11 新特性《Xcode 9》 (一)
- 玩转iOS开发:iOS 11 新特性《Xcode 9》 (二)
那么这一次呢, 我们来简单的了解一下, 在iOS 11
里, UIKit
更新了一些什么东西, 可以让我们更加快捷的开发.
转载声明:如需要转载该文章, 请联系作者, 并且注明出处, 以及不能擅自修改本文.
Paste configuration
我们都知道, 在iOS
有一个东西叫做UIMenuController
, 它是一个单例, 可以方便我们简单的去做一些复制, 粘贴等等的操作, 但在iOS 11
这个粘贴功能进化了, 让我们一起来看看吧, 首先我们要有一个工程项目:
简单显示的东西就好.
然后呢, 我们需要有一个用手势操作UIMenuController
的管理者MenuManager
, 详细的代码都在工程里, 大家可以去看看.
在iOS 11
的时候, 苹果推出了一个东西叫做UIPasteConfiguration
, 它是直接继承NSObject
官方解释:
The interface that an object implements to declare its ability to accept specific data types for pasting and for drag and drop activities.
这个东西能用来干嘛呢?
配置粘贴功能
在项目里, 我们默认给TableView
加了长按手势和点击手势, 便于用来控制UIMenuController
.
为了方便演示这个配置粘贴的功能, 另外多开了一个控制器, 这里我们需要声明一个全局字符串, 为的就是用来给这个粘贴功能加个唯一的标识:
@property (nonatomic, copy) NSArray<NSString *> *acceptableTypeIdentifiers;
添加了这个唯一标识, 我们就需要在Cell
里给copy:
的方法加点修改:
- (BOOL)canBecomeFirstResponder { return YES;}- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return action == @selector(copy:);}- (void)copy:(id)sender { if (self.model == nil) { return; } NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.model]; [[UIPasteboard generalPasteboard] setData:data forPasteboardType:CELL_TYPE];}
这里面的CELL_TYPE
就是全局的唯一标识.
还有就是要在需要粘贴功能的控制器PasteViewController
里也配置一下:
UIPasteConfiguration *pasteConfiguration = [[UIPasteConfiguration alloc] initWithAcceptableTypeIdentifiers:@[CELL_TYPE]]; self.pasteConfiguration = pasteConfiguration;
并且这里我们还要重写一个方法:
- (void)pasteItemProviders:(NSArray<NSItemProvider *> *)itemProviders { for (NSItemProvider *item in itemProviders) { [item loadObjectOfClass:TableViewCellModel.class completionHandler:^(id<NSItemProviderReading> _Nullable object, NSError * _Nullable error) { if (object) { TableViewCellModel *model = (TableViewCellModel *)object; dispatch_async(dispatch_get_main_queue(), ^{ self.targetTextField.text = [NSString stringWithFormat:@"复制的内容: %@", model.titleString]; }); } }]; }}
用来处理粘贴后的数据.
PS: 这里的TableViewCellModel
是需要遵守一个NSItemProviderReading
协议, 并且在内部实现它的协议方法, 详情可以去代码里看看.
拖放的基本认识
在iOS 11
, 苹果爸爸终于把拖放的功能添加进来了, 但这个功能真正受益的是iPad
, 它可以在分屏App
里实现数据复制和移动, 甚至还可以共享.
我们在拖动的过程中, 数据会被序列化, 然后呈现在用户拖动的系统控制预览中, 在拖动完成后, 序列化的数据会被复制到目的地, 然后反序列化, 最终将这些信息呈献给用户.
而最先获得支持的两个控件就是UITableView
和UICollectionView
. 现在让我们来新建个工程看看是如何操作.
这里我们还是一个简单的TableView
:
这里我们要介绍两个新的代理UITableViewDragDelegate
, 和UITableViewDropDelegate
, 一个分别拖动, 一个分别是放下的代理.
这里我们要声明一个遵守了NSItemProviderReading
, NSItemProviderWriting
的Model
, 内部实现在工程里查看:
最终我们去实现拖放功能的就是要去实现那两个代理的方法:
#pragma mark - Table View Drag Delegate- (NSArray<UIDragItem *> *)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath { ListModel *model = self.dataSource[indexPath.row]; NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:model]; UIDragItem *dragItem = [[UIDragItem alloc] initWithItemProvider:itemProvider]; return @[dragItem];}#pragma mark - Table View Drop Delegate- (void)tableView:(UITableView *)tableViewperformDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator { if (!coordinator) { return; } NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath; dispatch_async(dispatch_get_main_queue(), ^{ [tableView performBatchUpdates:^{ [coordinator.items enumerateObjectsUsingBlock:^(id<UITableViewDropItem> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (!obj) { return; } NSIndexPath *indexPath = obj.sourceIndexPath; ListModel *model = self.dataSource[indexPath.row]; [self.dataSource removeObject:model]; [self.dataSource insertObject:model atIndex:destinationIndexPath.row]; [tableView moveRowAtIndexPath:indexPath toIndexPath:destinationIndexPath]; }]; } completion:nil]; });}- (BOOL)tableView:(UITableView *)tableViewcanHandleDropSession:(id<UIDropSession>)session { return [session canLoadObjectsOfClass:ListModel.class];}- (UITableViewDropProposal *)tableView:(UITableView *)tableView dropSessionDidUpdate:(id<UIDropSession>)session withDestinationIndexPath:(nullable NSIndexPath *)destinationIndexPath { return [[UITableViewDropProposal alloc] initWithDropOperation:UIDropOperationMove intent:UITableViewDropIntentInsertAtDestinationIndexPath];}
代码写完了之后, 别忘了把TableView
的拖放功能给打开:
_tableView.dragInteractionEnabled = YES;
效果图这里就不放了, 自己去跑跑Demo
就好了, 个人认为自己写的代码还是挺规整的~~哈哈
更详细的内容会在后续的文章慢慢讲解.
TableView侧边栏的改进
在iOS 8
的时候, 苹果爸爸就为TableView
引进了侧边栏的功能, 叫做UITableViewRowAction
, 不过在iOS 11
的时候, 苹果爸爸又增加了一个更加灵活的东西, 叫做UISwipeActionsConfiguration
:
我们另外建一个工程来看看, 然后实现我们的配置:
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { UIContextualAction *contextualAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"Add" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { NSLog(@"Add"); }]; contextualAction.backgroundColor = [UIColor brownColor]; UISwipeActionsConfiguration *swipeActionsCOnfiguration = [UISwipeActionsConfiguration configurationWithActions:@[contextualAction]]; return swipeActionsCOnfiguration;}- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableViewleadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { UIContextualAction *contextualAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"Copy" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { NSLog(@"Copy"); }]; contextualAction.backgroundColor = [UIColor blackColor]; UISwipeActionsConfiguration *swipeActionsCOnfiguration = [UISwipeActionsConfiguration configurationWithActions:@[contextualAction]]; return swipeActionsCOnfiguration;}
关于TableView
刷新的时候, 我们还有一个专门的API
:
- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion API_AVAILABLE(ios(11.0), tvos(11.0));
刚刚的拖放功能也是在这里面完成刷新数据源的, 这么做的话, 可以让我们的逻辑结构更加的清晰, 这样子我们也需要在使用dispatch_async(dispatch_get_main_queue(), ^{});
去更新了, 爽爽滴~~
Asset UIColor的集成
在Xcode 9
里, Asset
里可以集成UIColor
的目录, 这样子我们就可以省略声明一大堆的颜色, 详细怎么做呢? 我们一起来看看, 这里随便弄一个项目就好了.
然后我们在Assets.xcassets
里添加Color Set
:
然后添加自己喜欢的颜色值:
这里我们要看看两个API
, 都是在iOS 11
之后才出来的
+ (nullable UIColor *)colorNamed:(NSString *)name+ (nullable UIColor *)colorNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection
最终效果:
新添加的辅助功能
在讲这个得时候, 这里是需要装有iOS 11
的真机设备.
但由于我现在手上没有iOS 11
的设备, 所以这里暂时不说, 有兴趣的话, 可以到百度去搜搜, 或者等我iOS 11
设备的时候再更新吧.
总结
在iOS 11
更多的东西都是在优化和改进开发的流程, 这篇张文章只是简单的介绍一下而已, 还有更多更深层次的可以自行去查阅苹果的官方文档, 或者是去看看WWDC
的视频演示:
- Cococa Touch中的新功能:apple.co/2vy2mOo
- 更新iOS 11的应用程序:apple.co/2syu3Tt
- 无障碍新功能:apple.co/2r9EASD
工程地址
项目地址: https://github.com/CainRun/iOS-11-Characteristic/tree/master/2.UIKit
作者:CainLuo
链接:https://juejin.im/post/5a017dd7518825297a0e29ca
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。