玩轉iOS開發:iOS 11 新特性《UIKit新特性的基本認識》

文章分享至個人我的技術博客: https://cainluo.github.io/15099354591154.htmlhtml


前兩篇, 咱們講了Xcode 9的一些新特性, 能夠更加方便咱們去寫"bug".ios

若是沒有看的朋友能夠去看看:git

那麼這一次呢, 咱們來簡單的瞭解一下, 在iOS 11裏, UIKit更新了一些什麼東西, 可讓咱們更加快捷的開發.github

轉載聲明:如須要轉載該文章, 請聯繫做者, 而且註明出處, 以及不能擅自修改本文.微信


Paste configuration

咱們都知道, 在iOS有一個東西叫作UIMenuController, 它是一個單例, 能夠方便咱們簡單的去作一些複製, 粘貼等等的操做, 但在iOS 11這個粘貼功能進化了, 讓咱們一塊兒來看看吧, 首先咱們要有一個工程項目:session

1

簡單顯示的東西就好.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裏實現數據複製和移動, 甚至還能夠共享.

咱們在拖動的過程當中, 數據會被序列化, 而後呈如今用戶拖動的系統控制預覽中, 在拖動完成後, 序列化的數據會被複制到目的地, 而後反序列化, 最終將這些信息呈獻給用戶.

而最早得到支持的兩個控件就是UITableViewUICollectionView. 如今讓咱們來新建個工程看看是如何操做.

這裏咱們仍是一個簡單的TableView:

2

這裏咱們要介紹兩個新的代理UITableViewDragDelegate, 和UITableViewDropDelegate, 一個分別拖動, 一個分別是放下的代理.

這裏咱們要聲明一個遵照了NSItemProviderReading, NSItemProviderWritingModel, 內部實如今工程裏查看:

最終咱們去實現拖放功能的就是要去實現那兩個代理的方法:

#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就行了, 我的認爲本身寫的代碼仍是挺規整的~~哈哈

更詳細的內容會在後續的文章慢慢講解.


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 *)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;
}
複製代碼

3
4

關於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:

5

而後添加本身喜歡的顏色值:

6

7

這裏咱們要看看兩個API, 都是在iOS 11以後纔出來的

+ (nullable UIColor *)colorNamed:(NSString *)name

+ (nullable UIColor *)colorNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection
複製代碼

最終效果:

8


新添加的輔助功能

在講這個得時候, 這裏是須要裝有iOS 11的真機設備.

但因爲我如今手上沒有iOS 11的設備, 因此這裏暫時不說, 有興趣的話, 能夠到百度去搜搜, 或者等我iOS 11設備的時候再更新吧.


總結

iOS 11更多的東西都是在優化和改進開發的流程, 這篇張文章只是簡單的介紹一下而已, 還有更多更深層次的能夠自行去查閱蘋果的官方文檔, 或者是去看看WWDC的視頻演示:


工程地址

項目地址: https://github.com/CainRun/iOS-11-Characteristic/tree/master/2.UIKit


最後

碼字很費腦, 看官賞點飯錢可好

微信

支付寶
相關文章
相關標籤/搜索