2016-12-14 3 views
1

I UICollectionView umgesetzt haben, und es kann unter Beispiel mit klebrigen Zeilen und Spalten horizontal und vertikal scrollen mit:CustomCollectionViewLayout arbeiten nicht auf Swift 3

Example

Github

Apps arbeitet auf Swift2 finden, aber nach upgrade Swift3CustomCollectionViewLayout gibt mir Fehler

class CustomCollectionViewLayout: UICollectionViewLayout { 

    let numberOfColumns = 8 
    var itemAttributes : NSMutableArray! 
    var itemsSize : NSMutableArray! 
    var contentSize : CGSize! 

    override func prepare() { 
     if self.collectionView?.numberOfSections == 0 { 
      return 
     } 

     if (self.itemAttributes != nil && self.itemAttributes.count > 0) { 
      for section in 0..<self.collectionView!.numberOfSections { 
       let numberOfItems : Int = self.collectionView!.numberOfItems(inSection: section) 
       for index in 0..<numberOfItems { 
        if section != 0 && index != 0 { 
         continue 
        } 

        let attributes : UICollectionViewLayoutAttributes = self.layoutAttributesForItem(at: IndexPath(item: index, section: section)) 
        if section == 0 { 
         var frame = attributes.frame 
         frame.origin.y = self.collectionView!.contentOffset.y 
         attributes.frame = frame 
        } 

        if index == 0 { 
         var frame = attributes.frame 
         frame.origin.x = self.collectionView!.contentOffset.x 
         attributes.frame = frame 
        } 
       } 
      } 
      return 
     } 

     if (self.itemsSize == nil || self.itemsSize.count != numberOfColumns) { 
      self.calculateItemsSize() 
     } 

     var column = 0 
     var xOffset : CGFloat = 0 
     var yOffset : CGFloat = 0 
     var contentWidth : CGFloat = 0 
     var contentHeight : CGFloat = 0 

     for section in 0..<self.collectionView!.numberOfSections { 
      let sectionAttributes = NSMutableArray() 

      for index in 0..<numberOfColumns { 
       let itemSize = (self.itemsSize[index] as AnyObject).cgSizeValue 
       let indexPath = IndexPath(item: index, section: section) 
       let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath) 
       attributes.frame = CGRect(x: xOffset, y: yOffset, width: (itemSize?.width)!, height: (itemSize?.height)!).integral 

       if section == 0 && index == 0 { 
        attributes.zIndex = 1024; 
       } else if section == 0 || index == 0 { 
        attributes.zIndex = 1023 
       } 

       if section == 0 { 
        var frame = attributes.frame 
        frame.origin.y = self.collectionView!.contentOffset.y 
        attributes.frame = frame 
       } 
       if index == 0 { 
        var frame = attributes.frame 
        frame.origin.x = self.collectionView!.contentOffset.x 
        attributes.frame = frame 
       } 

       sectionAttributes.add(attributes) 

       xOffset += (itemSize?.width)! 
       column += 1 

       if column == numberOfColumns { 
        if xOffset > contentWidth { 
         contentWidth = xOffset 
        } 

        column = 0 
        xOffset = 0 
        yOffset += (itemSize?.height)! 
       } 
      } 
      if (self.itemAttributes == nil) { 
       self.itemAttributes = NSMutableArray(capacity: self.collectionView!.numberOfSections) 
      } 
      self.itemAttributes .add(sectionAttributes) 
     } 

