文章分享至個人我的技術博客: https://cainluo.github.io/15099354591154.htmlhtml
前兩篇, 咱們講了Xcode 9
的一些新特性, 能夠更加方便咱們去寫"bug
".ios
若是沒有看的朋友能夠去看看:git
那麼這一次呢, 咱們來簡單的瞭解一下, 在iOS 11
裏, UIKit
更新了一些什麼東西, 可讓咱們更加快捷的開發.github
轉載聲明:如須要轉載該文章, 請聯繫做者, 而且註明出處, 以及不能擅自修改本文.微信
咱們都知道, 在iOS
有一個東西叫作UIMenuController
, 它是一個單例, 能夠方便咱們簡單的去作一些複製, 粘貼等等的操做, 但在iOS 11
這個粘貼功能進化了, 讓咱們一塊兒來看看吧, 首先咱們要有一個工程項目:session
簡單顯示的東西就好.app
而後呢, 咱們須要有一個用手勢操做UIMenuController
的管理者MenuManager
, 詳細的代碼都在工程裏, 你們能夠去看看.async
在iOS 11
的時候, 蘋果推出了一個東西叫作UIPasteConfiguration
, 它是直接繼承NSObject
官方解釋:ide
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 *)tableView
performDropWithCoordinator:(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 *)tableView
canHandleDropSession:(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
就行了, 我的認爲本身寫的代碼仍是挺規整的~~哈哈
更詳細的內容會在後續的文章慢慢講解.
在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 *)tableView
leadingSwipeActionsConfigurationForRowAtIndexPath:(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(), ^{});
去更新了, 爽爽滴~~
在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
的視頻演示:
項目地址: https://github.com/CainRun/iOS-11-Characteristic/tree/master/2.UIKit