2014-02-21 5 views
5

Ich postete dies auf Code Review, aber wurde gesagt, es könnte besser sein als eine Stapelüberlauf Frage, so dass dieser Beitrag.UITableView 'versteckte' Abschnitt verursacht mehr Speicherzuweisungen jedes Mal auf Pull zum Aktualisieren

Ich habe ein UITableView, dass ich einen Abschnitt "verstecke", wenn der Benutzer auf die Überschrift dieses Abschnitts tippt. Ich dachte, das wäre eine ziemlich coole Implementierung, die ich gefunden habe, aber es stellt sich heraus, wenn dieser Abschnitt ausgeblendet wird und der Benutzer zum Aktualisieren zieht, werden 1-2 MB in den Speicher jedes Mal hinzugefügt, wenn sie zum Aktualisieren (nach der Aktualisierung) ziehen. Wenn der Abschnitt von UITableView nicht ausgeblendet ist und sie zum Aktualisieren ziehen, wird kein zusätzlicher Speicher zugewiesen (der richtige Weg/das richtige Verhalten). Ich weiß, 1-2 MB ist nicht viel, aber alles summiert sich. Ich konnte in Profiler keinerlei Lecks finden, deshalb kam ich hierher.

Ich kann etwas übersehen oder meine Logik ist fehlerhaft, und würde jede mögliche Hilfe schätzen. Sorry für den langen Code unten:

Update: aufgelöst Code:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    switch (section) 
    { 
     case 0: 
     { 
      return [self friendRequests]; 
     } 
     case 1: 
     { 
      return [self friends]; 
     } 
     default: 
     { 
      if (self.showingBlockedUsers == YES) 
      { 
       return [self blockedUsers]; 
      } 
      else 
      { 
       return 0; 
      } 
     } 
    } 
} 

Alter Code von der ursprünglichen Frage:

- (void)refreshing:(UIRefreshControl *)refreshControl 
{ 
    [refreshControl beginRefreshing]; 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://foobar.com/test.plist"]]; 
    request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData; 
    request.timeoutInterval = 5.0; 

    [NSURLConnection sendAsynchronousRequest:request 
            queue:[NSOperationQueue mainQueue] 
         completionHandler: 
    ^(NSURLResponse *response, NSData *data, NSError *connectionError) 
    { 
     if (data) 
     { 
      NSPropertyListFormat format; 

      NSMutableDictionary *dictionary = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:nil]; 

      self.tableDataSource = dictionary; 
      [self.tableView reloadData]; 
      [refreshControl endRefreshing]; 
      [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
     } 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell; 
    NSString *identifier = @"cellIdentifier"; 
    UILabel *userNameLabel = [self userNameLabel]; 
    UIView *requestsView = [self requestsView]; 
    UIButton *approveButton = [self approveButton]; 
    UIButton *denyButton = [self denyButton]; 
    UIImageView *profileImageView = [self profileImageView]; 

    if (cell == nil) 
    { 
     cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; 
     cell.selectionStyle = UITableViewCellSelectionStyleDefault; 

     [requestsView addSubview:approveButton]; 
     [requestsView addSubview:denyButton]; 

     [cell.contentView addSubview:requestsView]; 
     [cell.contentView addSubview:profileImageView]; 
     [cell.contentView addSubview:userNameLabel]; 
    } 

    if (indexPath.section == 0) 
    { 
     cell.selectionStyle = UITableViewCellSelectionStyleNone; 
     userNameLabel.frame = CGRectMake(82, 0, 167, 68); 
     approveButton.tag = indexPath.row; 
     denyButton.tag = indexPath.row; 

     NSArray *keys = [self.tableDataSource objectForKey:@"Requests"]; 
     id aKey = [keys objectAtIndex:indexPath.row]; 

     userNameLabel.text = [aKey objectForKey:@"User"]; 

     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[aKey objectForKey:@"URL"]]]; 
     request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData; 
     request.timeoutInterval = 5.0; 

     if ([imageCache objectForKey:aKey]) 
     { 
      profileImageView.image = [imageCache objectForKey:aKey]; 
     } 
     else 
     { 
      [NSURLConnection sendAsynchronousRequest:request 
               queue:[NSOperationQueue mainQueue] 
            completionHandler: 
      ^(NSURLResponse *response, NSData *data, NSError *error) 
      { 
       if (data) 
       { 
        dispatch_async(dispatch_get_main_queue(),^
        { 
         profileImageView.image = [UIImage imageWithData:data]; 
         [imageCache setObject:[UIImage imageWithData:data] forKey:aKey]; 
        }); 
       } 
       else 
       { 
        profileImageView.image = [self profileImage]; 
       } 
      }]; 
     } 
    } 
    else if (indexPath.section == 1) 
    { 
     requestsView.hidden = YES; 
     NSArray *keys = [self.tableDataSource objectForKey:@"Friends"]; 
     id aKey = [keys objectAtIndex:indexPath.row]; 
     userNameLabel.text = [aKey objectForKey:@"User"]; 

     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[aKey objectForKey:@"URL"]]]; 
     request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData; 
     request.timeoutInterval = 5.0; 

     if ([imageCache objectForKey:aKey]) 
     { 
      profileImageView.image = [imageCache objectForKey:aKey]; 
     } 
     else 
     { 
      [NSURLConnection sendAsynchronousRequest:request 
               queue:[NSOperationQueue mainQueue] 
            completionHandler: 
      ^(NSURLResponse *response, NSData *data, NSError *error) 
      { 
       if (data) 
       { 
        dispatch_async(dispatch_get_main_queue(),^
        { 
         profileImageView.image = [UIImage imageWithData:data]; 
         [imageCache setObject:[UIImage imageWithData:data] forKey:aKey]; 
        }); 
       } 
       else 
       { 
        profileImageView.image = [self profileImage]; 
       } 
      }]; 
     } 
    } 
    else if (indexPath.section == 2) 
    { 
     requestsView.hidden = YES; 
     NSArray *keys = [self.tableDataSource objectForKey:@"Blocked"]; 
     id aKey = [keys objectAtIndex:indexPath.row]; 
     userNameLabel.text = [aKey objectForKey:@"User"]; 
    } 

    return cell; 
} 

