2015-01-19 13 views
0

Swift를 사용하여 테이블 뷰에 데이터를로드하려고합니다. 내 문제는 데이터를 표시하는 데 10-15 초가 걸린다는 점입니다. 데이터가 표시되는 것을 끝내지 만 오랜 시간이 걸립니다. iCal에서 이벤트를 가져 와서 테이블보기로 표시하고 있습니다. 코드에 문제가 있습니까?self.tableView.reloadData 호출시 10-15 초 소요

class EventsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 

    @IBOutlet weak var eventCounterLabel: UILabel! 
    @IBOutlet weak var tableView: UITableView! 

    var eventStore = EKEventStore() 
    var calendar: EKCalendar? 
    var events = NSMutableArray() as NSMutableArray 
    var times = NSMutableArray() as NSMutableArray 

    override func viewWillAppear(animated: Bool) { 
     super.viewWillAppear(animated) 

     //Table View Data Source and Delegate 
     self.tableView.delegate = self 
     self.tableView.dataSource = self 

     //Event Kit access 
     eventStore.requestAccessToEntityType(EKEntityTypeEvent, 
      completion: {(granted: Bool, error:NSError!) in 
       if !granted { 
        println("Access to store not granted") 
       }else{ 
        self.getTheCalendar() 
       } 
     }) 
    } 

    //Event Kit Methods 
    func getTheCalendar(){ 
     //Set the start and finish dates for events 
     let start = NSDate() as NSDate 
     let finish = NSDate() as NSDate 

     //Make the predicate 
     let eventPredicate =  self.eventStore.predicateForEventsWithStartDate(start, endDate: finish, calendars: nil) as NSPredicate 

     self.eventStore.enumerateEventsMatchingPredicate(eventPredicate, usingBlock: { (event: EKEvent!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in 
      if event != nil{ 
       self.events.addObject(event.title) 
       self.times.addObject(event.startDate) 
      } 

      //Set the event counter label 
      if self.events.count == 1{ 
       self.eventCounterLabel.text = "You have " + "\(self.events.count)" + " event today." 
      }else{ 
       self.eventCounterLabel.text = "You have " + "\(self.events.count)" + " events today." 
      } 

      //Reload the table view 
      self.tableView.reloadData() 
     }) 
    } 

    //Table View Methods 
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return self.events.count 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
     var cell:EventsTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as EventsTableViewCell 

     //Set the event label 
     cell.eventLabel.text = (self.events.objectAtIndex(indexPath.row) as String) 

     cell.eventLabel.adjustsFontSizeToFitWidth = true 

     //Set the event time label 
     let calendar = NSCalendar.currentCalendar() 
     let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate:self.times.objectAtIndex(indexPath.row) as NSDate) 

     let hour = components.hour as Int 

     var theHourOfTheEvent = hour 
     if theHourOfTheEvent < 12{ 

      if theHourOfTheEvent == 0{ 

       cell.eventTimeLabel.text = "All Day" 

      }else{ 

       cell.eventTimeLabel.text = "\(theHourOfTheEvent)" + " am" 

      } 

     }else if theHourOfTheEvent > 12 && theHourOfTheEvent < 24{ 

      theHourOfTheEvent -= 12 

      cell.eventTimeLabel.text = "\(theHourOfTheEvent)" + " pm" 

     }else if theHourOfTheEvent == 24{ 

      theHourOfTheEvent -= 12 

      cell.eventTimeLabel.text = "\(theHourOfTheEvent)" + " am" 

     }else if theHourOfTheEvent > 24{ 

      theHourOfTheEvent -= 24 

      cell.eventTimeLabel.text = "\(theHourOfTheEvent)" + " am" 

     }else if theHourOfTheEvent == 12{ 

      cell.eventTimeLabel.text = "\(theHourOfTheEvent)" + " pm" 

     } 

     return cell 
    } 

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
     return 100.0 
    } 

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    } 
} 

답변

2

EventKit 열거 자 내에서 테이블보기를 다시로드하고 있습니다. 유엔 필요한 다시로드를 많이 될 가능성, 그리고 천천히 -

self.eventStore.enumerateEventsMatchingPredicate(eventPredicate, usingBlock: { 
     ... 
     self.tableView.reloadData() 
    }) 

이 달력의 각 검색 이벤트에 대해 한 번 다시 의미한다.

모든 이벤트를 수집 한 후에 만이 함수를 호출해야합니다. 루프 외부로 옮기면 개선 된 부분이 나타납니다.

self.eventStore.enumerateEventsMatchingPredicate(eventPredicate, usingBlock: { 
     ... 
    }) 
    self.tableView.reloadData() 

또한 메인 스레드에 파견 블록에서 호출 할 수 있습니다

; UI를 변경하는 호출은 항상 주 스레드에 있어야하며 사용자 스레드에서 코드를 실행하는 스레드가 무엇인지 분명하지 않습니다. 이 경우 reloadTable를 사용하지 않는,하지만 당신은 새로운 데이터를 얻을로 insertRowsAtIndexPaths를 사용 -


양자 택일로, 당신은 당신이 그들을 얻을 자마자 테이블에 요소를 추가 할 수 있습니다. 이것은 모든 셀을 방문하지 않기 때문에 매번 reloadData를 호출하는 것보다 저렴합니다. 실제로는 화면의 셀만 방문합니다. 시작 부분이 아닌 목록 끝에 새 이벤트를 추가한다고 가정하면 값이 싸집니다.

+0

메인 스레드의 디스패치 블록에서 호출하는 것이 효과적이었습니다! – PoKoBros