2016-08-30 8 views
0

矢印の形を描くためにCAShapeLayerのカスタムセルがあります。異なる矢印(上、下、右)が適切なセルに適切に表示されます。セルが選択されたときに矢印の形状を変更すると、意図したとおりに動作します。UITableViewCell誤ったCAShapeLayer図形をロードしています

問題:

矢印が表示されたセル(セルが選択されている)のために変更された場合、オフスクリーン細胞の矢印でレンダリングされるランダム矢印方向で終わる、ランダムにその動作を継承するように見えますオフスクリーンセル。オフスクリーンセルの残りの要素は適切にレンダリングされているようです。

表ビューコントローラ:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath) 
    let cell = tableView.dequeueReusableCellWithIdentifier(currentCellDescriptor["cellIdentifier"] as! String, forIndexPath: indexPath) as? CustomCell 
    let settings = NSUserDefaults.standardUserDefaults() 
    if currentCellDescriptor["cellIdentifier"] as! String == "idCellNormal" { 
     if let settingName = currentCellDescriptor["settingsKey"] as? String { 
      if let labelString = settings.stringForKey(settingName) { 
       cell?.headerRightLabel?.text = labelString 
      } 
      else { 
       cell?.headerRightLabel?.text = currentCellDescriptor["settingsValue"] as? String 
      } 
      if (currentCellDescriptor["isExpanded"] as? Bool == false) { 
        cell?.drawArrow(arrowDirection: "Down") 
      } 
      else { 
        cell?.drawArrow(arrowDirection: "Up") 
      } 
     } 
     else { 
      cell?.headerRightLabel?.text = "" 
      cell?.drawArrow(arrowDirection: "Right") 
     } 
     if let secondaryTitle = currentCellDescriptor["secondaryTitle"] { 
      cell?.headerLeftLabel?.text = secondaryTitle as? String 
     } 
    } 
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellValuePicker" { 
     cell?.textLabel?.text = currentCellDescriptor["primaryTitle"] as? String 
    } 
    cell?.delegate = self 
    return cell! 
} 

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    (self.tableView.cellForRowAtIndexPath(indexPath) as? CustomCell)?.animateAccesoryView() 
} 

カスタムセルクラス:

class CustomCell: UITableViewCell { 

    // MARK: IBOutlet Properties 

     @IBOutlet weak var textField   : UITextField! 
     @IBOutlet weak var headerLeftLabel  : UILabel? 
     @IBOutlet weak var headerRightLabel  : UILabel? 
     @IBOutlet weak var rightAccessoryView : UIView? 

     var arrowShape = CAShapeLayer() 
     var arrowDownPath = UIBezierPath() 
     var arrowUpPath = UIBezierPath() 
     var arrowRightPath = UIBezierPath() 

     var delegate: CustomCellDelegate! 



    func drawArrow(arrowDirection direction : String) { 
     //Draw Accessory Arrow 

      // Create CAShapeLayerS 
      self.arrowShape.bounds = CGRect(x: 0, y: 0, width: 32, height: 32) 
      self.arrowShape.position = CGPointMake(((rightAccessoryView?.frame.width)!/2), (rightAccessoryView?.frame.height)!/2) 

      self.rightAccessoryView?.layer.addSublayer(self.arrowShape) 

      //Arrow Down Path 
      arrowDownPath.moveToPoint(CGPoint(x: 9, y: 13)) 
      arrowDownPath.addLineToPoint(CGPoint(x: 16, y: 19)) 
      arrowDownPath.addLineToPoint(CGPoint(x: 23, y: 13)) 
      arrowDownPath.addLineToPoint(CGPoint(x: 16, y: 19)) 
      arrowDownPath.addLineToPoint(CGPoint(x: 9, y: 13)) 
      arrowDownPath.closePath() 

      //Arrow Up Path 
      arrowUpPath.moveToPoint(CGPoint(x: 9, y: 19)) 
      arrowUpPath.addLineToPoint(CGPoint(x: 16, y: 13)) 
      arrowUpPath.addLineToPoint(CGPoint(x: 23, y: 19)) 
      arrowUpPath.addLineToPoint(CGPoint(x: 16, y: 13)) 
      arrowUpPath.addLineToPoint(CGPoint(x: 9, y: 19)) 
      arrowUpPath.closePath() 

      //Arrow Up Path 
      arrowRightPath.moveToPoint(CGPoint(x: 13, y: 9)) 
      arrowRightPath.addLineToPoint(CGPoint(x: 19, y: 16)) 
      arrowRightPath.addLineToPoint(CGPoint(x: 13, y: 23)) 
      arrowRightPath.addLineToPoint(CGPoint(x: 19, y: 16)) 
      arrowRightPath.addLineToPoint(CGPoint(x: 13, y: 9)) 
      arrowRightPath.closePath() 

      //set Arrow Shape (CAShapeLayer) 

      switch direction{ 
      case "Down": 
       arrowShape.path = arrowDownPath.CGPath 
      case "Up": 
       arrowShape.path = arrowUpPath.CGPath 
      case "Right": 
       arrowShape.path = arrowRightPath.CGPath 
      default: 
       arrowShape.path = arrowDownPath.CGPath 
      } 

      arrowShape.strokeColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.2).CGColor 
      arrowShape.lineWidth = 1.5 
      arrowShape.lineJoin = kCALineJoinRound 
      arrowShape.lineCap = kCALineCapRound 
      arrowShape.strokeEnd = 0.5 
    } 

func animateAccesoryView(){ 
    let animation = CABasicAnimation(keyPath: "path") 
    if (self.arrowShape.path == arrowDownPath.CGPath) { 
     animation.toValue = arrowUpPath.CGPath 
    } 
    else { 
     animation.toValue = arrowDownPath.CGPath 
    } 
    animation.duration = 0.3 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    animation.fillMode = kCAFillModeBoth 
    animation.removedOnCompletion = false 
    self.arrowShape.addAnimation(animation, forKey: animation.keyPath) 
} 
+1

"オフスクリーンセル"とはどういう意味ですか?セルが表の可視範囲外に出るとすぐに、可視セル(境界から外れた別のセルと同時に境界外に出た場合)に再利用するか、再利用キューに入れます。 –

+1

再使用されたセル(キューから削除されたセル)が選択されているため、この現象が発生します。したがって、どのセルが選択され、どのセルが選択されていないかを覚えておく必要があり、それに応じてcellforRowでセルを設定する必要があります。atIndexPath: – Ionut

+0

@robmayoff - 選択したセルの矢印を変更すると、スクリーンの外にあるボトムまたはトップは、矢印をランダムに変更します。 – Gizmodo

答えて

0

私はテーブルビューのセルのサブクラスでprepareForReuseを使用してこの問題を解決することができました。これはUICollectionViewCellでも使用できます。

override func prepareForReuse() { 
    super.prepareForReuse() 
    self.arrowShape.removeAllAnimations() 
    self.arrowShape.removeFromSuperlayer() 
} 
関連する問題