             }
         }
     }
-
+    
     /**
      *  Min scale that can be applied to individual item.
      *  Default to 1.0 (no scale).
      */
-    public var minCoverScale:CGFloat = 1.0
-    // TODO: Add validation for correct values here
-
+    open var minCoverScale:CGFloat = 1.0  {
+        didSet {
+            if minCoverScale < 0 {
+                minCoverScale = 0
+            } else if minCoverScale > 1 {
+                minCoverScale = 1
+            }
+        }
+    }
+    
     // Private Constant. Not a good naming convention but keeping as close to inspiration as possible
-    private let kDistanceToProjectionPlane:CGFloat = 500.0
-
-
+    fileprivate let kDistanceToProjectionPlane:CGFloat = 500.0
+
+    
     // MARK: Overrides
-
+    
     // Thanks to property initializations we do not need to override init(*)
-
-    override public func prepareLayout() {
-        super.prepareLayout()
-
-        // TODO: Why do we have these limitations? Can the Swift version support these?
-        assert(self.collectionView?.numberOfSections() == 1, "[LNICoverFlowLayout]: Multiple sections are not supported")
-        assert(self.scrollDirection == .Horizontal, "[LNICoverFlowLayout]: Vertical scrolling is not supported")
-    }
-
-    override public func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
+    
+    override open func prepare() {
+        super.prepare()
+        
+        assert(self.collectionView?.numberOfSections == 1, "[LNICoverFlowLayout]: Multiple sections are not supported")
+        assert(self.scrollDirection == .horizontal, "[LNICoverFlowLayout]: Vertical scrolling is not supported")
+    }
+    
+    override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
         return true
     }
-
-    override public func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
+    
+    override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
         let idxPaths = indexPathsContainedInRect(rect)
-
+        
         var resultingAttributes = [UICollectionViewLayoutAttributes]()
-
+        
         for path in idxPaths {
-            resultingAttributes.append(layoutAttributesForItemAtIndexPath(path))
-        }
-
+            resultingAttributes.append(layoutAttributesForItem(at: path))
+        }
+        
         return resultingAttributes
     }
-
-    override public func layoutAttributesForItemAtIndexPath(indexPath:NSIndexPath)->UICollectionViewLayoutAttributes {
-        let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath:indexPath)
-
+    
+    override open func layoutAttributesForItem(at indexPath:IndexPath)->UICollectionViewLayoutAttributes {
+        let attributes = UICollectionViewLayoutAttributes(forCellWith:indexPath)
+        
         attributes.size = self.itemSize
         attributes.center = CGPoint(x: collectionViewWidth()*CGFloat(indexPath.row) + collectionViewWidth(),
                                     y: collectionViewHeight()/2)
-
+        
         let contentOffsetX = collectionView?.contentOffset.x ?? 0
-
+        
         return interpolateAttributes(attributes, forOffset: contentOffsetX)
     }
-
-    override public func collectionViewContentSize() -> CGSize {
+    
+    override open var collectionViewContentSize : CGSize {
         if let collectionView = collectionView {
-            return CGSize(width: collectionView.bounds.size.width * CGFloat(collectionView.numberOfItemsInSection(0)),
+            return CGSize(width: collectionView.bounds.size.width * CGFloat(collectionView.numberOfItems(inSection: 0)),
                           height: collectionView.bounds.size.height)
         }
-        return CGSizeZero
-    }
-
+        return CGSize.zero
+    }
+    
     // MARK: Accessors
-    private func collectionViewHeight() -> CGFloat {
+    fileprivate func collectionViewHeight() -> CGFloat {
         let height = collectionView?.bounds.size.height ?? 0
         return height
     }
-
-    private func collectionViewWidth() -> CGFloat {
+    
+    fileprivate func collectionViewWidth() -> CGFloat {
         let width = collectionView?.bounds.size.width ?? 0
         return width
     }
-
+    
     // MARK: Private
-
-    private func itemCenterForRow(row:Int)->CGPoint {
-        let collectionViewSize = collectionView?.bounds.size ?? CGSizeZero
+    
+    fileprivate func itemCenterForRow(_ row:Int)->CGPoint {
+        let collectionViewSize = collectionView?.bounds.size ?? CGSize.zero
         return CGPoint(x: CGFloat(row) * collectionViewSize.width + collectionViewSize.width / 2,
                        y: collectionViewSize.height/2)
     }
-
-    private func minXForRow(row:Int)->CGFloat {
+    
+    fileprivate func minXForRow(_ row:Int)->CGFloat {
         return itemCenterForRow(row - 1).x + (1.0 / 2 - self.coverDensity) * self.itemSize.width
     }
-
-    private func maxXForRow(row:Int)->CGFloat {
+    
+    fileprivate func maxXForRow(_ row:Int)->CGFloat {
         return itemCenterForRow(row + 1).x - (1.0 / 2 - self.coverDensity) * self.itemSize.width
     }
-
-    private func minXCenterForRow(row:Int)->CGFloat {
+    
+    fileprivate func minXCenterForRow(_ row:Int)->CGFloat {
         let halfWidth = self.itemSize.width / 2
         let maxRads = degreesToRad(self.maxCoverDegree)
-
+        
         let center = itemCenterForRow(row - 1).x
         let prevItemRightEdge = center + halfWidth
         let projectedLeftEdgeLocal = halfWidth * cos(maxRads) * kDistanceToProjectionPlane / (kDistanceToProjectionPlane + halfWidth * sin(maxRads))
-
+        
         return prevItemRightEdge - (self.coverDensity * self.itemSize.width) + projectedLeftEdgeLocal
     }
-
-    private func maxXCenterForRow(row:Int)->CGFloat {
+    
+    fileprivate func maxXCenterForRow(_ row:Int)->CGFloat {
         let halfWidth = self.itemSize.width / 2
         let maxRads = degreesToRad(self.maxCoverDegree)
-
+        
         let center = itemCenterForRow(row + 1).x
         let nextItemLeftEdge = center - halfWidth
         let projectedRightEdgeLocal = fabs(halfWidth * cos(maxRads) * kDistanceToProjectionPlane / (-halfWidth * sin(maxRads) - kDistanceToProjectionPlane))
-
+        
         return nextItemLeftEdge + (self.coverDensity * self.itemSize.width) - projectedRightEdgeLocal
     }
-
-    private func degreesToRad(degrees:CGFloat)->CGFloat {
+    
+    fileprivate func degreesToRad(_ degrees:CGFloat)->CGFloat {
         return CGFloat(Double(degrees) * M_PI / 180)
     }
-
-    private func indexPathsContainedInRect(rect:CGRect)->[NSIndexPath] {
-        let noI = collectionView?.numberOfItemsInSection(0) ?? 0
+    
+    fileprivate func indexPathsContainedInRect(_ rect:CGRect)->[IndexPath] {
+        let noI = collectionView?.numberOfItems(inSection: 0) ?? 0
         if noI == 0 {
             return []
         }
-
+        
         let cvW = collectionViewWidth()
-
+        
         // Find min and max rows that can be determined for sure
         var minRow = Int(max(rect.origin.x/cvW, 0))
         var maxRow = 0
         if cvW != 0 {
-            maxRow = Int(CGRectGetMaxX(rect) / cvW)
-        }
-
+            maxRow = Int(rect.maxX / cvW)
+        }
+        
         // Additional check for rows that also can be included (our rows are moving depending on content size)
         let candidateMinRow = max(minRow-1, 0)
-
+        
         if maxXForRow(candidateMinRow) >= rect.origin.x {
             minRow = candidateMinRow
         }
-
+        
         let candidateMaxRow = min(maxRow + 1, noI - 1)
-        if minXForRow(candidateMaxRow) <= CGRectGetMaxX(rect) {
+        if minXForRow(candidateMaxRow) <= rect.maxX {
             maxRow = candidateMaxRow
         }
-
+        
         // Simply add index paths between min and max.
-        var resultingIdxPaths = [NSIndexPath]()
-
-        for i in minRow...maxRow {
-            resultingIdxPaths.append(NSIndexPath(forRow: i, inSection: 0))
-        }
-
+        var resultingIdxPaths = [IndexPath]()
+        
+        if minRow < maxRow {
+            for i in minRow...maxRow {
+                resultingIdxPaths.append(IndexPath(row: i, section: 0))
+            }
+        }
+        
         return resultingIdxPaths
     }
-
-    private func interpolateAttributes(attributes:UICollectionViewLayoutAttributes, forOffset offset:CGFloat)->UICollectionViewLayoutAttributes {
+    
+    fileprivate func interpolateAttributes(_ attributes:UICollectionViewLayoutAttributes, forOffset offset:CGFloat)->UICollectionViewLayoutAttributes {
 
         let attributesPath = attributes.indexPath
-
+        
         let minInterval = CGFloat(attributesPath.row - 1) * collectionViewWidth()
         let maxInterval = CGFloat(attributesPath.row + 1) * collectionViewWidth()
-
+        
         let minX = minXCenterForRow(attributesPath.row)
         let maxX = maxXCenterForRow(attributesPath.row)
         let spanX = maxX - minX
-
+        
         // Interpolate by formula
         let interpolatedX = min(max(minX + ((spanX / (maxInterval - minInterval)) * (offset - minInterval)), minX), maxX)
-
-        attributes.center = CGPointMake(interpolatedX, attributes.center.y)
-
+        
+        attributes.center = CGPoint(x: interpolatedX, y: attributes.center.y)
+        
         var transform = CATransform3DIdentity
-
+        
         // Add perspective
         transform.m34 = -1.0 / kDistanceToProjectionPlane
-
+        
         // Then rotate.
         let angle = -self.maxCoverDegree + (interpolatedX - minX) * 2 * self.maxCoverDegree / spanX
         transform = CATransform3DRotate(transform, degreesToRad(angle), 0, 1, 0)
-
+        
         // Then scale: 1 - abs(1 - Q - 2 * x * (1 - Q))
         let scale = 1.0 - abs(1 - self.minCoverScale - (interpolatedX - minX) * 2 * (1.0 - self.minCoverScale) / spanX)
         transform = CATransform3DScale(transform, scale, scale, scale)
-
+        
         // Apply transform
         attributes.transform3D = transform
-
+        
         // Add opacity: 1 - abs(1 - Q - 2 * x * (1 - Q))
         let opacity = 1.0 - abs(1 - self.minCoverOpacity - (interpolatedX - minX) * 2 * (1 - self.minCoverOpacity) / spanX)
-
+        
         attributes.alpha = opacity
-
+        
 //        print(String(format:"IDX: %d. MinX: %.2f. MaxX: %.2f. Interpolated: %.2f. Interpolated angle: %.2f",
 //               attributesPath.row,
 //               minX,

//               interpolatedX,
//               angle));


        return attributes
    }
}

     *  0 means that items are placed within a continuous line.
     *  0.5 means that half of 3rd and 1st item will be behind 2nd.
     */
    open var coverDensity:CGFloat = 0.25 {
        didSet {
            if coverDensity < 0 {
                coverDensity = 0
