2016-12-14 152 views
1

我已经实现UICollectionView,它可以滚动的水平和垂直使用下面的例子粘行和列:CustomCollectionViewLayout不是斯威夫特工作3

Example

Github

Apps的找到Swift2但经过升级Swift3CustomCollectionViewLayout给我错误

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 
      } 
     } 
    } 
} 

感谢

+0

如果你得到错误的,什么是错误的编辑与你的问题细节。 –

+0

@NiravD 第一个错误是返回self.itemAttributes [indexPath.section] [indexPath.row] as! UICollectionViewLayoutAttributes //错误:类型'Any'没有下标成员 第二个错误是return rect.intersects(evaluateObject.frame)//错误:类型为'Any?'的值没有成员'框' –

+0

@NiravD如果你滚动编码部分,你可以找到它我已经提到了评论中的错误... –

回答

1

你好取代你CustomCollectionViewLayout这个
CustomCollectionViewLayout.swift

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

我使用https://github.com/bartjacobs/StickyHeadersCollectionView

对于Swift 4 with xCode 9.2我的问题是,StickyHeadersCollectionViewFlowLayout停止时Swift 3 @objc inference被设置为默认或关闭工作(设置它在问题已经消失),但因为Swift 3 @objc inference是应该解决的问题我深入了解并发现,我只需要使用@objcUICollectionViewDelegate方法(对我来说,更精确地说是刚刚过去的一个):

// 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 
    } 
}