- (void)displayBlockedUsers 
{ 
    if (self.showingBlockedUsers == YES) 
    { 
     self.showingBlockedUsers = NO; 
     [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationNone]; 
    } 
    else 
    { 
     self.showingBlockedUsers = YES; 
     [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationNone]; 
    } 
} 

- (NSInteger)friendRequests 
{ 
    return [[self.tableDataSource objectForKey:@"Requests"]count]; 
} 

- (NSInteger)friends 
{ 
    return [[self.tableDataSource objectForKey:@"Friends"]count]; 
} 

- (NSInteger)blockedUsers 
{ 
    return [[self.tableDataSource objectForKey:@"Blocked"]count]; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == 2 && self.showingBlockedUsers == NO) 
    { 
     return 0; 
    } 
    else 
    { 
     return 68; 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    if (section == 0) 
    { 
     if ([self friendRequests] < 1) 
     { 
      return 0; 
     } 
     else 
     { 
      return 22; 
     } 
    } 
    else if (section == 1) 
    { 
     if ([self friends] < 1) 
     { 
      return 0; 
     } 
     else 
     { 
      return 22; 
     } 
    } 
    else 
    { 
     if ([self blockedUsers] < 1) 
     { 
      return 0; 
     } 
     else 
     { 
      return 22; 
     } 
    } 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    switch (section) 
    { 
     case 0: 
     { 
      return [self friendRequests]; 
     } 
     case 1: 
     { 
      return [self friends]; 
     } 
     default: 
     { 
      return [self blockedUsers]; 
     } 
    } 
} 

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    UIView *headerView = [[UIView alloc]init]; 
    headerView.backgroundColor = [UIColor colorWithRed:248.0/255.0 green:248.0/255.0 blue:248.0/255.0 alpha:1.0]; 

    UILabel *headerLabel = [[UILabel alloc]initWithFrame:CGRectMake(12, 0, 320, 22)]; 
    headerLabel.font = [UIFont systemFontOfSize:13.5]; 
    [headerView addSubview:headerLabel]; 

    if (section == 0) 
    { 
     NSInteger friendRequests = [self friendRequests]; 

     if (friendRequests < 2) 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Request",friendRequests]; 
     } 
     else 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Requests",friendRequests]; 
     } 
    } 
    else if (section == 1) 
    { 
     NSInteger friends = [self friends]; 

     if (friends < 2) 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Friend",friends]; 
     } 
     else 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Friends",friends]; 
     } 
    } 
    else 
    { 
     UIButton *theButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
     [theButton addTarget:self action:@selector(displayBlockedUsers) forControlEvents:UIControlEventTouchUpInside]; 
     theButton.frame = CGRectMake(0, 0, 320, 22); 

     [headerView addSubview:theButton]; 

     NSInteger blocked = [self blockedUsers]; 

     if (self.showingBlockedUsers == YES) 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Blocked - Tap to Hide",blocked]; 
     } 
     else 
     { 
      headerLabel.text = [NSString stringWithFormat:@"%d Blocked - Tap to Show",blocked]; 
     } 
    } 

    return headerView; 
} 

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

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 3; 
} 
+0

