Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import Reusable
* This view is NOT loaded from a NIB (but defined entierly by code),
* that's why it's not annotated as `NibLoadable` but only `Reusable`
*/
final class MyColorSquareCell: UICollectionViewCell, Reusable {
final class MyColorSquareCell: UICollectionViewCell, Reusable, AutoRegistering {
private lazy var colorView: UIView = {
let colorView = UIView()
colorView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
Expand Down
6 changes: 5 additions & 1 deletion Example/ReusableDemo iOS/CollectionViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ final class CollectionViewController: UICollectionViewController {
guard let collectionView = self.collectionView else { return }

// Register cell classes
collectionView.register(cellType: MyColorSquareCell.self)
collectionView.register(cellType: MyXIBIndexSquaceCell.self)

/* Since MyColorSquareCell is marked as conforming to AutoRegistering,
there's no need to register this type ahead of time */
//collectionView.register(cellType: MyColorSquareCell.self)

// No need to register this one, the UIStoryboard already auto-register its cells
// self.collectionView.registerReusableCell(MyStoryBoardIndexPathCell)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// MyAutoRegisterHeaderTableView.swift
// ReusableDemo
//
// Created by TJB on 07/08/18.
// Copyright © 2018 ApptekStudios. All rights reserved.
//

import UIKit
import Reusable

/**
* This view is loaded from a NIB, and is the XIB file's
* root view (and not the File's Owner). => it is `NibLoadable`
*
* It is also reusable and has a `reuseIdentifier` (as it's a TableViewHeaderFooterView
* and it uses the TableView recycling mechanism) => it is `Reusable`
*
* That's why it's annotated with the `NibReusable` typealias,
* Which in fact is just a convenience typealias that combines
* `NibLoadable` & `Reusable` protocols.
*/
final class MyAutoRegisterTableViewHeader: UITableViewHeaderFooterView, NibReusable, AutoRegistering {

@IBOutlet private weak var titleLabel: UILabel!

static let height: CGFloat = 55

func fillForSection(_ section: Int) {
self.titleLabel.text = "Header Section #\(section)"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="okZ-6Z-SVm" customClass="MyAutoRegisterTableViewHeader" customModule="ReusableDemo_iOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="298.5" height="55"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5FU-EW-ITI">
<rect key="frame" x="0.0" y="0.0" width="298.5" height="55"/>
<color key="backgroundColor" red="0.20392156862745098" green="0.45098039215686275" blue="0.72941176470588232" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="My HeaderView" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hYf-aH-s8i">
<rect key="frame" x="8" y="13" width="121" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zZ4-Xm-Xca" userLabel="Blue Bar">
<rect key="frame" x="8" y="42" width="239" height="5"/>
<color key="backgroundColor" red="0.80177218539999995" green="0.88913449410000001" blue="0.95461380880000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="5" id="k9e-UV-gvq"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="hYf-aH-s8i" firstAttribute="leading" secondItem="zZ4-Xm-Xca" secondAttribute="leading" id="Q4E-ve-ADj"/>
<constraint firstAttribute="trailing" secondItem="5FU-EW-ITI" secondAttribute="trailing" id="cAb-OQ-i7v"/>
<constraint firstAttribute="bottom" secondItem="zZ4-Xm-Xca" secondAttribute="bottom" constant="8" id="g2M-WH-Mhw"/>
<constraint firstItem="5FU-EW-ITI" firstAttribute="leading" secondItem="okZ-6Z-SVm" secondAttribute="leading" id="hue-vz-jI7"/>
<constraint firstItem="zZ4-Xm-Xca" firstAttribute="top" secondItem="hYf-aH-s8i" secondAttribute="bottom" constant="8" symbolic="YES" id="kvp-aL-8Hr"/>
<constraint firstItem="zZ4-Xm-Xca" firstAttribute="leading" secondItem="okZ-6Z-SVm" secondAttribute="leading" constant="8" id="orC-Gd-rNO"/>
<constraint firstItem="zZ4-Xm-Xca" firstAttribute="width" secondItem="okZ-6Z-SVm" secondAttribute="width" multiplier="8/10" id="owR-gy-XJA"/>
<constraint firstAttribute="bottom" secondItem="5FU-EW-ITI" secondAttribute="bottom" id="tc9-uM-9sG"/>
<constraint firstItem="5FU-EW-ITI" firstAttribute="top" secondItem="okZ-6Z-SVm" secondAttribute="top" id="wsU-Ky-EUd"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="titleLabel" destination="hYf-aH-s8i" id="TCO-Yc-dDI"/>
</connections>
<point key="canvasLocation" x="356.25" y="211.5"/>
</view>
</objects>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import Reusable
*
* That's why it's annotated with the `NibOwnerLoadable` protocol.
*/
final class MyHeaderTableView: UIView, NibOwnerLoadable {
final class MyTableViewHeader: UIView, NibOwnerLoadable {

@IBOutlet private weak var titleLabel: UILabel!
static let height: CGFloat = 55
Expand All @@ -30,6 +30,6 @@ final class MyHeaderTableView: UIView, NibOwnerLoadable {
}

func fillForSection(_ section: Int) {
self.titleLabel.text = "Header Section #\(section)"
self.titleLabel.text = "Header Section #\(section) (manual load)"
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MyHeaderTableView" customModule="ReusableDemo" customModuleProvider="target">
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MyTableViewHeader" customModule="ReusableDemo_iOS" customModuleProvider="target">
<connections>
<outlet property="titleLabel" destination="hYf-aH-s8i" id="WZ1-Km-cgw"/>
</connections>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Reusable
* Which in fact is just a convenience typealias that combines
* `NibLoadable` & `Reusable` protocols.
*/
final class MyXIBInfoCell: UITableViewCell, NibReusable {
final class MyXIBInfoCell: UITableViewCell, NibReusable, AutoRegistering {

@IBOutlet private weak var titleLabel: UILabel!
private var info: String = "<Info?>"
Expand Down
46 changes: 31 additions & 15 deletions Example/ReusableDemo iOS/TableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,44 @@ final class TableViewController: UITableViewController {

tableView.register(cellType: MySimpleColorCell.self)
tableView.register(cellType: MyXIBTextCell.self)
tableView.register(cellType: MyXIBInfoCell.self)

/* Since MyXIBInfoCell is marked as conforming to AutoRegistering,
there's no need to register this type ahead of time */
// tableView.register(cellType: MyXIBInfoCell.self)

/* No need to register this one, the UIStoryboard already auto-register its cells */
// tableView.registerReusableCell(MyStoryBoardIndexPathCell)
// tableView.registerReusableCell(MyStoryBoardIndexPathCell)
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return MyHeaderTableView.height
switch section {
case 0:
return MyTableViewHeader.height
default:
return MyAutoRegisterTableViewHeader.height
}
}

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let frame = CGRect(
x: 0,
y: 0,
width: tableView.bounds.size.width,
height: self.tableView(tableView, heightForHeaderInSection: section)
)
// See the overridden `MyHeaderTableView.init(frame:)` initializer, which
// automatically loads the view content from its nib using loadNibContent()
let view = MyHeaderTableView(frame: frame)

view.fillForSection(section)
return view
switch section {
case 0:
let frame = CGRect(
x: 0,
y: 0,
width: tableView.bounds.size.width,
height: self.tableView(tableView, heightForHeaderInSection: section)
)
// See the overridden `MyHeaderTableView.init(frame:)` initializer, which
// automatically loads the view content from its nib using loadNibContent()
let view = MyTableViewHeader(frame: frame)
view.fillForSection(section)
return view
default:
// This header class is set to auto-register itself
let view: MyAutoRegisterTableViewHeader = tableView.dequeueReusableHeaderFooterView()
view.fillForSection(section)
return view
}
}

override func numberOfSections(in tableView: UITableView) -> Int {
Expand All @@ -61,6 +76,7 @@ final class TableViewController: UITableViewController {
textCell.fill("{section \(indexPath.section), row \(indexPath.row)}")
return textCell
case 2:
// Note that auto-register is enabled here
let infoCell = tableView.dequeueReusableCell(for: indexPath) as MyXIBInfoCell
infoCell.fill("InfoCell #\(indexPath.row)", info: "Info #\(indexPath.row)", details: "Details #\(indexPath.row)")
return infoCell
Expand Down
24 changes: 16 additions & 8 deletions Example/ReusableDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
37E3FC761E55CDD8000A7436 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 37E3FC751E55CDD8000A7436 /* Assets.xcassets */; };
37E3FC7E1E55D056000A7436 /* MyCustomWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E3FC7D1E55D056000A7436 /* MyCustomWidget.swift */; };
37E3FC801E55D08C000A7436 /* MyCustomWidget.xib in Resources */ = {isa = PBXBuildFile; fileRef = 37E3FC7F1E55D08C000A7436 /* MyCustomWidget.xib */; };
3BC2191F1CFC259F003BE78C /* MyHeaderTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC2191D1CFC259F003BE78C /* MyHeaderTableView.swift */; };
3BC219201CFC259F003BE78C /* MyHeaderTableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BC2191E1CFC259F003BE78C /* MyHeaderTableView.xib */; };
3BC2191F1CFC259F003BE78C /* MyTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC2191D1CFC259F003BE78C /* MyTableViewHeader.swift */; };
3BC219201CFC259F003BE78C /* MyTableViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BC2191E1CFC259F003BE78C /* MyTableViewHeader.xib */; };
47EE563C1D66155100AD3E4D /* MyCustomWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47EE563B1D66155100AD3E4D /* MyCustomWidget.swift */; };
47EE563E1D66155D00AD3E4D /* MyCustomWidget.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47EE563D1D66155D00AD3E4D /* MyCustomWidget.xib */; };
73E86102FC28DA0699B75437 /* Pods_ReusableDemo_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2606E6E047118D562E70F0CF /* Pods_ReusableDemo_tvOS.framework */; };
B818B06E2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B818B06C2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.swift */; };
B818B06F2119BE8700D0BF37 /* MyAutoRegisterTableViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = B818B06D2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.xib */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -78,12 +80,14 @@
37E3FC771E55CDD8000A7436 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
37E3FC7D1E55D056000A7436 /* MyCustomWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyCustomWidget.swift; sourceTree = "<group>"; };
37E3FC7F1E55D08C000A7436 /* MyCustomWidget.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyCustomWidget.xib; sourceTree = "<group>"; };
3BC2191D1CFC259F003BE78C /* MyHeaderTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyHeaderTableView.swift; sourceTree = "<group>"; };
3BC2191E1CFC259F003BE78C /* MyHeaderTableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyHeaderTableView.xib; sourceTree = "<group>"; };
3BC2191D1CFC259F003BE78C /* MyTableViewHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyTableViewHeader.swift; sourceTree = "<group>"; };
3BC2191E1CFC259F003BE78C /* MyTableViewHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyTableViewHeader.xib; sourceTree = "<group>"; };
47EE563B1D66155100AD3E4D /* MyCustomWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyCustomWidget.swift; sourceTree = "<group>"; };
47EE563D1D66155D00AD3E4D /* MyCustomWidget.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyCustomWidget.xib; sourceTree = "<group>"; };
80A8538E60254C825B7D505B /* Pods-ReusableDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReusableDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReusableDemo/Pods-ReusableDemo.debug.xcconfig"; sourceTree = "<group>"; };
868A47776F0B74DD17857FFE /* Pods_ReusableDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReusableDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B818B06C2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAutoRegisterTableViewHeader.swift; sourceTree = "<group>"; };
B818B06D2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyAutoRegisterTableViewHeader.xib; sourceTree = "<group>"; };
CFC3794861C2D883C20E9AC8 /* Pods-ReusableDemo iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReusableDemo iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS.debug.xcconfig"; sourceTree = "<group>"; };
E7E0B2333D96C0FED6D45DD1 /* Pods-ReusableDemo tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReusableDemo tvOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReusableDemo tvOS/Pods-ReusableDemo tvOS.debug.xcconfig"; sourceTree = "<group>"; };
FB77CDB068583366F960D03D /* Pods-ReusableDemo iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReusableDemo iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReusableDemo iOS/Pods-ReusableDemo iOS.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -171,8 +175,10 @@
09B3461F1C4ED34F00BA041F /* TableView Cells */ = {
isa = PBXGroup;
children = (
3BC2191D1CFC259F003BE78C /* MyHeaderTableView.swift */,
3BC2191E1CFC259F003BE78C /* MyHeaderTableView.xib */,
3BC2191D1CFC259F003BE78C /* MyTableViewHeader.swift */,
3BC2191E1CFC259F003BE78C /* MyTableViewHeader.xib */,
B818B06C2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.swift */,
B818B06D2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.xib */,
09B346201C4ED39700BA041F /* MyXIBTextCell.swift */,
09B346211C4ED39700BA041F /* MyXIBTextCell.xib */,
09B346261C4ED51600BA041F /* MyXIBInfoCell.swift */,
Expand Down Expand Up @@ -347,9 +353,10 @@
47EE563E1D66155D00AD3E4D /* MyCustomWidget.xib in Resources */,
09441AE21D32A0390029B8A6 /* InfoViewController.storyboard in Resources */,
09B346141C4ED26F00BA041F /* Assets.xcassets in Resources */,
B818B06F2119BE8700D0BF37 /* MyAutoRegisterTableViewHeader.xib in Resources */,
09B346251C4ED4CE00BA041F /* [email protected] in Resources */,
09B346121C4ED26F00BA041F /* Main.storyboard in Resources */,
3BC219201CFC259F003BE78C /* MyHeaderTableView.xib in Resources */,
3BC219201CFC259F003BE78C /* MyTableViewHeader.xib in Resources */,
09B346421C4EF71900BA041F /* MyXIBIndexSquaceCell.xib in Resources */,
09B346291C4ED51600BA041F /* MyXIBInfoCell.xib in Resources */,
);
Expand Down Expand Up @@ -496,13 +503,14 @@
09B346411C4EF71900BA041F /* MyXIBIndexSquaceCell.swift in Sources */,
09B346341C4EDC7D00BA041F /* MyStoryBoardIndexPathCell.swift in Sources */,
09B346221C4ED39700BA041F /* MyXIBTextCell.swift in Sources */,
B818B06E2119BCB100D0BF37 /* MyAutoRegisterTableViewHeader.swift in Sources */,
47EE563C1D66155100AD3E4D /* MyCustomWidget.swift in Sources */,
09B3463C1C4EF46100BA041F /* MyStoryboardTextSquareCell.swift in Sources */,
09B3463E1C4EF4A400BA041F /* CollectionViewController.swift in Sources */,
09B3460F1C4ED26F00BA041F /* TableViewController.swift in Sources */,
09441AE41D32A0700029B8A6 /* InfoDetailViewController.swift in Sources */,
09B3460D1C4ED26F00BA041F /* AppDelegate.swift in Sources */,
3BC2191F1CFC259F003BE78C /* MyHeaderTableView.swift in Sources */,
3BC2191F1CFC259F003BE78C /* MyTableViewHeader.swift in Sources */,
09441AE61D32A07D0029B8A6 /* InfoViewController.swift in Sources */,
09B346281C4ED51600BA041F /* MyXIBInfoCell.swift in Sources */,
09B346441C4EF8B700BA041F /* CollectionHeaderView.swift in Sources */,
Expand Down
Loading