     let attributes : UICollectionViewLayoutAttributes = (self.itemAttributes.lastObject as AnyObject).lastObject as! UICollectionViewLayoutAttributes 
     contentHeight = attributes.frame.origin.y + attributes.frame.size.height 
     self.contentSize = CGSize(width: contentWidth, height: contentHeight) 
    } 

    override var collectionViewContentSize : CGSize { 
     return self.contentSize 
    } 

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes! { 
     return self.itemAttributes[indexPath.section][indexPath.row] as! UICollectionViewLayoutAttributes 
     // Error in above return line and error is Type 'Any' has no subscript members 
    } 

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
     var attributes = [UICollectionViewLayoutAttributes]() 
     if self.itemAttributes != nil { 
      for section in self.itemAttributes { 

       let filteredArray = (section as AnyObject).filtered(

        using: NSPredicate(block: { (evaluatedObject, bindings) -> Bool in 
         return rect.intersects(evaluatedObject.frame) 
         // Error in above return line and error is Value of type 'Any?' has no member 'frame' 
        }) 
        ) as! [UICollectionViewLayoutAttributes] 


       attributes.append(contentsOf: filteredArray) 

      } 
     } 

     return attributes 
    } 

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 
     return true 
    } 

    func sizeForItemWithColumnIndex(_ columnIndex: Int) -> CGSize { 
     var text : String = "" 
     switch (columnIndex) { 
     case 0: 
      text = "Col 0" 
     case 1: 
      text = "Col 1" 
     case 2: 
      text = "Col 2" 
     case 3: 
      text = "Col 3" 
     case 4: 
      text = "Col 4" 
     case 5: 
      text = "Col 5" 
     case 6: 
      text = "Col 6" 
     default: 
      text = "Col 7" 
     } 

     let size : CGSize = (text as NSString).size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 17.0)]) 
     let width : CGFloat = size.width + 25 
     return CGSize(width: width, height: 30) 
    } 

    func calculateItemsSize() { 
     self.itemsSize = NSMutableArray(capacity: numberOfColumns) 
     for index in 0..<numberOfColumns { 
      self.itemsSize.add(NSValue(cgSize: self.sizeForItemWithColumnIndex(index))) 
     } 
    } 
} 

ContentCollectionViewCell

class ContentCollectionViewCell: UICollectionViewCell { 
    @IBOutlet weak var contentLabel: UILabel! 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     // Initialization code 
    } 

} 

DateCollectionViewCell

class DateCollectionViewCell: UICollectionViewCell { 
    @IBOutlet weak var dateLabel: UILabel! 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     // Initialization code 
    } 

} 

CollectionViewController

class CollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { 
    let dateCellIdentifier = "DateCellIdentifier" 
    let contentCellIdentifier = "ContentCellIdentifier" 
    @IBOutlet weak var collectionView: UICollectionView! 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.collectionView .register(UINib(nibName: "DateCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: dateCellIdentifier) 
     self.collectionView .register(UINib(nibName: "ContentCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: contentCellIdentifier) 
    } 


    // MARK - UICollectionViewDataSource 

    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 5 
    } 


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return 8 
    } 


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     print(indexPath.description) 
     if indexPath.section == 0 { 
      if indexPath.row == 0 { 
       let dateCell : DateCollectionViewCell = collectionView .dequeueReusableCell(withReuseIdentifier: dateCellIdentifier, for: indexPath) as! DateCollectionViewCell 
       dateCell.backgroundColor = UIColor.white 
       dateCell.dateLabel.font = UIFont.systemFont(ofSize: 13) 
       dateCell.dateLabel.textColor = UIColor.black 
       dateCell.dateLabel.text = "Donor ID" 

       return dateCell 
      } else { 
       let contentCell : ContentCollectionViewCell = collectionView .dequeueReusableCell(withReuseIdentifier: contentCellIdentifier, for: indexPath) as! ContentCollectionViewCell 
       contentCell.contentLabel.font = UIFont.systemFont(ofSize: 13) 
       contentCell.contentLabel.textColor = UIColor.black 
       contentCell.contentLabel.text = "Section" 

       if indexPath.section % 2 != 0 { 
        contentCell.backgroundColor = UIColor(white: 242/255.0, alpha: 1.0) 
       } else { 
        contentCell.backgroundColor = UIColor.white 
       } 

       return contentCell 
      } 
     } else { 
      if indexPath.row == 0 { 
       let dateCell : DateCollectionViewCell = collectionView .dequeueReusableCell(withReuseIdentifier: dateCellIdentifier, for: indexPath) as! DateCollectionViewCell 
       dateCell.dateLabel.font = UIFont.systemFont(ofSize: 13) 
       dateCell.dateLabel.textColor = UIColor.black 
       dateCell.dateLabel.text = String(indexPath.section) 
       if indexPath.section % 2 != 0 { 
        dateCell.backgroundColor = UIColor(white: 242/255.0, alpha: 1.0) 
       } else { 
        dateCell.backgroundColor = UIColor.white 
       } 

       return dateCell 
      } else { 
       let contentCell : ContentCollectionViewCell = collectionView .dequeueReusableCell(withReuseIdentifier: contentCellIdentifier, for: indexPath) as! ContentCollectionViewCell 
       contentCell.contentLabel.font = UIFont.systemFont(ofSize: 13) 
       contentCell.contentLabel.textColor = UIColor.black 
       contentCell.contentLabel.text = "Section:\(indexPath.section.description)/Row: \(indexPath.row.description)" 
       if indexPath.section % 2 != 0 { 
        contentCell.backgroundColor = UIColor(white: 242/255.0, alpha: 1.0) 
       } else { 
        contentCell.backgroundColor = UIColor.white 
       } 

       return contentCell 
      } 
     } 
    } 
} 

