Skip to content

Commit 0aa4c25

Browse files
committed
ErrorView added
1 parent 49d00d3 commit 0aa4c25

File tree

11 files changed

+264
-26
lines changed

11 files changed

+264
-26
lines changed

Example/LoadingViewController/AppDelegate.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1313

1414
var window: UIWindow?
1515

16-
1716
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
1817
// Override point for customization after application launch.
1918
return true

Example/LoadingViewController/ViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ViewController: LoadingViewController {
1919
delay(3.0) { [weak self] in
2020
self?.setVisibleScreen(.Loading)
2121
self?.delay(3, closure: { [weak self] in
22-
self?.setVisibleScreen(.Content)
22+
self?.setVisibleScreen(.Failure)
2323
})
2424
}
2525
}

Example/Pods/Pods.xcodeproj/project.pbxproj

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LoadingViewController.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ LoadingViewController is able to switch from ContentView to LoadingView and then
3232

3333
s.source_files = 'LoadingViewController/Classes/**/*'
3434

35-
# s.resource_bundles = {
36-
# 'LoadingViewController' => ['LoadingViewController/Assets/*.png']
37-
# }
35+
s.resource_bundles = {
36+
'LoadingViewController' => ['LoadingViewController/Assets/*']
37+
}
3838

3939
# s.public_header_files = 'Pod/Classes/**/*.h'
4040
# s.frameworks = 'UIKit', 'MapKit'
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// UIView+Nib.swift
3+
// Pods
4+
//
5+
// Created by Sapozhnik Ivan on 29.06.16.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
// http://stackoverflow.com/a/26326006/1320184
12+
13+
public extension UIView {
14+
15+
public class func fromNib(nibNameOrNil: String? = nil) -> Self {
16+
return fromNib(nibNameOrNil, type: self)
17+
}
18+
19+
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T {
20+
let v: T? = fromNib(nibNameOrNil, type: T.self)
21+
return v!
22+
}
23+
24+
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T? {
25+
var view: T?
26+
let name: String
27+
if let nibName = nibNameOrNil {
28+
name = nibName
29+
} else {
30+
// Most nibs are demangled by practice, if not, just declare string explicitly
31+
name = nibName
32+
}
33+
34+
let allBundles = NSBundle.allBundles()[1]
35+
36+
let mainBundle = NSBundle.mainBundle()
37+
// let bundlePath = NSBundle.mainBundle().pathForResource("LoadingViewController", ofType: "bundle")
38+
// let oneMoreBundle = NSBundle(path: bundlePath!)
39+
40+
let classBundle = NSBundle(forClass: object_getClass(self))
41+
42+
let nibViews = mainBundle.loadNibNamed(name, owner: nil, options: nil)
43+
for v in nibViews {
44+
if let tog = v as? T {
45+
view = tog
46+
}
47+
}
48+
return view
49+
}
50+
51+
public class var nibName: String {
52+
let name = "\(self)".componentsSeparatedByString(".").first ?? ""
53+
return name
54+
}
55+
public class var nib: UINib? {
56+
if let _ = NSBundle.mainBundle().pathForResource(nibName, ofType: "nib") {
57+
return UINib(nibName: nibName, bundle: nil)
58+
} else {
59+
return nil
60+
}
61+
}
62+
}

LoadingViewController/Classes/LoadingViewController.swift

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import UIKit
1010

11+
// This extension should be used for testing purposes
12+
1113
extension UIViewController {
1214
public func delay(delay:Double, closure:()->()) {
1315
dispatch_after(
@@ -17,23 +19,6 @@ extension UIViewController {
1719
),
1820
dispatch_get_main_queue(), closure)
1921
}
20-
21-
func synced(lock: AnyObject, closure: () -> ()) {
22-
objc_sync_enter(lock)
23-
closure()
24-
objc_sync_exit(lock)
25-
}
26-
}
27-
28-
enum LoadingViewStyle {
29-
case Indicator
30-
case Stroke
31-
case Multicolor
32-
case Custom
33-
}
34-
35-
enum ErrorViewStyle {
36-
case Simple
3722
}
3823

3924
public enum ContentType: Int {
@@ -53,6 +38,7 @@ let animationDuration: NSTimeInterval = 0.3;
5338

5439

5540
typealias AnimationDict = Dictionary<String, AnyObject>
41+
public typealias ActionHandler = () -> ()
5642

5743
public class LoadingViewController: UIViewController {
5844

@@ -82,12 +68,12 @@ public class LoadingViewController: UIViewController {
8268
}
8369

8470
func defaultErrorView() -> UIView {
85-
//TODO: create default view for Error
86-
return UIView()
71+
let view = ErrorView.viewWithStyle(errorViewStyle(), actionHandler: nil)
72+
return view
8773
}
8874

8975
func defaultLoadingView() -> UIView {
90-
let view = LoadingView.viewWithStyle(.Multicolor)
76+
let view = LoadingView.viewWithStyle(loadingViewStyle())
9177

9278
//TODO: add title, background image, etc.
9379
view.title = "Loading"
@@ -140,7 +126,8 @@ public class LoadingViewController: UIViewController {
140126
}
141127
}
142128

143-
public func setVisibleScreen(contentType: ContentType) {
129+
// TODO: add ActionHandler support to handle 'Retry' tap on ErrorViews
130+
public func setVisibleScreen(contentType: ContentType, actionHandler:ActionHandler? = nil) {
144131
if visibleContentType != contentType {
145132
visibleContentType = contentType
146133
setActiveView(viewForScreen(visibleContentType))
403 KB
Loading
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// ErrorView.swift
3+
// Pods
4+
//
5+
// Created by Sapozhnik Ivan on 29.06.16.
6+
//
7+
//
8+
9+
import UIKit
10+
11+
enum ErrorViewStyle {
12+
case Simple
13+
}
14+
15+
class ErrorView: UIView {
16+
17+
var action: ActionHandler?
18+
19+
var title: String? {
20+
didSet {
21+
didSetTitle()
22+
}
23+
}
24+
var message: String? {
25+
didSet {
26+
didSetMessage()
27+
}
28+
}
29+
var image: UIImage? {
30+
didSet {
31+
didSetImage()
32+
}
33+
}
34+
35+
static func viewWithStyle(style: ErrorViewStyle, actionHandler:ActionHandler?) -> ErrorView {
36+
37+
switch style {
38+
case .Simple:
39+
let errorView = SimpleErrorView.fromNib()
40+
errorView.action = actionHandler
41+
return errorView
42+
default: break
43+
}
44+
45+
}
46+
47+
func didSetTitle() {}
48+
func didSetMessage() {}
49+
func didSetImage() {}
50+
func didSetAction() {}
51+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// SimpleErrorView.swift
3+
// Pods
4+
//
5+
// Created by Sapozhnik Ivan on 29.06.16.
6+
//
7+
//
8+
9+
import UIKit
10+
11+
class SimpleErrorView: ErrorView {
12+
13+
14+
15+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
3+
<dependencies>
4+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
5+
</dependencies>
6+
<objects>
7+
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
8+
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
9+
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="SimpleErrorView" customModule="LoadingViewController">
10+
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
11+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
12+
<subviews>
13+
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QG0-nT-4fb">
14+
<rect key="frame" x="50" y="0.0" width="220" height="480"/>
15+
<subviews>
16+
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Oops! Something went wrong." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="220" translatesAutoresizingMaskIntoConstraints="NO" id="gfN-0e-n0e">
17+
<rect key="frame" x="0.0" y="333" width="220" height="38"/>
18+
<color key="backgroundColor" red="0.40784313729999999" green="0.41568627450000001" blue="0.50980392159999999" alpha="0.0" colorSpace="calibratedRGB"/>
19+
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="16"/>
20+
<color key="textColor" red="0.22352941179999999" green="0.22352941179999999" blue="0.22352941179999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
21+
<nil key="highlightedColor"/>
22+
</label>
23+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bFX-MB-E6F" userLabel="message label">
24+
<rect key="frame" x="0.0" y="391" width="220" height="19"/>
25+
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="16"/>
26+
<color key="textColor" red="0.40000000000000002" green="0.41176470590000003" blue="0.43921568630000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
27+
<nil key="highlightedColor"/>
28+
</label>
29+
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sNq-j4-dgH">
30+
<rect key="frame" x="20" y="430" width="180" height="30"/>
31+
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="15"/>
32+
<state key="normal" title="Reload in a moment">
33+
<color key="titleColor" red="0.13725490200000001" green="0.66666666669999997" blue="0.88235294119999996" alpha="1" colorSpace="calibratedRGB"/>
34+
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
35+
</state>
36+
<state key="highlighted">
37+
<color key="titleColor" red="0.24313725489999999" green="0.42352941179999998" blue="0.5450980392" alpha="1" colorSpace="calibratedRGB"/>
38+
</state>
39+
</button>
40+
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" image="doc_fail.png" translatesAutoresizingMaskIntoConstraints="NO" id="pyy-8x-tJd">
41+
<rect key="frame" x="-210" y="64" width="640" height="240"/>
42+
</imageView>
43+
</subviews>
44+
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
45+
<constraints>
46+
<constraint firstItem="sNq-j4-dgH" firstAttribute="top" secondItem="bFX-MB-E6F" secondAttribute="bottom" constant="20" id="2Yf-JI-XFc"/>
47+
<constraint firstItem="bFX-MB-E6F" firstAttribute="centerX" secondItem="gfN-0e-n0e" secondAttribute="centerX" id="Lu7-vy-bCW"/>
48+
<constraint firstItem="gfN-0e-n0e" firstAttribute="leading" secondItem="QG0-nT-4fb" secondAttribute="leading" id="Pib-Qe-VLS"/>
49+
<constraint firstItem="sNq-j4-dgH" firstAttribute="leading" secondItem="QG0-nT-4fb" secondAttribute="leading" constant="20" id="Q6v-T4-fmc"/>
50+
<constraint firstItem="bFX-MB-E6F" firstAttribute="leading" secondItem="QG0-nT-4fb" secondAttribute="leading" id="csy-4V-xWP"/>
51+
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="sNq-j4-dgH" secondAttribute="bottom" constant="20" id="gGg-K0-r2x"/>
52+
<constraint firstAttribute="trailing" secondItem="bFX-MB-E6F" secondAttribute="trailing" id="hcI-kf-Ee8"/>
53+
<constraint firstItem="bFX-MB-E6F" firstAttribute="top" secondItem="gfN-0e-n0e" secondAttribute="bottom" constant="20" id="hfC-Mb-5u0"/>
54+
<constraint firstAttribute="trailing" secondItem="gfN-0e-n0e" secondAttribute="trailing" id="j6M-lK-8jA"/>
55+
<constraint firstAttribute="centerX" secondItem="pyy-8x-tJd" secondAttribute="centerX" id="jJv-kB-mXm"/>
56+
<constraint firstAttribute="centerX" secondItem="sNq-j4-dgH" secondAttribute="centerX" id="mYE-bY-lX2"/>
57+
<constraint firstItem="pyy-8x-tJd" firstAttribute="top" secondItem="QG0-nT-4fb" secondAttribute="top" constant="64" id="rgd-t9-uOt"/>
58+
<constraint firstAttribute="trailing" secondItem="sNq-j4-dgH" secondAttribute="trailing" constant="20" id="wl6-lh-GTK"/>
59+
<constraint firstItem="gfN-0e-n0e" firstAttribute="top" secondItem="pyy-8x-tJd" secondAttribute="bottom" constant="29" id="zDY-xi-xe7"/>
60+
</constraints>
61+
</view>
62+
</subviews>
63+
<color key="backgroundColor" red="0.98039215686274506" green="0.98039215686274506" blue="0.98039215686274506" alpha="1" colorSpace="calibratedRGB"/>
64+
<constraints>
65+
<constraint firstItem="QG0-nT-4fb" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="0GS-3x-pkV"/>
66+
<constraint firstAttribute="trailing" secondItem="QG0-nT-4fb" secondAttribute="trailing" constant="50" id="DCX-W0-eWD"/>
67+
<constraint firstAttribute="bottom" secondItem="QG0-nT-4fb" secondAttribute="bottom" id="h3X-sS-UKx"/>
68+
<constraint firstItem="QG0-nT-4fb" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="50" id="jNT-du-umr"/>
69+
</constraints>
70+
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
71+
<point key="canvasLocation" x="220" y="437"/>
72+
</view>
73+
</objects>
74+
<resources>
75+
<image name="doc_fail.png" width="640" height="530"/>
76+
</resources>
77+
</document>

0 commit comments

Comments
 (0)