Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>At the very least, I'd suggest checking to make sure a refresh is not already in progress. You might also want to change your <code>getEvents</code> to take the refresh control as a parameter and for it to update the pull down accordingly (so the user will know that a refresh is in progress):</p> <pre><code>- (void)viewDidLoad { [super viewDidLoad]; _imageForCalendarType = @{ @"The Irish House Music Calendar" : [UIImage imageNamed:@"music.png"] , @"FixedEvents-Student Night" : [UIImage imageNamed:@"student.png"] , @"FixedEvents-Ladies Night" : [UIImage imageNamed:@"cocktail.png"] , @"AppTest" : [UIImage imageNamed:@"football.png"] }; UIRefreshControl *refresh = [[UIRefreshControl alloc] init]; refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"]; [refresh addTarget:self action:@selector(getEvents:) forControlEvents:UIControlEventValueChanged]; self.refreshControl = refresh; [self getEvents:refresh]; } - (void)getEvents:(UIRefreshControl *)refresh { static BOOL refreshInProgress = NO; if (!refreshInProgress) { refreshInProgress = YES; refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing"]; // let the user know refresh is in progress dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // get the data here dispatch_async(dispatch_get_main_queue(), ^{ // when done, update the model and the UI here refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"]; // reset the message [refresh endRefreshing]; refreshInProgress = NO; }); }); } } </code></pre> <hr> <p>But, you should be very careful about updating your model data asynchronously (because your main queue could try to retrieve information from the model while your update is in progress). You really should defer the update of the model until that final dispatch to the main queue. But don't update the model in the middle of your asynchronous process, or else your model and UI can momentarily end up in a inconsistent state.</p> <p>Also, as a bit of a refinement, you might want to retrieve those three data sources concurrently, and you may observe a discernible performance improvement.</p> <pre><code>- (void)getEvents:(UIRefreshControl *)refresh { static BOOL refreshInProgress = NO; if (!refreshInProgress) { refreshInProgress = YES; refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing"]; // let the user know refresh is in progress // get the data here __block NSData *data1 = nil; __block NSData *data2 = nil; __block NSData *data3 = nil; dispatch_queue_t queue = dispatch_queue_create([[[[NSBundle mainBundle] bundleIdentifier] stringByAppendingString:@".network"] UTF8String], DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ data1 = [NSData dataWithContentsOfURL:sportsCalendarURL]; }); dispatch_async(queue, ^{ data2 = [NSData dataWithContentsOfURL:musicCalendarURL]; }); dispatch_async(queue, ^{ data3 = [NSData dataWithContentsOfURL:fixedCalendarURL]; }); // use dispatch barrier here, which will only fire when the previous three requests are done dispatch_barrier_async(queue, ^{ // update the UI here dispatch_async(dispatch_get_main_queue(), ^{ startDates = [NSMutableArray array]; sectionEntries = [NSMutableArray array]; entries = [NSMutableArray array]; [self fetchedData:data1]; [self fetchedData:data2]; [self fetchedData:data3]; refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"]; // reset the message [refresh endRefreshing]; sortedStartDates = [startDates sortedArrayUsingSelector:@selector(compare:)]; [self.tableView reloadData]; refreshInProgress = NO; }); }); } } </code></pre> <p>You can probably get away with a GCD concurrent queue if you have only three data sources, but if you might have more than that, you might want to use an operation queue in which you can constrain the number of concurrent requests. Also, you might consider using <a href="https://github.com/AFNetworking/AFNetworking" rel="nofollow">AFNetworking</a>, which can better coordinate these network requests with other network requests you might have going on concurrently elsewhere.</p> <p>But the main observations here are (a) don't update your model until the refresh is done and you're ready to update the UI; and (b) make sure you don't initiate a new refresh while the prior one is in progress (or, if you really need it, move to an operation queue model where you make cancelable <code>NSOperation</code> subclasses, and then you could theoretically cancel the prior request, if any, prior to issuing another update request).</p> <hr> <p>Completely unrelated to the question at hand, but in my first code snippet, you'll see that I moved the setting of the <code>_imageForCalendarType</code> out of this block (as you're always setting it to the same thing) and into <code>viewDidLoad</code>. I also eliminated this unnecessary line:</p> <pre><code>_imageForCalendarType = [[NSDictionary alloc]init]; </code></pre> <p>You discard this instantiated dictionary for the dictionary literal in the next line, so the above line is not needed. </p> <p>Frankly, you probably shouldn't even have a dictionary of <code>UIImage</code> objects anyway, but rather just a dictionary of image names, and have <code>cellForRowAtIndexPath</code> instantiate the <code>UIImage</code> there. It probably doesn't matter when you have only three images, but if you ever had more, the existing array of <code>UIImage</code> objects construct could be problematic in memory pressure situations. Yes, you could insert the appropriate <code>didReceiveMemoryWarning</code> handling, but it's far simpler to just never maintain a dictionary with <code>UIImage</code> objects in the first place.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload