Good articles to my personal technology blog: https://cainluo.github.io/15099354591154.html


In the last two articles, we talked about some new features in Xcode 9 that make it easier to write “bugs “.

If you do not see the friends can go to see:

  • Xcode 9 is a new feature in iOS 11.
  • Xcode 9 is a new feature in iOS 11.

So this time, let’s take a quick look at what UIKit has updated in iOS 11 to help us develop faster.

Reprint statement: if you need to reprint this article, please contact the author, and indicate the source, and can not modify this article without authorization.


Paste configuration

As we all know, there is a thing called UIMenuController in iOS. It is a singleton, which allows us to do some simple operations like copy and paste, but in iOS 11 the paste function has evolved. Let’s take a look.

Just something simple to display.

Then, we need to have a manager MenuManager that uses gestures to operate UIMenuController, the detailed code is in the project, you can go to see.

In iOS 11, Apple came out with something called UIPasteConfiguration, which is a direct inheritance of NSObject.

The interface that an object implements to declare its ability to accept specific data types for pasting and for drag and drop activities.

What can this be used for?


Configuring the Paste Function

In the project, by default, we added a long press gesture and a click gesture to the TableView to control the UIMenuController.

In order to demonstrate the paste function, we need to declare a global string to give the paste function a unique identifier:

@property (nonatomic.copy) NSArray<NSString *> *acceptableTypeIdentifiers;
Copy the code

With this unique identifier, we need to add a change to the copy: method in the Cell:

- (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];
}
Copy the code

Here, CELL_TYPE is the unique identifier of the global.

Also, configure it in the PasteViewController that requires the paste function:

    UIPasteConfiguration *pasteConfiguration = [[UIPasteConfiguration alloc] initWithAcceptableTypeIdentifiers:@[CELL_TYPE]];
        
    self.pasteConfiguration = pasteConfiguration;
Copy the code

And here we have to rewrite a method:

- (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:@" Content copied: %@", model.titleString]; }); }}]; }}Copy the code

Used to process pasted data.

PS: hereTableViewCellModelThere is one that needs to be followedNSItemProviderReadingProtocol, and internal implementation of its protocol method, details can go to the code to see.


Basic understanding of drag and drop

In iOS 11, Apple’s dad finally added drag and drop, but the real benefit of this feature is the iPad, which can copy and move data between split-screen apps and even share them.

As we drag, the data will be serialized, and then displayed in the system control preview that the user drags. After the drag is complete, the serialized data will be copied to the destination, then deserialized, and finally presented to the user.

The first two controls to gain support were UITableView and UICollectionView. Now let’s create a new project to see how it works.

Here we have a simple TableView:

So here we’re going to introduce two new proxies UITableViewDragDelegate and UITableViewDropDelegate, one for dragging, one for dropping.

NSItemProviderReading, NSItemProviderWriting, NSItemProviderWriting

The last thing we need to implement drag and drop is to implement the two proxy methods:

#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];
}
Copy the code

After writing the code, don’t forget to turn on the drag and drop function of the TableView:

        _tableView.dragInteractionEnabled = YES;
Copy the code

I will not put the renderings here, I will run the Demo. I think the code I wrote is quite neat ~~ haha

More details will be explained in subsequent articles.


TableView sidebar improvements

In iOS 8, Apple introduced a sidebar feature for TableViews called UITableView Action, but in iOS 11, Apple added a more flexible feature, Called UISwipeActionsConfiguration:

Let’s create another project to look at and implement our configuration:

- (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;
}
Copy the code

We also have a special API for TableView refresh:

- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion API_AVAILABLE(ios(11.0), tvos(11.0));
Copy the code

Dispatch_async (dispatch_get_main_queue(), ^{}); To update, cool drop


Asset UIColor integration

In Xcode 9, Asset can integrate with UIColor’s directory, so we can skip declaring a bunch of colors. How do we do that? Let’s take a look at it. We can just pick a random project here.

Then we add Color Set to assets.xcassets:

Then add your favorite color value:

Here we’re going to look at two apis, both of which came out after iOS 11

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

+ (nullable UIColor *)colorNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection
Copy the code

End result:


Newly added accessibility features

While we’re at it, here’s a real device with iOS 11.

However, since I do not have an iOS 11 device, I will not talk about it here for the time being. If you are interested, you can go to Baidu to search, or update it when I have an iOS 11 device.


conclusion

In iOS 11, there are more things to optimize and improve the development process. This article is just a brief introduction, and you can also check out the official Documentation of Apple, or watch the WWDC video demo:

  • New in Cococa Touch: apple.co/2vy2mOo
  • Update iOS 11 app: apple.co/2syu3Tt
  • New barrier-free feature: apple.co/2r9EASD

The project address

The address of the project: https://github.com/CainRun/iOS-11-Characteristic/tree/master/2.UIKit


The last