简体   繁体   中英

How to cancel a function when a user taps on or scrolls through a UITableView?

For my MatchCenterViewController , I have it set to run the MatchCenter function in viewDidAppear , after a 2 second time interval. This function populates the UITableView with text and images. The issue is, when a user tries to either scroll through the UITableView or tap on any cell from the moment MatchCenterViewController appears until the MatchCenter function is done loading, the app crashes.

It seems to be happening because if a user scrolls or taps on a cell to open up the model 'WebViewSegue', it conflicts with the MatchCenter function which is attempting to populate/update the table. What I want to happen is, if a user starts to scroll through the table or taps on a cell, then the MatchCenter function in viewDidAppear exits.

How would I form this syntax, and once I do, will I have to put this in both 'didSelectRowAtIndexPath' and a separate function, to take into account scrolling as well?

MatchCenterViewController.m:

#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>

@interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *matchCenter;
@end

@implementation MatchCenterViewController


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
    self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
    _matchCenter.dataSource = self;
    _matchCenter.delegate = self;
    [self.view addSubview:self.matchCenter];

    _matchCenterArray = [[NSArray alloc] init];
}

- (void)viewDidAppear:(BOOL)animated
{
    self.matchCenterArray = [[NSArray alloc] init];

    // Delay to allow MatchCenter item enough time to be added before pinging ebay
    [NSThread sleepForTimeInterval:2];

    [PFCloud callFunctionInBackground:@"MatchCenter"
                       withParameters:@{}
                                block:^(NSArray *result, NSError *error) {

                                    if (!error) {
                                        _matchCenterArray = result;
                                        [_matchCenter reloadData];

                                        NSLog(@"Result: '%@'", result);
                                    }
                                }];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return _matchCenterArray.count;
}

//the part where i setup sections and the deleting of said sections

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 21.0f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 0.01f;
}


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
    headerView.backgroundColor = [UIColor lightGrayColor];

    _searchTerm = [[[[_matchCenterArray  objectAtIndex:section] objectForKey:@"Top 3"] objectAtIndex:3]objectForKey:@"Search Term"];

    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
    headerLabel.text = [NSString stringWithFormat:@"%@", _searchTerm];
    headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
    headerLabel.textColor = [UIColor whiteColor];
    headerLabel.backgroundColor = [UIColor lightGrayColor];
    [headerView addSubview:headerLabel];


    UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
    deleteButton.tag = section;
    deleteButton.frame = CGRectMake(300, 2, 17, 17);
    [deleteButton setImage:[UIImage imageNamed:@"xbutton.png"] forState:UIControlStateNormal];
    [deleteButton addTarget:self action:@selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [headerView addSubview:deleteButton];
    return headerView;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 3;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Initialize cell
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        // if no cell could be dequeued create a new one
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    // No cell seperators = clean design
    tableView.separatorColor = [UIColor clearColor];

    // title of the item
    cell.textLabel.text = _matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Title"];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:14];

    // price of the item
    cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@", _matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Price"]];
    cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];

    // image of the item
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Image URL"]]];
    [[cell imageView] setImage:[UIImage imageWithData:imageData]];

    return cell;

}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 65;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    self.itemURL = _matchCenterArray[indexPath.section][@"Top 3"][indexPath.row][@"Item URL"];
    [self performSegueWithIdentifier:@"WebViewSegue" sender:self];
}

- (void)deleteButtonPressed:(id)sender
{
    // links button
    UIButton *deleteButton = (UIButton *)sender;

    // Define the sections title
    NSString *sectionName = _searchTerm = [[[[_matchCenterArray  objectAtIndex:deleteButton.tag] objectForKey:@"Top 3"] objectAtIndex:3]objectForKey:@"Search Term"];

    // Run delete function with respective section header as parameter
    [PFCloud callFunctionInBackground:@"deleteFromMatchCenter"
                       withParameters:
                      @{@"searchTerm": sectionName,}
                                block:^(NSDictionary *result, NSError *error) {
                                   if (!error) {
                                       [PFCloud callFunctionInBackground:@"MatchCenter"
                                                          withParameters:@{
                                                                           @"test": @"Hi",
                                                                           }
                                                                   block:^(NSArray *result, NSError *error) {

                                                                       if (!error) {
                                                                           _matchCenterArray = result;
                                                                           [_matchCenter reloadData];

                                                                           NSLog(@"Result: '%@'", result);
                                                                       }
                                                                   }];

                                   }
                                }];
}



- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}



 #pragma mark - Navigation

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
 {
     WebViewController *controller = (WebViewController *) segue.destinationViewController;
     controller.itemURL = self.itemURL;
 }


@end

You are blocking on the main thread! Not good! See this question: NSThread sleepfortimeinterval blocks main thread

A much better way to have a delay is to use GCD. Try this instead:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [PFCloud callFunctionInBackground:@"MatchCenter"
                       withParameters:@{}
                                block:^(NSArray *result, NSError *error) {
                                    if (!error) {
                                        // Might not be necessary, but it would be good to  check to make
                                        // sure _matchCenterArray and _matchCenter still exist.
                                        if (_matchCenterArray && _matchCenter) {
                                            // I am not sure if this block is invoked on the main thread
                                            dispatch_async(dispatch_get_main_queue(), ^{
                                                _matchCenterArray = result;
                                                [_matchCenter reloadData];

                                                NSLog(@"Result: '%@'", result);
                                            })
                                        }
                                    }
                                }];
});

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