2013-05-04 129 views
2

我幾乎完成了我的應用程序,似乎所有東西都能正常工作,但主要觀點。
這是一個UIViewController與嵌入式UITableView
我使用Parse作爲後端,並在我的viewDidLoad方法中獲得需要的對象數組。複雜單元格的UITableView速度很慢並且很緩慢

每個單元格都包含一些我在tableView:cellForRowAtIndexPath中提取的數據,恐怕這就是爲什麼我的表格視圖非常滯後的原因,但我不知道如何獲取每個我需要的數據對象在我的陣列中沒有indexPath.row號碼。

我已經使每個單元格元素「不透明」,如其他答案中的建議。

這是我的代碼,任何幫助將不勝感激:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"cellHT"; 
    CellHT *cell = (CellHT *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (!cell) { 
     cell = [[CellHT alloc] 
       initWithStyle:UITableViewCellStyleDefault 
       reuseIdentifier:CellIdentifier]; 
    } 

    // self.hH is an NSArray containing all the objects 
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 
    cell.lblTitle.text = [self.hH[indexPath.row] objectForKey:@"title"]; 
    cell.lblVenueName.text = [self.hH[indexPath.row] objectForKey:@"venueName"]; 
    cell.lblDistance.text = NSLocalizedString(@"Distance from you", nil); 
    self.geo = [self.hH[indexPath.row] objectForKey:@"coordinates"]; 

    // the formatters are initialized in the viewDidLoad: method 
    self.formatData = [NSDateFormatter dateFormatFromTemplate:@"dd/MM" options:0 locale:[NSLocale currentLocale]]; 
    [self.formatterData setDateFormat:self.formatData]; 
    self.formatOra = [NSDateFormatter dateFormatFromTemplate:@"j:mm" options:0 locale:[NSLocale currentLocale]]; 
    [self.formatterOra setDateFormat:self.formatOra]; 
    self.dal = NSLocalizedString(@"from", nil); 
    self.ore = NSLocalizedString(@"at", nil); 
    CLLocation *vLoc = [[CLLocation alloc] initWithLatitude:self.geo.latitude longitude:self.geo.longitude]; 
    CLLocation *user = [[CLLocation alloc] initWithLatitude:self.userGeo.latitude longitude:self.userGeo.longitude]; 
    CLLocationDistance distance = [user distanceFromLocation:venueLoc]; 
    if ([[prefs objectForKey:@"unit"] isEqualToString:@"km"]) { 
     cell.lblDist.text = [NSString stringWithFormat:@"%.1f Km", distance /1000]; 
    } else { 
     cell.lblDist.text = [NSString stringWithFormat:@"%.1f Miles", distance /1609]; 
    } 

    // compare the object's starting date with the current date to set some images in the cell 
    NSComparisonResult startCompare = [[self.hH[indexPath.row] objectForKey:@"startDate"] compare: [NSDate date]]; 
    if (startCompare == NSOrderedDescending) { 
     cell.quad.image = [UIImage imageNamed:@"no_HT"]; 
     cell.lblStartTime.textColor = [UIColor redColor]; 
    } else { 
     cell.quad.image = [UIImage imageNamed:@"yes_HT"]; 
     cell.lblStartTime.textColor = [UIColor colorWithRed:104.0/255.0 green:166.0/255.0 blue:66.0/255.0 alpha:1.0]; 
    } 
    NSString *dataInizio = [NSString stringWithFormat:@"%@ %@ %@ %@", self.dal, [self.formatterData stringFromDate:[self.hH[indexPath.row] objectForKey:@"startDate"]], self.ore, [self.formatterOra stringFromDate:[self.hH[indexPath.row] objectForKey:@"endDate"]]]; 
    cell.lblStartTime.text = dataInizio; 
    PFObject *cat = [self.hH[indexPath.row] objectForKey:@"catParent"]; 
    NSString *languageCode = [[NSLocale preferredLanguages] objectAtIndex:0]; 
    if ([languageCode isEqualToString:@"it"]) { 
     cell.lblCategory.text = [cat objectForKey:@"nome_it"]; 
    } else if ([languageCode isEqualToString:@"es"]) { 
     cell.lblCategory.text = [cat objectForKey:@"nome_es"]; 
    } else { 
     cell.lblCategory.text = [cat objectForKey:@"nome_en"]; 
    } 

    //getting the image data from the Parse PFFile 
    PFFile *theImage = [self.hH[indexPath.row] objectForKey:@"photo"]; 
    [theImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) { 
     if (!error) { 
      cell.cellImageView.image = [UIImage imageWithData:data]; 
     } 
    }]; 

    //getting the cell object's owner and his profile 
    PFUser *usr = [self.hH[indexPath.row] objectForKey:@"parent"]; 
    PFQuery *prof = [PFQuery queryWithClassName:@"Profile"]; 
    prof.cachePolicy = kPFCachePolicyCacheThenNetwork; 
    [prof whereKey:@"parent" equalTo:usr]; 
    [prof getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) { 
     if (!error) { 
      //getting the object's rating and the number of votes 
      PFQuery *rateQuery = [PFQuery queryWithClassName:@"Rating"]; 
      [rateQuery whereKey:@"parent" equalTo:object]; 
      [rateQuery getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) { 
       if (!error) { 
        float vote = [[object objectForKey:@"rate"] floatValue]; 
        float temp = ((vote * 2) + 0.5); 
        int tempvote = (int)temp; 
        float roundedVote = (float)tempvote/2; 
        // drawing the stars number, depending on the rating obtained 
        UIImage *starsImage = [UIImage imageNamed:@"stars"]; 
        UIGraphicsBeginImageContextWithOptions(cell.imgVoto.frame.size, NO, 0); 
        CGPoint starPoint = (CGPoint) { 
         .y = (cell.imgVoto.frame.size.height * (2 * roundedVote + 1)) - (starsImage.size.height) 
        }; 
        [starsImage drawAtPoint:starPoint]; 
        cell.imgVoto.image = UIGraphicsGetImageFromCurrentImageContext(); 
        UIGraphicsEndImageContext(); 
        cell.lblVoto.text = [NSString stringWithFormat:@"(%d)", [[object objectForKey:@"voters"] intValue]]; 
       } 
      }]; 
     } 
     }]; 
    return cell; 
} 

編輯:這是單元代碼:

+ (void)initialize { 
    if (self != [HH class]) { 
     return; 
    } 
} 

-(id)initWithCoder:(NSCoder *)aDecoder { 
    if (!(self = [super initWithCoder:aDecoder])) return nil; 

    self.cellImageView.image = [UIImage imageNamed:@"icona_foto"]; 
    self.cellImageView.contentMode = UIViewContentModeScaleToFill; 
    self.formatterData = [[NSDateFormatter alloc] init]; 
    self.formatData = [[NSString alloc] init]; 
    self.formatterOra = [[NSDateFormatter alloc] init]; 
    self.formatOra = [[NSString alloc] init]; 
    self.formatData = [NSDateFormatter dateFormatFromTemplate:@"dd/MM" options:0 locale:[NSLocale currentLocale]]; 
    [self.formatterData setDateFormat:self.formatData]; 
    self.formatOra = [NSDateFormatter dateFormatFromTemplate:@"j:mm" options:0 locale:[NSLocale currentLocale]]; 
    [self.formatterOra setDateFormat:self.formatOra]; 
    self.lblVoto.text = @"(0)"; 

    return self; 
} 

第二個編輯:這是在viewDidLoad方法的代碼:

 PFQuery *hours = [PFQuery queryWithClassName:@"HH"]; 
     hours.cachePolicy = kPFCachePolicyCacheThenNetwork; 
     // here I'm making lots of query constraints that I'll not include 

     [hours findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { 
      if (!error) { 
       self.objectsNumber = objects.count; 
       self.hH = [[NSArray alloc] initWithArray:objects]; 
      } 
     }]; 
     [self.tableView reloadData]; 
} 
+0

你可以發佈'CellHT'的代碼嗎? – jszumski 2013-05-04 15:38:09

+0

我編輯了問題以包含單元代碼。 – Aleph72 2013-05-04 15:50:30

+1

你有沒有在樂器中進行表格分析? Time Profiler儀器會告訴你準確的時間。 – Fogmeister 2013-05-04 16:00:07

回答

4

我會盡可能多的邏輯搬出cellForRowAtIndexPath:就可以了,它需要非常輕量級以獲得良好的滾動性能。你在主線程上做了很多工作,當你從Parse返回你的模型對象時(如果你可以發佈viewDidLoad我可以給你更具體的幫助),我會做更多的工作,並更新表格視圖時,這些調用完成:

  • [UIImage imageWithData:data]
  • 什麼關係NSDateFormatter
  • CLLocationinitWithLatitude:longitude:
  • 創建評分星像

這些都不依賴於表視圖的狀態,所以它們可以有效地預先計算並緩存在模型對象中。如果你只是在桌子上上下滾動,你會一遍又一遍地做同樣的工作,導致你的表現不佳。


更新了提問者的最新代碼:

我將不包括所有您在此處的功能,但是這應該給你一個想法:

// create a single shared formatter instead of one per object 
NSDateFormatter *dateFormatter = [NSDateFormatter dateFormatFromTemplate:@"dd/MM" options:0 locale:[NSLocale currentLocale]]; 
NSDateFormatter *timeFormatter = [NSDateFormatter dateFormatFromTemplate:@"j:mm" options:0 locale:[NSLocale currentLocale]]; 

[hours findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { 
    if (!error) { 
     self.objectsNumber = objects.count; 

     for (SomeObject *modelObj in objects) { 
      // if you can add properties to your model object directly, do that 
      // otherwise write a category on the Parse object to add the ones you need 
      modelObj.dateString = [NSString stringWithFormat:@"%@ %@ %@ %@", modelObj.dal, [self.dateFormatter stringFromDate:[modelObj objectForKey:@"startDate"]], modelObj.ore, [self.timeFormatter stringFromDate:[modelObj objectForKey:@"endDate"]]]; 

      // create your locations, images, etc in here too 
     } 

     self.hH = [[NSArray alloc] initWithArray:objects]; 
    } 
}];] 

然後在cellForRowAtIndexPath:,採取預先計算屬性,並簡單地將它們分配給適當的標籤,圖像視圖等。

通過GCD在主線程中完成大部分處理會更好,但這很可能超出了這個問題的範圍。有關更多信息,請參見Using GCD and Blocks Effectively。請記住,只能從主線程與UIKit進行交互!

+0

我已經添加了代碼來加載對象的數組 – Aleph72 2013-05-04 15:58:39

+0

@ Aleph72添加了一些代碼,讓您瞭解如何將事物移動到'viewDidLoad'。 – jszumski 2013-05-04 16:16:19

+0

我會立即嘗試。關於GCD,'findObjectsInBackgroundWithBlock'自動使用後臺線程並在需要時調度主線程。 – Aleph72 2013-05-04 16:24:20

1

試試刪除

CLLocation *vLoc = [[CLLocation alloc] initWithLatitude:self.geo.latitude longitude:self.geo.longitude]; 

CLLocation *user = [[CLLocation alloc] initWithLatitude:self.userGeo.latitude long itude:self.userGeo.longitude]; 

CLLocationDistance distance = [user distanceFromLocation:venueLoc]; 

這是一見鍾情,然後我看到你所有的代碼,我實現了很多圖像的使用

+0

刪除這些線可以減少很多延遲!但是我需要計算每個對象中包含的點的用戶距離,在加載單元格之前我怎麼做? – Aleph72 2013-05-04 16:03:14

+0

你必須提前計算它並存儲在一個數組中 – 2013-05-04 16:06:31

+0

你的意思是隻有一個新的數組? – Aleph72 2013-05-04 16:12:11