2013-11-04 3 views
0

"reloadData"가 UITableView와 함께 작동하는 데 약간의 문제가 있습니다. 간단히 말해서; 테이블에 데이터/행을 추가하면 행이 추가되지만 기존 행의 중복으로 표시됩니다. "DequeueReusableCell"디버깅하는 경우 그냥 임의의 셀을 반환하는 것. 여기 내 코드가있다.UITableView reloadData 중복 셀

public partial class MyViewController : UITableViewController 
{ 
    AppDelegate AppDelegate; 
    MyStuff sendToDetail; 
    MyRestClient client; 

    public MyViewController (IntPtr handle) : base (handle) 
    { 
     AppDelegate = (AppDelegate)UIApplication.SharedApplication.Delegate; 
     client = new MyRestClient(); 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 

     this.TableView.Source = new TableSource(getMyStuff(), this); 
    } 

    public override void PrepareForSegue (UIStoryboardSegue segue, NSObject sender) 
    { 
     base.PrepareForSegue (segue, sender); 

     if (segue.Identifier == "DetailSegue") { 
      DetailController controller = segue.DestinationViewController as DetailController; 
      controller.MyStuffItem = sendToDetail; 
     } 
    } 

    private IEnumerable<MyStuff> getMyStuff(int skip = 0, int count = 10) 
    { 
     var request = new RestRequest("MyStuff"); 
     request.AddParameter("id", AppDelegate.ActiveUser.Id); 
     request.AddParameter("$top", count); 
     request.AddParameter("$skip", skip); 
     var response = client.Execute(request); 

     var source = (IEnumerable<MyStuff>)JsonConvert.DeserializeObject(response.Content, typeof(IEnumerable<MyStuff>)); 

     return source; 
    } 

    public class TableSource : UITableViewSource { 
     IEnumerable<MyStuff> tableItems; 
     MyViewController Controller; 

     public TableSource (IEnumerable<MyStuff> items, MyViewController controller) 
     { 
      tableItems = items; 
      Controller = controller; 
     } 

     public override int NumberOfSections (UITableView tableView) 
     { 
      return 1; 
     } 

     public override int RowsInSection (UITableView tableview, int section) 
     { 
      return tableItems.Count() + 1; 
     } 

     public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath) 
     { 

      if (indexPath.Row == tableItems.Count()) { 
       //bottom load more cell 

       LoadingCell loadMore = tableView.DequeueReusableCell ("LoadingCell") as LoadingCell; 
       if (loadMore == null) 
        loadMore = LoadingCell.Create(); 

       return loadMore; 
      } 

      MyStuffCell cell = tableView.DequeueReusableCell ("MyStuffCell") as MyStuffCell; 
      // if there are no cells to reuse, create a new one 
      if (cell == null) { 
       cell = MyStuffCell.Create(); 

       MyStuff current = tableItems.ElementAt (indexPath.Row); 

       cell.Update (current); 
      } 

      return cell; 
     } 

     public override void RowSelected (UITableView tableView, NSIndexPath indexPath) 
     { 
      if (indexPath.Row != tableItems.Count()) { 
       Controller.sendToDetail = tableItems.ElementAt (indexPath.Row); 
       Controller.PerformSegue ("DetailSegue", this); 
      } 
     } 

     public override void WillDisplay (UITableView tableView, UITableViewCell cell, NSIndexPath indexPath) 
     { 
      if (cell is LoadingCell) { 
       var count = tableItems.Count(); 
       var second = Controller.getMyStuff (count); 
       tableItems = tableItems.Concat (second); 
       tableView.ReloadData(); 
      } 
     } 
    } 
} 

마법이 WillDisplay에서 일어나는 - (당신은 단지 그것을 게시, 목표 - C에서 답을 알고 있다면, monotouch 난 유연 해요 예는 C 번호입니다). 여기에 LoadingCell (하단에로드 표시기가 있음)이 표시되는지 확인한 다음 이에 따라 추가 데이터를로드하고 내 IEnumerable에 추가합니다. 그런 다음 reloadData을 호출 한 후 GetCell으로 들어가고 DequeueReusableCell은 "새"셀이라도 복제본을 반환합니다 ...

문제의 일부가 아니므로 모든 것을 제거했습니다. 내 getMyStuff 메서드에서 오류 처리, 어느 곳에서도 캐싱이없는 것처럼 보이지 않습니다. 그렇지 않으면 모범 사례에 대한 의견이 열려 있습니다.

나는 믿을 수 없을만큼 간단하다고 확신하지만, 나는 그저 머리를 감쌀 수 없다. StackOverflow에 다른 비슷한 질문을 본 적이 있지만 아무도 명확한 대답을 제공하지 않습니다 ...

답변

2

DequeueReusableCell은 내부 캐시에서 할당 된 Cell 객체를 반환합니다. 해당 섹션/행에 적합한 것이 무엇이든지 반영하도록 셀의 내용을 업데이트해야합니다.

 MyStuffCell cell = tableView.DequeueReusableCell ("MyStuffCell") as MyStuffCell; 
     // if there are no cells to reuse, create a new one 
     if (cell == null) { 
      cell = MyStuffCell.Create(); 
     } 

     MyStuff current = tableItems.ElementAt (indexPath.Row); 
     cell.Update (current); 

     return cell; 
+0

분명히 DequeueReusableCell이 작동하는 방식에 대해 오해했습니다. 나는 "업데이트"에서 몇 가지 추가 로딩 및 계산을 수행하고 있는데, 나는이 방법으로 "캐시"하기를 원했지만 분명히 그렇게되지는 않습니다. 기본적으로 DequeueReusableCell을 사용하는 유일한 방법은 메모리에 할당 된 셀의 수가 제한되어 있는지 확인하는 것입니다. – reinder

+0

오른쪽. 스크롤 할 때 셀을 폐기하고 생성하는 대신 셀을 캐시하기 만하면 끊임없이 오버 헤드를 생성 할 필요가 없습니다. 하지만 가져온 셀에는 다른 행의 오래된 데이터가있을 수 있으므로 내용을 업데이트해야합니다. – Jason

+0

그래, 나도 이해하지 못하는 "정적"식별자를 설명한다. 오늘 새로운 것을 배웠다. 고마워. – reinder

관련 문제