Skip to content

Instantly share code, notes, and snippets.

@danielctull
Last active November 29, 2015 17:41
Show Gist options
  • Save danielctull/e645724ec6c357ae8cd8 to your computer and use it in GitHub Desktop.
Save danielctull/e645724ec6c357ae8cd8 to your computer and use it in GitHub Desktop.
public extension NSIndexPath {
// Allows us to split NSIndexPaths
public subscript (subrange: Range<Int>) -> NSIndexPath? {
guard subrange.startIndex >= 0 else {
return nil
}
let newLength = subrange.endIndex + 1 - subrange.startIndex
guard newLength > 0 else {
return nil
}
guard subrange.endIndex < length else {
return nil
}
let indexes = indexesForRange(NSRange(location: subrange.startIndex, length: newLength))
return NSIndexPath(indexes:indexes, length:newLength)
}
private func indexesForRange(range: NSRange) -> [Int] {
var indexPointer: UnsafeMutablePointer<Int> = UnsafeMutablePointer.alloc(range.length)
getIndexes(indexPointer, range: range)
var indexes: [Int] = []
for var i = 0; i < range.length; i++ {
indexes.append(indexPointer[i])
}
return indexes
}
}
import UIKit
typealias Frame = CGRect
typealias Width = CGFloat
typealias Height = CGFloat
typealias Item = (Width, NSIndexPath?) -> Frame
let ColumnPadding: CGFloat = 5
let RowPadding: CGFloat = 15
func column(items: [Item]) -> Item {
return { (width, indexPath) in
let itemWidth = width - 2 * ColumnPadding
if let indexPath = indexPath {
let index = indexPath.indexAtPosition(0)
let item = items[index]
let itemIndexPath = indexPath[Range(start: 1, end: indexPath.length - 1)]
return item(itemWidth, itemIndexPath)
}
let height = items.map { $0(itemWidth, nil) }.map { $0.height }.reduce(0, combine: { $0 + $1 + ColumnPadding }) + ColumnPadding
return CGRect(x: 0, y: 0, width: width, height: height)
}
}
func row(columns: [Item]) -> Item {
return { (width, indexPath) in
let columnCount = CGFloat(columns.count)
let totalPadding = (columnCount + 1) * RowPadding
let columnWidth = (width - totalPadding) / columnCount
if let indexPath = indexPath {
let index = indexPath.indexAtPosition(0)
let column = columns[index]
let columnIndexPath = indexPath[Range(start: 1, end: indexPath.length - 1)]
return column(columnWidth, columnIndexPath)
}
let height = columns.map { $0(columnWidth, nil) }.map { $0.height }.reduce(0, combine: { max($0, $1) }) + 2 * RowPadding
return CGRect(x: 0, y: 0, width: width, height: height)
}
}
func item() -> Item {
return { (width, indexPath) in
return CGRect(x: 0, y: 0, width: width, height: 20)
}
}
let column1 = column([item(), item()])
let column2 = column([item(), item(), item()])
let column3 = column([item(), item(), item()])
let row1 = row([column1, column2, column3])
row1(1024, nil)
// Outputs x:0 y:0 w:1024 h:110
row1(900, NSIndexPath(indexes: [1, 2], length: 2))
// Outputs x:0 y:0 w:270 h:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment