简体   繁体   中英

Slow iOS Share Extension

I'm working on a sharing extension to simply grab a link, choose a few names to share it to, and Share. The data layer isn't added yet, only the UI to display some names in a tableview (using a custom cell) and I'm pulling in the shared URL from the extension context. All of the code in the VC is below. All views are set up in the Storyboard. Two UIButtons, Two UILabels, One TableView and a UIView to hold it all, so I can easily round the corners.

在此输入图像描述

The issue I'm having is that the _linkLabel that I'm using the display the URL doesn't visually update for nearly 10 seconds! What.In.The.World. What I'm a doing here that's causing this?

I'm logging out the URL in the callback from hasItemConformingToTypeIdentifier and it happens as soon as the extension appears, but doesn't update the label??!! Helps. Please.

#import "ShareViewController.h"
#import "UserCell.h"

@interface ShareViewController ()

@end

@implementation ShareViewController

- (void)viewDidLoad{
    self.view.alpha = 0;
    _friends = [@[@"Ronnie",@"Bobby",@"Ricky",@"Mike"] mutableCopy];
    _containerView.layer.cornerRadius = 6.f;
    _selectedIndexPaths = [[NSMutableArray alloc] init];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [UIView animateWithDuration:0.5 animations:^{
        self.view.alpha = 1;
    }];
}

- (void)viewDidAppear:(BOOL)animated{
    //pull the URL out
    NSExtensionItem *item = self.extensionContext.inputItems[0];
    NSItemProvider *provider = item.attachments[0];
    if ([provider hasItemConformingToTypeIdentifier:@"public.url"]) {
        [provider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
            NSURL *url = (NSURL*)item;
            _linkLabel.text = url.absoluteString;
            NSLog(@"Link: %@", url.absoluteString);
        }];
    }
    else{
        NSLog(@"No Link");
    }
}

#pragma mark - UITableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UserCell *cell = (UserCell*)[tableView cellForRowAtIndexPath:indexPath];
    if([_selectedIndexPaths containsObject:indexPath]){
        [_selectedIndexPaths removeObject:indexPath];
        cell.selected = NO;
    }
    else{
        cell.selected = YES;
        [_selectedIndexPaths addObject:indexPath];
    }
    NSLog(@"Share to %i friends", (int)[_selectedIndexPaths count]);
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    //Later, calc height based on text in comment
    return  44;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [_friends count];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @"UserCell";
    UserCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil){
        cell = [[UserCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    cell.selected = ([_selectedIndexPaths containsObject:indexPath]) ? YES : NO;
    cell.nameLabel.text = [_friends objectAtIndex:indexPath.row];
    return cell;
}

- (IBAction)dismiss {
    [UIView animateWithDuration:0.34 animations:^{
        self.view.alpha = 0;
    } completion:^(BOOL finished) {
        [self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
    }];
}

@end

Delays in updates to UI elements is a classic sign of trying to update the UI from outside the main queue. Which is what is happening here. You have this:

[provider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
    NSURL *url = (NSURL*)item;
    _linkLabel.text = url.absoluteString;
    NSLog(@"Link: %@", url.absoluteString);
}];

Except that NSItemProvider does not guarantee that the completion handler will be called on the same queue that you started on. You're almost guaranteed to be on a different queue here, so you're getting this weird delay. You need to dispatch back to the main queue to perform the update:

[provider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSURL *url = (NSURL*)item;
        _linkLabel.text = url.absoluteString;
        NSLog(@"Link: %@", url.absoluteString);
    });
}];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM