2015-06-29 86 views
-1

我有一個相當長的cellForRowAtIndexPath函數。我使用解析作爲我的後端,並有很多事情要做。我想提取很多這些條件並將它們放入自己的功能中。特別是PFUser查詢,但不幸的是,我不知道最好的方法是什麼,因爲我不知道如何訪問我想寫的函數中的每個單元的元素。Refactor cellForRowIndexPath in UITableView Swift

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCellWithIdentifier("PostCells", forIndexPath: indexPath) as! NewsFeedTableCellTableViewCell 

    // Configure the cell... 

    // A drive is a post 
    let drive: PFObject = self.timelineData[indexPath.row] as PFObject 
    var driverId = drive.objectForKey("driver")!.objectId! 
    var currentUserObjectId = PFUser.currentUser()!.objectId 
    if(driverId != currentUserObjectId){ 
     cell.requestButton.layer.borderWidth = 1 
     cell.requestButton.titleLabel!.font = UIFont.systemFontOfSize(11) 
     cell.requestButton.tintColor = UIColor.orangeColor() 
     cell.requestButton.layer.borderColor = UIColor.orangeColor().CGColor 
     cell.requestButton.setTitle("REQUEST", forState: UIControlState.Normal) 

    } 
    else { 

     cell.requestButton.layer.borderWidth = 1 
     cell.requestButton.titleLabel!.font = UIFont.systemFontOfSize(11) 
     cell.requestButton.tintColor = UIColor.grayColor() 
     cell.requestButton.layer.borderColor = UIColor.lightGrayColor().CGColor 
     cell.requestButton.setTitle("REQUEST", forState: UIControlState.Normal) 
     cell.requestButton.enabled = false 

    } 


    // Setting up the attributes of the cell for the news feed 
    cell.driveTitleTextField.text = drive.objectForKey("title") as! String 
    cell.wayTextField.text = drive.objectForKey("way") as! String 

    var departureDate = NSDate() 
    departureDate = drive.objectForKey("departureDate") as! NSDate 
    var dateFormat = NSDateFormatter() 
    dateFormat.dateFormat = "M/dd hh:mm a" 
    cell.departureDateTextField.text = dateFormat.stringFromDate(departureDate) 

    if((drive.objectForKey("way")!.isEqualToString("Two Way"))) 
    { 
     var returnDate = NSDate() 
     returnDate = drive.objectForKey("returnDate") as! NSDate 
     cell.returningDateTextField.text = dateFormat.stringFromDate(returnDate) 
    } 
    else if((drive.objectForKey("way")!.isEqualToString("One Way"))) 
    { 
     cell.returningDateTextField.enabled = false 
     cell.returningDateTextField.userInteractionEnabled = false 
     cell.returningDateTextField.hidden = true 
     cell.returningLabel.hidden = true 
    } 

    var seatNumber = NSNumber() 
    seatNumber = drive.objectForKey("seatNumber") as! NSInteger 
    var numberFormat = NSNumberFormatter() 
    numberFormat.stringFromNumber(seatNumber) 
    cell.seatNumberTextField.text = numberFormat.stringFromNumber(seatNumber) 


    // this is a PFUser query so we can get the users image and name and email from the User class 
    var findDrive = PFUser.query() 
    var objectId: AnyObject? = drive.objectForKey("driver")!.objectId! 
    findDrive?.whereKey("objectId", equalTo: objectId!) 
    findDrive?.findObjectsInBackgroundWithBlock{ 
     (objects:[AnyObject]?, error:NSError?)->Void in 
     if (error == nil){ 
      if let actualObjects = objects { 
       let possibleUser = (actualObjects as NSArray).lastObject as? PFUser 
       if let user = possibleUser { 
        cell.userProfileNameLabel.text = user["fullName"] as? String 
        cell.userEmailLabel.text = user["username"] as? String 

        //Profile Image 
        cell.profileImage.alpha = 0 
        if let profileImage = user["profilePicture"] as? PFFile { 
         profileImage.getDataInBackgroundWithBlock{ 
          (imageData:NSData? , error:NSError?)-> Void in 

          if(error == nil) { 
           if imageData != nil{ 
            let image:UIImage = UIImage (data: imageData!)! 
            cell.profileImage.image = image 
           } 
          } 
         } 

        } 

        UIView.animateWithDuration(0.5, animations: { 
         cell.driveTitleTextField.alpha = 1 
         cell.wayTextField.alpha = 1 
         cell.profileImage.alpha = 1 
         cell.userProfileNameLabel.alpha = 1 
         cell.userEmailLabel.alpha = 1 
         cell.seatNumberTextField.alpha = 1 
         cell.returningDateTextField.alpha = 1 
         cell.departureDateTextField.alpha = 1 

        }) 

       } 
      } 

     } 
    } 
    return cell 
} 

編輯1

我想出了一個辦法來重構我的代碼,我想批評!

1.我提取了很多單元格配置並將它們放入函數中,一個用於單元格上的按鈕,另一個用於解析所有數據。

func configureDataTableViewCell(cell:NewsFeedTableCellTableViewCell, drive: PFObject) 
{ 
    cell.driveTitleTextField.text = drive.objectForKey("title") as! String 
    cell.wayTextField.text = drive.objectForKey("way") as! String 
    cell.userEmailLabel.text = drive.objectForKey("username") as? String 
    cell.userProfileNameLabel.text = drive.objectForKey("name") as? String 

    var departureDate = NSDate() 
    departureDate = drive.objectForKey("departureDate") as! NSDate 
    var dateFormat = NSDateFormatter() 
    dateFormat.dateFormat = "M/dd hh:mm a" 
    cell.departureDateTextField.text = dateFormat.stringFromDate(departureDate) 

    if((drive.objectForKey("way")!.isEqualToString("Two Way"))) 
    { 
     var returnDate = NSDate() 
     returnDate = drive.objectForKey("returnDate") as! NSDate 
     cell.returningDateTextField.text = dateFormat.stringFromDate(returnDate) 
    } 
    else if((drive.objectForKey("way")!.isEqualToString("One Way"))) 
    { 
     cell.returningDateTextField.enabled = false 
     cell.returningDateTextField.userInteractionEnabled = false 
     cell.returningDateTextField.hidden = true 
     cell.returningLabel.hidden = true 
    } 

    var seatNumber = NSNumber() 
    seatNumber = drive.objectForKey("seatNumber") as! NSInteger 
    var numberFormat = NSNumberFormatter() 
    numberFormat.stringFromNumber(seatNumber) 
    cell.seatNumberTextField.text = numberFormat.stringFromNumber(seatNumber) 


} 

func configureButtonTableViewCell(cell:NewsFeedTableCellTableViewCell, userID: String) 
{ 
    var currentUserObjectId = PFUser.currentUser()!.objectId 
    if(userID != currentUserObjectId){ 
     cell.requestButton.layer.borderWidth = 1 
     cell.requestButton.titleLabel!.font = UIFont.systemFontOfSize(11) 
     cell.requestButton.tintColor = UIColor.orangeColor() 
     cell.requestButton.layer.borderColor = UIColor.orangeColor().CGColor 
     cell.requestButton.setTitle("REQUEST", forState: UIControlState.Normal) 
     println("orange") 
    } 
    else { 

     cell.requestButton.layer.borderWidth = 1 
     cell.requestButton.titleLabel!.font = UIFont.systemFontOfSize(11) 
     cell.requestButton.tintColor = UIColor.grayColor() 
     cell.requestButton.layer.borderColor = UIColor.lightGrayColor().CGColor 
     cell.requestButton.setTitle("REQUEST", forState: UIControlState.Normal) 
     cell.requestButton.enabled = false 
     println("gray") 
    } 

} 

2.然後我在功能通過從步驟1,然後進入我cellForRowIndexPath

// A drive is a post 
    let drive: PFObject = self.timelineData[indexPath.row] as PFObject 
    var driverId : String = drive.objectForKey("driver")!.objectId!! 
    configureButtonTableViewCell(cell, userID: driverId) 
    configureDataTableViewCell(cell, drive: drive) 

3.我存儲在我的所有PFUser數據到我的對象時,其代替保存查詢的用戶類。所以當他們保存帖子時,我得到了PFUser.currentUser()用戶名,全名和個人資料圖片。

我的裝載數據已被修改。我將所有的個人資料圖片存儲在自己的數組中。

func loadData(){ 


    var findItemData:PFQuery = PFQuery(className:"Posts") 

    findItemData.addDescendingOrder("createdAt") 

    findItemData.findObjectsInBackgroundWithBlock{ 
     (objects:[AnyObject]? , error:NSError?) -> Void in 
      if error == nil 
      { 
       self.timelineData.removeAll(keepCapacity: false) 
       self.profilePictures.removeAll(keepCapacity: false) 
       self.timelineData = objects as! [PFObject] 
       for object in objects! { 

        self.profilePictures.append(object.objectForKey("profilePicture") as! PFFile) 


       } 

       self.newsFeedTableView.reloadData() 


      } 

    } 
} 

最後,這裏是我的更新cellForRowIndexPath

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    var cell = tableView.dequeueReusableCellWithIdentifier("PostCells", forIndexPath: indexPath) as! NewsFeedTableCellTableViewCell 

    // Configure the cell... 

    // A drive is a post 
    let drive: PFObject = self.timelineData[indexPath.row] as PFObject 
    var driverId : String = drive.objectForKey("driver")!.objectId!! 
    configureButtonTableViewCell(cell, userID: driverId) 
    configureDataTableViewCell(cell, drive: drive) 
    println(PFUser.currentUser()?.objectForKey("username")) 


    if let profileImage = drive["profilePicture"] as? PFFile { 
     profileImage.getDataInBackgroundWithBlock{ 
      (imageData:NSData? , error:NSError?)-> Void in 

      if(error == nil) { 
       if imageData != nil{ 
        let image:UIImage = UIImage (data: imageData!)! 
        cell.profileImage.image = image 
       } 
      } 
     } 

    } 


    return cell 
} 

讓我知道你們的想法,我想這樣做使我的代碼更可讀,快速和高效存儲。

+0

日期格式化程序可能會很慢,如果您可以將它們移出cellForRow,並且可能將它們作爲字符串設置在您獲取的對象上,那可能是最好的。除此之外,看起來非常好。 –

+0

@BeauYoung謝謝!你能給我一個讓日期格式化程序離開的例子嗎? – kareem

+0

你有出發日期是否正確?爲什麼不用你在Parse上需要的格式?如果你不能這樣做,我只需在PFObject上創建一個新的鍵,並在完成取回之後立即添加它。只要把它們扔進一個循環。 –

回答

0

重構,讓您有一些數據類型或一組實例變量作爲視圖模型。避免使cellForRowAtIndexPath中的單元格發生異步調用。而是讓你的數據訪問方法改變或重新創建視圖模型,並在你的回調結束時,dispatch_async到主隊列。給它一個閉包,告訴你的表視圖reloadData以及任何你需要做的視圖來顯示新的數據。

這裏有一個小的僞代碼來描述我的意思:

func loadData() { 
    parseQueryWithCallback() { data in 
     self.viewModel = doWhateverTransformsAreNeeded(data) 
     dispatch_async(dispatch_get_main_queue(), self.tableView.reloadData) 
    } 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) { 
    let cell = dequeue(...) 
    cell.thingOne = self.viewModel.things[indexPath.row].thingOne 
    cell.thingTwo = self.viewModel.things[indexPath.row].thingTwo 
    return cell 
} 
+0

你能給我一些代碼,你需要更多的問題的背景嗎? – kareem

+0

其中parseQueryWithCallback()來自哪裏? – kareem

+0

它是僞代碼,所以你用你從Parse獲取數據的真實代碼替換它。 –

4

你不應該做內部cellForRow任何重的東西模型。 你目前正在嘗試做什麼會大大減慢你的用戶界面。

在大多數情況下,你會希望你的模型對象設置,並準備好之前,你甚至到cellForRow。

這意味着在像viewDidLoad這樣的地方執行Parse查詢,將這些結果保存在一個數組中,並且在需要時將其應用於cellForRow中的單元格。這樣,當用戶滾動時,將不會爲每個進入視圖的新單元分派新的查詢。它已經可用。

除此之外,您應該在獲取這些項目後對這些項目進行任何更改,您可以這樣做,即使在用戶滾動時也保持不變。