Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for direct instantiation of UIView from nib #5

Merged
merged 1 commit into from
Jan 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Example/ReusableDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
09B346421C4EF71900BA041F /* MyXIBIndexSquaceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 09B346401C4EF71900BA041F /* MyXIBIndexSquaceCell.xib */; };
09B346441C4EF8B700BA041F /* CollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09B346431C4EF8B700BA041F /* CollectionHeaderView.swift */; };
09B346461C4EF8F600BA041F /* CollectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 09B346451C4EF8F600BA041F /* CollectionHeaderView.xib */; };
CD1A4B0A1C5A1BAF00F28455 /* NibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD1A4B091C5A1BAF00F28455 /* NibLoadable.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -55,6 +56,7 @@
09B346401C4EF71900BA041F /* MyXIBIndexSquaceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyXIBIndexSquaceCell.xib; sourceTree = "<group>"; };
09B346431C4EF8B700BA041F /* CollectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionHeaderView.swift; sourceTree = "<group>"; };
09B346451C4EF8F600BA041F /* CollectionHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CollectionHeaderView.xib; sourceTree = "<group>"; };
CD1A4B091C5A1BAF00F28455 /* NibLoadable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NibLoadable.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -75,7 +77,9 @@
09B3460B1C4ED26F00BA041F /* ReusableDemo */,
09B3460A1C4ED26F00BA041F /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
09B3460A1C4ED26F00BA041F /* Products */ = {
isa = PBXGroup;
Expand Down Expand Up @@ -127,6 +131,7 @@
09B3462C1C4ED6F000BA041F /* Reusable */ = {
isa = PBXGroup;
children = (
CD1A4B091C5A1BAF00F28455 /* NibLoadable.swift */,
09B3462D1C4ED72B00BA041F /* Reusable.swift */,
09B3462F1C4ED75400BA041F /* README.md */,
09B346351C4EF12200BA041F /* CHANGELOG.md */,
Expand Down Expand Up @@ -236,6 +241,7 @@
09B346281C4ED51600BA041F /* MyXIBSwitchCell.swift in Sources */,
09B346441C4EF8B700BA041F /* CollectionHeaderView.swift in Sources */,
09B3462B1C4ED6C400BA041F /* MySimpleColorCell.swift in Sources */,
CD1A4B0A1C5A1BAF00F28455 /* NibLoadable.swift in Sources */,
09B346371C4EF13300BA041F /* Reusable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
29 changes: 29 additions & 0 deletions Sources/NibLoadable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import UIKit

/// Make your UIView subclasses
/// conform to this protocol when they *are* NIB-based
/// to be able to instantiate them from NIB in a type-safe manner
public protocol NibLoadable: class {
static var nib: UINib { get }
}

// MARK: - Default implementation form NibLoadable

public extension NibLoadable {
static var nib: UINib {
return UINib(nibName: String(Self), bundle: nil)
}
}

// MARK: - Support for instantiation from nib

public extension NibLoadable where Self: UIView {
/**
Returns a `UIView` object instantiated from nib

- returns: A `NibLoadable`, `UIView` instance
*/
static func loadFromNib() -> Self {
return nib.instantiateWithOwner(nil, options: nil).first as! Self
}
}
73 changes: 34 additions & 39 deletions Sources/Reusable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,24 @@ public protocol Reusable: class {
/// Make your UITableViewCell and UICollectionViewCell subclasses
/// conform to this protocol when they *are* NIB-based
/// to be able to dequeue them in a type-safe manner
public protocol NibReusable: Reusable {
static var nib: UINib { get }
}
public protocol NibReusable: Reusable, NibLoadable {}

// MARK: - Default implementation for Reusable

public extension Reusable {
static var reuseIdentifier: String {
return String(Self)
}
}
public extension NibReusable {
static var nib: UINib {
return UINib(nibName: String(Self), bundle: nil)
}
}

// MARK: - UITableView support for Reusable & NibReusable

public extension UITableView {
/**
Register a NIB-Based `UITableViewCell` subclass (conforming to `NibReusable`)

- parameter cellType: the `UITableViewCell` (`NibReusable`-conforming) subclass to register

- seealso: `registerNib(_:,forCellReuseIdentifier:)`
*/
func registerReusableCell<T: UITableViewCell where T: NibReusable>(cellType: T.Type) {
Expand All @@ -41,9 +36,9 @@ public extension UITableView {

/**
Register a Class-Based `UITableViewCell` subclass (conforming to `Reusable`)

- parameter cellType: the `UITableViewCell` (`Reusable`-conforming) subclass to register

- seealso: `registerClass(_:,forCellReuseIdentifier:)`
*/
func registerReusableCell<T: UITableViewCell where T: Reusable>(cellType: T.Type) {
Expand All @@ -52,11 +47,11 @@ public extension UITableView {

/**
Returns a reusable `UITableViewCell` object for the class infered by the return-type

- parameter indexPath: The index path specifying the location of the cell.

- returns: A `Reusable`, `UITableViewCell` instance

- seealso: `dequeueReusableCellWithIdentifier(_:,forIndexPath:)`
*/
func dequeueReusableCell<T: UITableViewCell where T: Reusable>(indexPath indexPath: NSIndexPath) -> T {
Expand All @@ -65,9 +60,9 @@ public extension UITableView {

/**
Register a NIB-Based `UITableViewHeaderFooterView` subclass (conforming to `NibReusable`)

- parameter viewType: the `UITableViewHeaderFooterView` (`NibReusable`-conforming) subclass to register

- seealso: `registerNib(_:,forHeaderFooterViewReuseIdentifier:)`
*/
func registerReusableHeaderFooterView<T: UITableViewHeaderFooterView where T: NibReusable>(viewType: T.Type) {
Expand All @@ -76,9 +71,9 @@ public extension UITableView {

/**
Register a Class-Based `UITableViewHeaderFooterView` subclass (conforming to `Reusable`)

- parameter viewType: the `UITableViewHeaderFooterView` (`Reusable`-confirming) subclass to register

- seealso: `registerClass(_:,forHeaderFooterViewReuseIdentifier:)`
*/
func registerReusableHeaderFooterView<T: UITableViewHeaderFooterView where T: Reusable>(viewType: T.Type) {
Expand All @@ -87,9 +82,9 @@ public extension UITableView {

/**
Returns a reusable `UITableViewHeaderFooterView` object for the class infered by the return-type

- returns: A `Reusable`, `UITableViewHeaderFooterView` instance

- seealso: `dequeueReusableHeaderFooterViewWithIdentifier(_:)`
*/
func dequeueReusableHeaderFooterView<T: UITableViewHeaderFooterView where T: Reusable>() -> T? {
Expand All @@ -102,20 +97,20 @@ public extension UITableView {
public extension UICollectionView {
/**
Register a NIB-Based `UICollectionViewCell` subclass (conforming to `NibReusable`)

- parameter cellType: the `UICollectionViewCell` (`NibReusable`-conforming) subclass to register

- seealso: `registerNib(_:,forCellWithReuseIdentifier:)`
*/
func registerReusableCell<T: UICollectionViewCell where T: NibReusable>(cellType: T.Type) {
self.registerNib(T.nib, forCellWithReuseIdentifier: T.reuseIdentifier)
}

/**
Register a Class-Based `UICollectionViewCell` subclass (conforming to `Reusable`)

- parameter cellType: the `UICollectionViewCell` (`Reusable`-conforming) subclass to register

- seealso: `registerClass(_:,forCellWithReuseIdentifier:)`
*/
func registerReusableCell<T: UICollectionViewCell where T: Reusable>(cellType: T.Type) {
Expand All @@ -124,11 +119,11 @@ public extension UICollectionView {

/**
Returns a reusable `UICollectionViewCell` object for the class infered by the return-type

- parameter indexPath: The index path specifying the location of the cell.

- returns: A `Reusable`, `UICollectionViewCell` instance

- seealso: `dequeueReusableCellWithReuseIdentifier(_:,forIndexPath:)`
*/
func dequeueReusableCell<T: UICollectionViewCell where T: Reusable>(indexPath indexPath: NSIndexPath) -> T {
Expand All @@ -137,36 +132,36 @@ public extension UICollectionView {

/**
Register a NIB-Based `UICollectionReusableView` subclass (conforming to `NibReusable`) as a Supplementary View

- parameter elementKind: The kind of supplementary view to create.
- parameter viewType: the `UIView` (`NibReusable`-conforming) subclass to register as Supplementary View

- seealso: `registerNib(_:,forSupplementaryViewOfKind:,withReuseIdentifier:)`
*/
func registerReusableSupplementaryView<T: UICollectionReusableView where T: NibReusable>(elementKind: String, viewType: T.Type) {
self.registerNib(T.nib, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: T.reuseIdentifier)
self.registerNib(T.nib, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: T.reuseIdentifier)
}

/**
Register a Class-Based `UICollectionReusableView` subclass (conforming to `Reusable`) as a Supplementary View

- parameter elementKind: The kind of supplementary view to create.
- parameter viewType: the `UIView` (`Reusable`-conforming) subclass to register as Supplementary View

- seealso: `registerClass(_:,forSupplementaryViewOfKind:,withReuseIdentifier:)`
*/
func registerReusableSupplementaryView<T: UICollectionReusableView where T: Reusable>(elementKind: String, viewType: T.Type) {
self.registerClass(T.self, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: T.reuseIdentifier)
self.registerClass(T.self, forSupplementaryViewOfKind: elementKind, withReuseIdentifier: T.reuseIdentifier)
}

/**
Returns a reusable `UICollectionReusableView` object for the class infered by the return-type

- parameter elementKind: The kind of supplementary view to retrieve.
- parameter indexPath: The index path specifying the location of the cell.

- returns: A `Reusable`, `UICollectionReusableView` instance

- seealso: `dequeueReusableSupplementaryViewOfKind(_:,withReuseIdentifier:,forIndexPath:)`
*/
func dequeueReusableSupplementaryView<T: UICollectionReusableView where T: Reusable>(elementKind: String, indexPath: NSIndexPath) -> T {
Expand Down