Skip to content

Commit fb9cbad

Browse files
author
Michael Long
committed
Add Dismissible presentation option
1 parent d7fe3ec commit fb9cbad

File tree

5 files changed

+66
-8
lines changed

5 files changed

+66
-8
lines changed

RxSwiftWidgets.xcodeproj/project.pbxproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
4C21217D22EA698900C5D6FB /* MainMenuLabelWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C21217C22EA698900C5D6FB /* MainMenuLabelWidget.swift */; };
4242
4C31A0CD22EF7BCC004A3464 /* FeaturesWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C31A0CC22EF7AEF004A3464 /* FeaturesWidget.swift */; };
4343
4C31A0CF22EF7CE9004A3464 /* DemoPositioningWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C31A0CE22EF7CE9004A3464 /* DemoPositioningWidget.swift */; };
44+
4C3B618D2327D7F5001253D0 /* UIColor+Widgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B618B2327D773001253D0 /* UIColor+Widgets.swift */; };
4445
4C3EFF1522FC7A2F007F909A /* LoginFormWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EFF1422FC7A2F007F909A /* LoginFormWidget.swift */; };
4546
4C44C2C522EA4E3600E3CBDD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C44C2C422EA4E3600E3CBDD /* AppDelegate.swift */; };
4647
4C44C2E022EA508F00E3CBDD /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "RxSwift::RxCocoa::Product" /* RxCocoa.framework */; };
@@ -574,6 +575,7 @@
574575
4C21217C22EA698900C5D6FB /* MainMenuLabelWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainMenuLabelWidget.swift; sourceTree = "<group>"; };
575576
4C31A0CC22EF7AEF004A3464 /* FeaturesWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturesWidget.swift; sourceTree = "<group>"; };
576577
4C31A0CE22EF7CE9004A3464 /* DemoPositioningWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoPositioningWidget.swift; sourceTree = "<group>"; };
578+
4C3B618B2327D773001253D0 /* UIColor+Widgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Widgets.swift"; sourceTree = "<group>"; };
577579
4C3EFF1422FC7A2F007F909A /* LoginFormWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginFormWidget.swift; sourceTree = "<group>"; };
578580
4C44C2C222EA4E3600E3CBDD /* RxSwiftWidgetsDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxSwiftWidgetsDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
579581
4C44C2C422EA4E3600E3CBDD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ../AppDelegate.swift; sourceTree = "<group>"; };
@@ -1357,6 +1359,7 @@
13571359
OBJ_19 /* Extensions */ = {
13581360
isa = PBXGroup;
13591361
children = (
1362+
4C3B618B2327D773001253D0 /* UIColor+Widgets.swift */,
13601363
OBJ_20 /* UIView+Widgets.swift */,
13611364
OBJ_21 /* UIWidgetHostController.swift */,
13621365
);
@@ -2234,6 +2237,7 @@
22342237
4C8F4E34231470C5001997C8 /* WidgetTheme.swift in Sources */,
22352238
OBJ_665 /* WidgetModifyUIViewCustom.swift in Sources */,
22362239
4CD6916C2306EFBC00C6FB9C /* TableWidget.swift in Sources */,
2240+
4C3B618D2327D7F5001253D0 /* UIColor+Widgets.swift in Sources */,
22372241
OBJ_666 /* WidgetModifyUIViewGestures.swift in Sources */,
22382242
4CE49AB922FCD7080030CD9D /* WidgetModifyUIControl.swift in Sources */,
22392243
OBJ_667 /* WidgetModifyUIViewLayer.swift in Sources */,
@@ -2437,7 +2441,7 @@
24372441
GCC_WARN_UNUSED_VARIABLE = YES;
24382442
INFOPLIST_FILE = "$(SRCROOT)/RxSwiftWidgetsDemo/Info.plist";
24392443
INFOPLIST_PREFIX_HEADER = "$(SRCROOT)/RxSwiftWidgetsDemo/Info.plist";
2440-
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
2444+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
24412445
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
24422446
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
24432447
MTL_FAST_MATH = YES;
@@ -2497,7 +2501,7 @@
24972501
GCC_WARN_UNUSED_VARIABLE = YES;
24982502
INFOPLIST_FILE = "$(SRCROOT)/RxSwiftWidgetsDemo/Info.plist";
24992503
INFOPLIST_PREFIX_HEADER = "$(SRCROOT)/RxSwiftWidgetsDemo/Info.plist";
2500-
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
2504+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
25012505
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
25022506
MTL_ENABLE_DEBUG_INFO = NO;
25032507
MTL_FAST_MATH = YES;

RxSwiftWidgetsDemo/Application/Features/FeaturesWidget.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct FeaturesWidget: WidgetView {
3131
}),
3232