Dank

+0

Wo Sie Fehler bekommen und was ist der Fehler bearbeiten Ihre Frage mit, dass Details. –

+0

@NiravD 1. Fehler ist zurück selb.itemAttributes [indexPath.section] [indexPath.row] as! UICollectionViewLayoutAttributes // Fehler: Typ 'Any' hat keine tiefgestellten Mitglieder 2. Fehler ist zurück rect.intersects (evaluatedObject.frame) // Fehler: Wert des Typs 'Any?' hat kein Mitglied 'frame' –

+0

@NiravD wenn Sie den Codierungsabschnitt scrollen, können Sie es finden Ich habe den Fehler in Kommentar erwähnt ... –

Antwort

1

Hallo Ihr CustomCollectionViewLayout mit diesem
CustomCollectionViewLayout.swift ich https://github.com/bartjacobs/StickyHeadersCollectionView bin mit

Für Swift 4 with xCode 9.2 mein Problem war

let numberOfColumns = 8 
var itemAttributes : NSMutableArray! 
var itemsSize : NSMutableArray! 
var contentSize : CGSize! 

override func prepare() { 
if self.collectionView?.numberOfSections == 0 { 
    return 
} 

if (self.itemAttributes != nil && self.itemAttributes.count > 0) { 
    for section in 0..<self.collectionView!.numberOfSections { 
     let numberOfItems : Int = self.collectionView!.numberOfItems(inSection: section) 
     for index in 0..<numberOfItems { 
      if section != 0 && index != 0 { 
       continue 
      } 

      let attributes : UICollectionViewLayoutAttributes = self.layoutAttributesForItem(at: IndexPath(item: index, section: section)) 
      if section == 0 { 
       var frame = attributes.frame 
       frame.origin.y = self.collectionView!.contentOffset.y 
       attributes.frame = frame 
      } 

      if index == 0 { 
       var frame = attributes.frame 
       frame.origin.x = self.collectionView!.contentOffset.x 
       attributes.frame = frame 
      } 
     } 
    } 
    return 
} 

if (self.itemsSize == nil || self.itemsSize.count != numberOfColumns) { 
    self.calculateItemsSize() 
} 

var column = 0 
var xOffset : CGFloat = 0 
var yOffset : CGFloat = 0 
var contentWidth : CGFloat = 0 
var contentHeight : CGFloat = 0 

for section in 0..<self.collectionView!.numberOfSections { 
    let sectionAttributes = NSMutableArray() 

    for index in 0..<numberOfColumns { 
     let itemSize = (self.itemsSize[index] as AnyObject).cgSizeValue 
     let indexPath = IndexPath(item: index, section: section) 
     let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath) 
     attributes.frame = CGRect(x: xOffset, y: yOffset, width: (itemSize?.width)!, height: (itemSize?.height)!).integral 

     if section == 0 && index == 0 { 
      attributes.zIndex = 1024; 
     } else if section == 0 || index == 0 { 
      attributes.zIndex = 1023 
     } 

     if section == 0 { 
      var frame = attributes.frame 
      frame.origin.y = self.collectionView!.contentOffset.y 
      attributes.frame = frame 
     } 
     if index == 0 { 
      var frame = attributes.frame 
      frame.origin.x = self.collectionView!.contentOffset.x 
      attributes.frame = frame 
     } 

     sectionAttributes.add(attributes) 

     xOffset += (itemSize?.width)! 
     column += 1 

     if column == numberOfColumns { 
      if xOffset > contentWidth { 
       contentWidth = xOffset 
      } 

      column = 0 
      xOffset = 0 
      yOffset += (itemSize?.height)! 
     } 
    } 
    if (self.itemAttributes == nil) { 
     self.itemAttributes = NSMutableArray(capacity: self.collectionView!.numberOfSections) 
    } 
    self.itemAttributes .add(sectionAttributes) 
} 