Können Sie den Code für Ihre Pull-to-Refresh-Handler und Ihre CellForRowAtIndexPath-Methode? –

+0

@JasonCoco Ich habe gerade die Frage mit dem Code aktualisiert, den Sie oben im Codeblock angefordert haben. – klcjr89

Antwort

5

Es sieht so aus, als ob Sie den Abschnitt ausblenden, indem Sie 0 in heightForRowAtIndexPath: zurückgeben. Das Problem bei diesem Ansatz besteht darin, dass die Tabellenansicht immer noch diese Zellen erstellt. Zusätzlich zur Erstellung der Zellen für alle Zellen, die tatsächlich angezeigt werden, erstellt die Tabellenansicht zusätzliche Zellen für alle blockierten Benutzer.

Um einen Abschnitt auszublenden, geben Sie einfach 0 von tableView:numberOfRowsInSection: zurück, wenn der Abschnitt "geschlossen" ist. Auf diese Weise ruft die Tabellenansicht nicht heightForRowAtIndexPath:, cellForRowAtIndexPath: oder irgendetwas anderes auf, da Sie sagen, dass dort keine Zellen vorhanden sind.

+0

Perfekt!Jetzt keine Speicherzuordnungen mehr. Sehen Sie meinen neuen Code oben in der ursprünglichen Frage, wie ich ihn gelöst habe. – klcjr89

+0

@ troop231 Schön, dass es funktioniert hat! Übrigens, Ihr Download-Code für asynchrone Bilder sieht so aus, als ob er falsch wäre - "profileImageView" könnte wiederverwendet werden, während der Benutzer schnell scrollt; Dies könnte dazu führen, dass das falsche Profilbild angezeigt wird. –

+0

Irgendwelche Vorschläge, wie ich es verbessern könnte? – klcjr89

0

Nun, es sucht über wirklich schnell ist es Speicher mit weil cellForRowAtIndexPath: immer noch aufgerufen wird und Sie die Zelle immer noch als ob es sichtbar war. Das klingt vielleicht wirklich einfach, aber haben Sie versucht, zu überprüfen, ob der Abschnitt versteckt ist und dann eine leere Zelle zurückgeben?

UPDATE: Das Problem ist, dass Sie nicht wirklich die Tabellenansicht sagen, dass Sie die Zellen versteckt (nur die Höhe zu reduzieren). In MVC weiß Ihr Modell, aber der Controller nicht. Geben Sie einfach 0 in - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section zurück, nachdem Sie mit einem booleschen Wert in Ihrem Modell überprüft haben, ob Sie Ihre Zellen versteckt haben.

+0

Ich dachte das auch, ich werde das schnell umsetzen und zu dir zurückkommen. – klcjr89

+0

Tun Sie das nicht. Sie können 'nil' von dieser Methode nicht zurückgeben! Es wird alles kaputt machen! –

+0

Ich kann bestätigen, dass meine App nicht stürzt. – klcjr89

Verwandte Themen