Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

enter image description here

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
like image 743
d2burke Avatar asked Mar 17 '23 22:03

d2burke


1 Answers

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);
    });
}];
like image 165
Tom Harrington Avatar answered Mar 29 '23 10:03

Tom Harrington