let attributes : UICollectionViewLayoutAttributes = (self.itemAttributes.lastObject as AnyObject).lastObject as! UICollectionViewLayoutAttributes 
contentHeight = attributes.frame.origin.y + attributes.frame.size.height 
self.contentSize = CGSize(width: contentWidth, height: contentHeight) 
} 

override var collectionViewContentSize : CGSize { 
return self.contentSize 
} 

override func layoutAttributesForItem(at indexPath: IndexPath) ->  UICollectionViewLayoutAttributes! { 
//return self.itemAttributes[indexPath.section][indexPath.row] as! UICollectionViewLayoutAttributes 
let arr = self.itemAttributes[indexPath.section] as! NSMutableArray 
return arr[indexPath.row] as! UICollectionViewLayoutAttributes 
} 

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
var attributes = [UICollectionViewLayoutAttributes]() 
if self.itemAttributes != nil { 
    for section in self.itemAttributes { 

     let filteredArray = (section as! NSMutableArray).filtered(

      using: NSPredicate(block: { (evaluatedObject , bindings) -> Bool in 
       let a = evaluatedObject as! UICollectionViewLayoutAttributes 
       return rect.intersects(a.frame) 
      }) 
      ) as! [UICollectionViewLayoutAttributes] 


     attributes.append(contentsOf: filteredArray) 

    } 
} 

return attributes 
} 

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 
return true 
} 

func sizeForItemWithColumnIndex(_ columnIndex: Int) -> CGSize { 
var text : String = "" 
switch (columnIndex) { 
case 0: 
    text = "Col 0" 
case 1: 
    text = "Col 1" 
case 2: 
    text = "Col 2" 
case 3: 
    text = "Col 3" 
case 4: 
    text = "Col 4" 
case 5: 
    text = "Col 5" 
case 6: 
    text = "Col 6" 
default: 
    text = "Col 7" 
} 

let size : CGSize = (text as NSString).size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 17.0)]) 
let width : CGFloat = size.width + 25 
return CGSize(width: width, height: 30) 
} 

func calculateItemsSize() { 
self.itemsSize = NSMutableArray(capacity: numberOfColumns) 
for index in 0..<numberOfColumns { 
    self.itemsSize.add(NSValue(cgSize: self.sizeForItemWithColumnIndex(index))) 
} 
} 
} 
0

ersetzen, dass StickyHeadersCollectionViewFlowLayout aufgehört zu arbeiten, wenn Swift 3 @objc inference eingestellt wurde auf Standard oder Off (Setzen Sie es auf das Problem war weg) aber seit Swift 3 @objc inference ist etwas, das gelöst werden sollte, nahm ich einen tieferen Blick und fand heraus, dass ich nurverwenden mussteauf UICollectionViewDelegate Methoden (für mich, genauer gesagt war nur der letzte zu sein):

// MARK: - Collection View Delegate Flow Layout Methods 
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 
    return CGSize(width: collectionView.bounds.width, height: self.gridCellHeight) 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 
    return UIEdgeInsets.zero 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 
    return 0.0 
} 

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 
    return 0.0 
} 

@objc func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 
    if useStickyHeader { 
     return CGSize(width: collectionView.bounds.width, height: self.gridCellHeight) 
    } else { 
     return CGSize.zero 
    } 
}