3333
MainMenuItemWidget(text: "Dismissible", onTap: { context in
34-
context.navigator?.push(widget: DemoDismissibleWidget(), onDismiss: { (value: String) in
34+
context.navigator?.present(widget: DemoDismissibleWidget(), onDismiss: { (value: String) in
3535
print(value)
3636
})
3737
}),

RxSwiftWidgetsDemo/Shared/ErrorMessageWidget.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct ErrorMessageWidget: WidgetView {
2727
return
2828
}
2929
let baseAnimation = { (_ value: String) in
30-
label.text = value
30+
label.text = value.isEmpty ? nil : value
3131
label.isHidden = value.isEmpty
3232
label.superview?.layoutIfNeeded()
3333
}

Sources/RxSwiftWidgets/Core/WidgetDismissible.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,8 @@ public struct WidgetDismissibleReturn<Value>: WidgetDismissibleType {
2020
}
2121

2222
}
23+
24+
public enum WidgetDismissiblePresentationType {
25+
case presented
26+
case pushed
27+
}

Sources/RxSwiftWidgets/Core/WidgetNavigation.swift

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import UIKit
1010
import RxSwift
1111

12-
12+
/// WidgetNavigator provides access to the current UINavgiationController and navigation stack.
1313
public struct WidgetNavigator {
1414

1515
var context: WidgetContext
@@ -18,54 +18,88 @@ public struct WidgetNavigator {
1818
self.context = context
1919
}
2020

21+
/// Returns the current UINavigation controller for the current context.
2122
public var navigationController: UINavigationController? {
2223
context.viewController?.navigationController
2324
}
2425

2526
// dismissible functionality
2627

28+
/// Pushes the widget onto the navigation stack in a new UIWidgetHostController.
2729
public func push(widget: Widget, animated: Bool = true) {
30+
let context = self.context.set(presentation: .pushed)
2831
let viewController = UIWidgetHostController(widget, with: context)
2932
navigationController?.pushViewController(viewController, animated: animated)
3033
}
3134

35+
/// Pushes the widget onto the navigation stack in a new UIWidgetHostController with a return value handler.
3236
public func push<ReturnType>(widget: Widget, animated: Bool = true, onDismiss handler: @escaping WidgetDismissibleReturnHandler<ReturnType>) {
37+
let context = self.context.set(presentation: .pushed)
3338
let dismissible = WidgetDismissibleReturn<ReturnType>(handler)
3439
let viewController = UIWidgetHostController(widget, with: context, dismissible: dismissible)
3540
navigationController?.pushViewController(viewController, animated: animated)
3641
}
3742

43+
/// Presents a widget on the navigation stack in a new UIWidgetHostController.
44+
public func present(widget: Widget, animated: Bool = true) {
45+
let context = self.context.set(presentation: .presented)
46+
let viewController = UIWidgetHostController(widget, with: context)
47+
navigationController?.present(viewController, animated: animated, completion: nil)
48+
}
49+
50+
/// Presents a widget on the navigation stack in a new UIWidgetHostController with a return value handler.
51+
public func present<ReturnType>(widget: Widget, animated: Bool = true, onDismiss handler: @escaping WidgetDismissibleReturnHandler<ReturnType>) {
52+
let context = self.context.set(presentation: .presented)
53+
let dismissible = WidgetDismissibleReturn<ReturnType>(handler)
54+
let viewController = UIWidgetHostController(widget, with: context, dismissible: dismissible)
55+
navigationController?.present(viewController, animated: animated, completion: nil)
56+
}
57+
58+
/// Pops or dismisses the current view controller, returning a value that will be passed to the onDismiss handler.
3859
public func dismiss<Value>(returning value: Value, animated: Bool = true) {
3960
if let dimissible = context.dismissible as? WidgetDismissibleReturn<Value> {
4061
dimissible.handler(value)
4162
}
4263
dismiss(animated: animated)
4364
}
4465

66+
/// Pops or dismisses the current view controller, dependent upon the presentation state.
4567
public func dismiss(animated: Bool = true) {
46-
guard let viewController = context.viewController else { return }
47-
viewController.navigationController?.popToViewController(viewController, animated: false)
48-
viewController.navigationController?.popViewController(animated: animated)
68+
guard let viewController = context.viewController else {
69+
return
70+
}
71+
switch self.context.presentation {
72+
case .presented:
73+
viewController.dismiss(animated: animated, completion: nil)
74+
case .pushed:
75+
viewController.navigationController?.popToViewController(viewController, animated: false)
76+
viewController.navigationController?.popViewController(animated: animated)
77+
}
4978
}
5079

5180
// standard functionality
5281

82+
/// Pushes a non-widget baseed view controller onto the current navigation stack.
5383
public func pushViewController(_ viewController: UIViewController, animated: Bool = true) {
5484
navigationController?.pushViewController(viewController, animated: animated)
5585
}
5686

87+
/// Pops a view controller from the current navigation stack.
5788
public func popViewController(animated: Bool = true) {
5889
navigationController?.popViewController(animated: animated)
5990
}
6091

92+
/// Pops to the root view controller on the current navigation stack.
6193
public func popToRootViewController(animated: Bool = true) {
6294
navigationController?.popToRootViewController(animated: animated)
6395
}
6496

97+
/// Presents a view controller using the current navigation stack.
6598
public func presentViewController(_ viewController: UIViewController, animated: Bool = true) {
6699
context.viewController?.present(viewController, animated: animated, completion: nil)
67100
}
68101

102+
/// Dismisses a view controller from the current navigation stack.
69103
public func dismissViewController(animated: Bool = true) {
70104
context.viewController?.dismiss(animated: animated, completion: nil)
71105
}
@@ -75,36 +109,51 @@ public struct WidgetNavigator {
75109

76110
extension WidgetContext {
77111

112+
/// Returns the Navigator for the current context.
78113
public var navigator: WidgetNavigator? {
79114
if viewController != nil {
80115
return WidgetNavigator(self)
81116
}
82117
return nil
83118
}
84119

120+
/// Returns the current context with a new RxSwift DisposeBag for subscriptions.
85121
public func new() -> WidgetContext {
86122
var context = self
87123
context.disposeBag = DisposeBag()
88124
return context
89125
}
90126

127+
/// Sets the current view controller to be the passed view controller.
91128
public func set(viewController: UIViewController) -> WidgetContext {
92129
var context = self
93130
context.viewController = viewController
94131
return context
95132
}
96133

134+
/// Returns the current navigation dismissible, if any.
97135
public var dismissible: WidgetDismissibleType? {
98136
return get(WidgetDismissibleType.self)
99137
}
100138

139+
/// Sets the current navigation dismissible.
101140
public func set(dismissible: WidgetDismissibleType?) -> WidgetContext {
102141
if let dismissible = dismissible {
103142
return put(dismissible)
104143
}
105144
return self
106145
}
107146

147+
/// Returns the current navigation presentation type for the current view controller.
148+
public var presentation: WidgetDismissiblePresentationType {
149+
return find(WidgetDismissiblePresentationType.self) ?? .pushed
150+
}
151+
152+
/// Sets the current navigation presentation type for the current view controller.
153+
public func set(presentation: WidgetDismissiblePresentationType) -> WidgetContext {
154+
return put(presentation)
155+
}
156+
108157
}
109158

110159
fileprivate struct UIViewControllerBox {

0 commit comments

Comments
 (0)