mirror of
https://github.com/ReactiveX/RxSwift.git
synced 2024-10-04 22:17:41 +03:00
Adds UITests.
This commit is contained in:
parent
c9742e51b6
commit
b68fc4260e
@ -92,7 +92,7 @@ extension Reactive where Base: NSObject {
|
||||
#endif
|
||||
|
||||
// Dealloc
|
||||
extension Reactive where Base: NSObject {
|
||||
extension Reactive where Base: AnyObject {
|
||||
|
||||
/**
|
||||
Observable sequence of object deallocated events.
|
||||
@ -211,7 +211,7 @@ let deallocSelector = NSSelectorFromString("dealloc")
|
||||
let rxDeallocatingSelector = RX_selector(deallocSelector)
|
||||
let rxDeallocatingSelectorReference = RX_reference_from_selector(rxDeallocatingSelector)
|
||||
|
||||
extension Reactive where Base: NSObject {
|
||||
extension Reactive where Base: AnyObject {
|
||||
func synchronized<T>( _ action: () -> T) -> T {
|
||||
objc_sync_enter(self.base)
|
||||
let result = action()
|
||||
@ -220,7 +220,7 @@ extension Reactive where Base: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
extension Reactive where Base: NSObject {
|
||||
extension Reactive where Base: AnyObject {
|
||||
/**
|
||||
Helper to make sure that `Observable` returned from `createCachedObservable` is only created once.
|
||||
This is important because there is only one `target` and `action` properties on `NSControl` or `UIBarButtonItem`.
|
||||
|
@ -63,7 +63,7 @@ extension Reactive where Base: UIControl {
|
||||
You might be wondering why the ugly `as!` casts etc, well, for some reason if
|
||||
Swift compiler knows C is UIControl type and optimizations are turned on, it will crash.
|
||||
*/
|
||||
static func value<C: AnyObject, T: Equatable>(_ control: C, getter: @escaping (C) -> T, setter: @escaping (C, T) -> Void) -> ControlProperty<T> {
|
||||
static func value<C: NSObject, T: Equatable>(_ control: C, getter: @escaping (C) -> T, setter: @escaping (C, T) -> Void) -> ControlProperty<T> {
|
||||
let source: Observable<T> = Observable.create { [weak weakControl = control] observer in
|
||||
guard let control = weakControl else {
|
||||
observer.on(.completed)
|
||||
@ -80,7 +80,7 @@ extension Reactive where Base: UIControl {
|
||||
|
||||
return Disposables.create(with: controlTarget.dispose)
|
||||
}
|
||||
.takeUntil((control as! NSObject).rx.deallocated)
|
||||
.takeUntil((control as NSObject).rx.deallocated)
|
||||
|
||||
let bindingObserver = UIBindingObserver(UIElement: control, binding: setter)
|
||||
|
||||
|
@ -18,6 +18,10 @@ extension Reactive where Base: UISwitch {
|
||||
|
||||
/**
|
||||
Reactive wrapper for `on` property.
|
||||
|
||||
**⚠️Unlike other controls, Apple is reusing instances of UISwitch or a there is a leak,
|
||||
so underlying observable sequence won't complete when nothing holds a strong reference
|
||||
to UISwitch.⚠️**
|
||||
*/
|
||||
public var value: ControlProperty<Bool> {
|
||||
return Reactive<UIControl>.value(
|
||||
|
266
RxExample/RxExample-iOSUITests/FlowTests.swift
Normal file
266
RxExample/RxExample-iOSUITests/FlowTests.swift
Normal file
@ -0,0 +1,266 @@
|
||||
//
|
||||
// FlowTests.swift
|
||||
// RxExample-iOSUITests
|
||||
//
|
||||
// Created by Krunoslav Zaher on 8/20/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class FlowTests : XCTestCase {
|
||||
var app: XCUIApplication!
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
continueAfterFailure = false
|
||||
self.app = XCUIApplication()
|
||||
self.app.launchEnvironment = ["isUITest": ""]
|
||||
self.app.launch()
|
||||
}
|
||||
}
|
||||
|
||||
extension FlowTests {
|
||||
func testAll() {
|
||||
for test in [
|
||||
_testSearchWikipedia,
|
||||
_testMasterDetail,
|
||||
_testGitHubSignUp,
|
||||
_testAnimatedPartialUpdates,
|
||||
_testVisitEveryScreen
|
||||
] {
|
||||
test()
|
||||
wait(interval: 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
func _testGitHubSignUp() {
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[3].tap()
|
||||
let username = app.textFields.allElementsBoundByIndex[0]
|
||||
let password = app.secureTextFields.allElementsBoundByIndex[0]
|
||||
let repeatedPassword = app.secureTextFields.allElementsBoundByIndex[1]
|
||||
|
||||
username.tap()
|
||||
username.typeText("rxrevolution")
|
||||
|
||||
password.tap()
|
||||
password.typeText("mypassword")
|
||||
|
||||
repeatedPassword.tap()
|
||||
repeatedPassword.typeText("mypassword")
|
||||
|
||||
app.windows.allElementsBoundByIndex[0].coordinate(withNormalizedOffset: CGVector(dx: 14.50, dy: 80.00)).tap()
|
||||
app.buttons["Sign up"].tap()
|
||||
|
||||
waitForElementToAppear(app.alerts.element(boundBy: 0))
|
||||
|
||||
app.alerts.allElementsBoundByIndex[0].buttons.allElementsBoundByIndex[0].tap()
|
||||
|
||||
goBack()
|
||||
}
|
||||
|
||||
func _testSearchWikipedia() {
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[12].tap()
|
||||
|
||||
let searchField = app.tables.children(matching: .searchField).element
|
||||
|
||||
searchField.tap()
|
||||
|
||||
searchField.typeSlow(text: "banana")
|
||||
searchField.clearText()
|
||||
searchField.typeSlow(text: "Yosemite")
|
||||
searchField.clearText()
|
||||
|
||||
goBack()
|
||||
}
|
||||
|
||||
func _testMasterDetail() {
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[10].tap()
|
||||
waitForElementToAppear(app.tables.allElementsBoundByIndex[0].cells.element(boundBy: 5))
|
||||
|
||||
let editButton = app.navigationBars.buttons["Edit"]
|
||||
|
||||
editButton.tap()
|
||||
|
||||
func reorderButtonForIndex(_ index: Int) -> XCUIElement {
|
||||
return app.tables.cells.allElementsBoundByIndex[index].buttons.allElementsBoundByIndex.filter { element in
|
||||
element.label.hasPrefix("Reorder ")
|
||||
}.first!
|
||||
}
|
||||
|
||||
reorderButtonForIndex(5).press(forDuration: 1.5, thenDragTo: reorderButtonForIndex(2))
|
||||
|
||||
reorderButtonForIndex(7).press(forDuration: 1.5, thenDragTo: reorderButtonForIndex(4))
|
||||
|
||||
reorderButtonForIndex(1).press(forDuration: 1.5, thenDragTo: reorderButtonForIndex(3))
|
||||
|
||||
let doneButton = app.navigationBars.buttons["Done"]
|
||||
doneButton.tap()
|
||||
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[6].tap()
|
||||
|
||||
goBack()
|
||||
goBack()
|
||||
}
|
||||
|
||||
func _testAnimatedPartialUpdates() {
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[11].tap()
|
||||
|
||||
let randomize = app.navigationBars.buttons["Randomize"]
|
||||
waitForElementToAppear(randomize)
|
||||
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
randomize.tap()
|
||||
|
||||
goBack()
|
||||
}
|
||||
|
||||
func _testVisitEveryScreen() {
|
||||
let count = Int(app.tables.allElementsBoundByIndex[0].cells.count)
|
||||
XCTAssertTrue(count > 0)
|
||||
|
||||
for i in 0 ..< count {
|
||||
app.tables.allElementsBoundByIndex[0].cells.allElementsBoundByIndex[i].tap()
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FlowTests {
|
||||
func testControls() {
|
||||
for test in [
|
||||
_testDatePicker,
|
||||
_testBarButtonItemTap,
|
||||
_testButtonTap,
|
||||
_testSegmentedControl,
|
||||
//_testUISwitch,
|
||||
_testUITextField,
|
||||
_testUITextView,
|
||||
_testSlider
|
||||
] {
|
||||
goToControlsView()
|
||||
test()
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
|
||||
func goToControlsView() {
|
||||
let tableView = app.tables.element(boundBy: 0)
|
||||
|
||||
waitForElementToAppear(tableView)
|
||||
|
||||
tableView.cells.allElementsBoundByIndex[5].tap()
|
||||
}
|
||||
|
||||
func checkDebugLabelValue(_ expected: String) {
|
||||
let textValue = app.staticTexts["debugLabel"].value as? String
|
||||
XCTAssertEqual(textValue, expected)
|
||||
}
|
||||
|
||||
func _testDatePicker() {
|
||||
let picker = app.datePickers.allElementsBoundByIndex[0]
|
||||
picker.pickerWheels.element(boundBy: 0).coordinate(withNormalizedOffset: CGVector(dx: 0.49, dy: 0.65)).tap()
|
||||
picker.pickerWheels.element(boundBy: 1).coordinate(withNormalizedOffset: CGVector(dx: 0.35, dy: 0.64)).tap()
|
||||
picker.pickerWheels.element(boundBy: 2).coordinate(withNormalizedOffset: CGVector(dx: 0.46, dy: 0.64)).tap()
|
||||
|
||||
wait(interval: 1.0)
|
||||
|
||||
checkDebugLabelValue("UIDatePicker date 1970-01-02 01:01:00 +0000")
|
||||
}
|
||||
|
||||
func _testBarButtonItemTap() {
|
||||
app.navigationBars.buttons["TapMe"].tap()
|
||||
checkDebugLabelValue("UIBarButtonItem Tapped")
|
||||
}
|
||||
|
||||
func _testButtonTap() {
|
||||
app.scrollViews.buttons["TapMe"].tap()
|
||||
checkDebugLabelValue("UIButton Tapped")
|
||||
}
|
||||
|
||||
func _testSegmentedControl() {
|
||||
let segmentedControl = app.scrollViews.segmentedControls.allElementsBoundByIndex[0]
|
||||
segmentedControl.buttons["Second"].tap()
|
||||
checkDebugLabelValue("UISegmentedControl value 1")
|
||||
segmentedControl.buttons["First"].tap()
|
||||
checkDebugLabelValue("UISegmentedControl value 0")
|
||||
}
|
||||
|
||||
func _testUISwitch() {
|
||||
let switchControl = app.switches.allElementsBoundByIndex[0]
|
||||
switchControl.tap()
|
||||
checkDebugLabelValue("UISwitch value false")
|
||||
switchControl.tap()
|
||||
checkDebugLabelValue("UISwitch value true")
|
||||
}
|
||||
|
||||
func _testUITextField() {
|
||||
let textField = app.textFields.allElementsBoundByIndex[0]
|
||||
textField.tap()
|
||||
textField.typeText("f")
|
||||
checkDebugLabelValue("UITextField text f")
|
||||
}
|
||||
|
||||
func _testUITextView() {
|
||||
let textView = app.textViews.allElementsBoundByIndex[0]
|
||||
textView.tap()
|
||||
textView.typeText("f")
|
||||
checkDebugLabelValue("UITextView text f")
|
||||
}
|
||||
|
||||
func _testSlider() {
|
||||
let slider = app.sliders.allElementsBoundByIndex[0]
|
||||
slider.adjust(toNormalizedSliderPosition: 0)
|
||||
checkDebugLabelValue("UISlider value 0.0")
|
||||
}
|
||||
}
|
||||
|
||||
extension FlowTests {
|
||||
|
||||
func goBack() {
|
||||
let navigationBar = app.navigationBars.allElementsBoundByIndex[0]
|
||||
navigationBar.coordinate(withNormalizedOffset: .zero).withOffset(CGVector(dx: 20, dy: 30)).tap()
|
||||
wait(interval: 1.5)
|
||||
}
|
||||
|
||||
func waitForElementToAppear(_ element: XCUIElement, timeout: TimeInterval = 2, file: String = #file, line: UInt = #line) {
|
||||
let existsPredicate = NSPredicate(format: "exists == true")
|
||||
|
||||
expectation(for: existsPredicate,
|
||||
evaluatedWith: element,
|
||||
handler: nil)
|
||||
|
||||
waitForExpectations(timeout: timeout) { (error) -> Void in
|
||||
if (error != nil) {
|
||||
let message = "Failed to find \(element) after \(timeout) seconds."
|
||||
self.recordFailure(withDescription: message, inFile: file, atLine: line, expected: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func wait(interval: TimeInterval) {
|
||||
RunLoop.current.run(until: Date().addingTimeInterval(interval))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension XCUIElement {
|
||||
func clearText() {
|
||||
let backspace = "\u{8}"
|
||||
let backspaces = Array(((self.value as? String) ?? "").characters).map { _ in backspace }
|
||||
self.typeText(backspaces.joined(separator: ""))
|
||||
}
|
||||
|
||||
func typeSlow(text: String) {
|
||||
for i in text.characters {
|
||||
self.typeText(String(i))
|
||||
}
|
||||
}
|
||||
}
|
22
RxExample/RxExample-iOSUITests/Info.plist
Normal file
22
RxExample/RxExample-iOSUITests/Info.plist
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
@ -96,6 +96,7 @@
|
||||
C88BB8C71B07E6C90064D411 /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E3C2321B03605B0010338D /* Dependencies.swift */; };
|
||||
C88BB8CA1B07E6C90064D411 /* WikipediaAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86E2F3B1AE5A0CA00C31024 /* WikipediaAPI.swift */; };
|
||||
C88BB8CC1B07E6C90064D411 /* WikipediaPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86E2F3C1AE5A0CA00C31024 /* WikipediaPage.swift */; };
|
||||
C88C2B2A1D67EC5200B01A98 /* FlowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C88C2B291D67EC5200B01A98 /* FlowTests.swift */; };
|
||||
C890A65D1AEC084100AFF7E6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C890A65C1AEC084100AFF7E6 /* ViewController.swift */; };
|
||||
C89634081B95BE50002AE38C /* RxBlocking.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C8A468EF1B8A8BD000BF917B /* RxBlocking.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
C89634091B95BE50002AE38C /* RxCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C8A468ED1B8A8BCC00BF917B /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@ -125,6 +126,8 @@
|
||||
C8C46DAA1B47F7110020D71E /* WikipediaSearchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C46DA51B47F7110020D71E /* WikipediaSearchCell.swift */; };
|
||||
C8C46DAB1B47F7110020D71E /* WikipediaSearchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8C46DA61B47F7110020D71E /* WikipediaSearchCell.xib */; };
|
||||
C8C46DAC1B47F7110020D71E /* WikipediaSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C46DA71B47F7110020D71E /* WikipediaSearchViewController.swift */; };
|
||||
C8CDF0AB1D67F8FC00C18F99 /* UIApplication+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8CDF0AA1D67F8FC00C18F99 /* UIApplication+Extensions.swift */; };
|
||||
C8CDF0C11D688DF700C18F99 /* UITableView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8CDF0C01D688DF700C18F99 /* UITableView+Extensions.swift */; };
|
||||
C8D132151C42B54B00B59FFF /* UIImagePickerController+RxCreate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132141C42B54B00B59FFF /* UIImagePickerController+RxCreate.swift */; };
|
||||
C8DF92CD1B0B2F84009BCF9A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DF92C81B0B2F84009BCF9A /* AppDelegate.swift */; };
|
||||
C8DF92DF1B0B328B009BCF9A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DF92DE1B0B328B009BCF9A /* AppDelegate.swift */; };
|
||||
@ -288,6 +291,13 @@
|
||||
remoteGlobalIDString = C88FA53F1C25C4CC00CCFEA4;
|
||||
remoteInfo = "RxTests-watchOS";
|
||||
};
|
||||
C88C2B2C1D67EC5200B01A98 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = C83366D51AD0293800C668A7 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = C83366DC1AD0293800C668A7;
|
||||
remoteInfo = "RxExample-iOS";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -386,6 +396,9 @@
|
||||
C86E2F3C1AE5A0CA00C31024 /* WikipediaPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = WikipediaPage.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C86E2F3D1AE5A0CA00C31024 /* WikipediaSearchResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = WikipediaSearchResult.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
C88BB8DC1B07E6C90064D411 /* RxExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C88C2B271D67EC5200B01A98 /* RxExample-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RxExample-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C88C2B291D67EC5200B01A98 /* FlowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowTests.swift; sourceTree = "<group>"; };
|
||||
C88C2B2B1D67EC5200B01A98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C890A65C1AEC084100AFF7E6 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
C8984CCE1C36BC3E001E4272 /* NumberCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberCell.swift; sourceTree = "<group>"; };
|
||||
C8984CCF1C36BC3E001E4272 /* NumberSectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSectionView.swift; sourceTree = "<group>"; };
|
||||
@ -410,6 +423,8 @@
|
||||
C8C46DA51B47F7110020D71E /* WikipediaSearchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaSearchCell.swift; sourceTree = "<group>"; };
|
||||
C8C46DA61B47F7110020D71E /* WikipediaSearchCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WikipediaSearchCell.xib; sourceTree = "<group>"; };
|
||||
C8C46DA71B47F7110020D71E /* WikipediaSearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WikipediaSearchViewController.swift; sourceTree = "<group>"; };
|
||||
C8CDF0AA1D67F8FC00C18F99 /* UIApplication+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8CDF0C01D688DF700C18F99 /* UITableView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+Extensions.swift"; sourceTree = "<group>"; };
|
||||
C8D132141C42B54B00B59FFF /* UIImagePickerController+RxCreate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImagePickerController+RxCreate.swift"; sourceTree = "<group>"; };
|
||||
C8DF92C81B0B2F84009BCF9A /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C8DF92DE1B0B328B009BCF9A /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
@ -456,6 +471,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C88C2B241D67EC5200B01A98 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -548,6 +570,7 @@
|
||||
C8B290A51C959D2900E923D0 /* RxDataSources */,
|
||||
C83366DF1AD0293800C668A7 /* RxExample */,
|
||||
C849EF621C3190360048AC4A /* RxExample-iOSTests */,
|
||||
C88C2B281D67EC5200B01A98 /* RxExample-iOSUITests */,
|
||||
C83366DE1AD0293800C668A7 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@ -558,6 +581,7 @@
|
||||
C83366DD1AD0293800C668A7 /* RxExample-iOS.app */,
|
||||
C88BB8DC1B07E6C90064D411 /* RxExample.app */,
|
||||
C849EF611C3190360048AC4A /* RxExample-iOSTests.xctest */,
|
||||
C88C2B271D67EC5200B01A98 /* RxExample-iOSUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -773,6 +797,15 @@
|
||||
path = GitHubSignup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C88C2B281D67EC5200B01A98 /* RxExample-iOSUITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C88C2B291D67EC5200B01A98 /* FlowTests.swift */,
|
||||
C88C2B2B1D67EC5200B01A98 /* Info.plist */,
|
||||
);
|
||||
path = "RxExample-iOSUITests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8984CCD1C36BC3E001E4272 /* TableViewPartialUpdates */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -835,6 +868,8 @@
|
||||
C8DF92E11B0B32DA009BCF9A /* Main.storyboard */,
|
||||
C8DF92E21B0B32DA009BCF9A /* RootViewController.swift */,
|
||||
C8DF92C81B0B2F84009BCF9A /* AppDelegate.swift */,
|
||||
C8CDF0AA1D67F8FC00C18F99 /* UIApplication+Extensions.swift */,
|
||||
C8CDF0C01D688DF700C18F99 /* UITableView+Extensions.swift */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
@ -905,13 +940,31 @@
|
||||
productReference = C88BB8DC1B07E6C90064D411 /* RxExample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
C88C2B261D67EC5200B01A98 /* RxExample-iOSUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C88C2B2E1D67EC5200B01A98 /* Build configuration list for PBXNativeTarget "RxExample-iOSUITests" */;
|
||||
buildPhases = (
|
||||
C88C2B231D67EC5200B01A98 /* Sources */,
|
||||
C88C2B241D67EC5200B01A98 /* Frameworks */,
|
||||
C88C2B251D67EC5200B01A98 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
C88C2B2D1D67EC5200B01A98 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "RxExample-iOSUITests";
|
||||
productName = "RxExample-iOSUITests";
|
||||
productReference = C88C2B271D67EC5200B01A98 /* RxExample-iOSUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C83366D51AD0293800C668A7 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastSwiftUpdateCheck = 0800;
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = "Krunoslav Zaher";
|
||||
TargetAttributes = {
|
||||
@ -922,12 +975,19 @@
|
||||
};
|
||||
C849EF601C3190360048AC4A = {
|
||||
CreatedOnToolsVersion = 7.2;
|
||||
DevelopmentTeam = 783T66X79Y;
|
||||
LastSwiftMigration = 0800;
|
||||
TestTargetID = C83366DC1AD0293800C668A7;
|
||||
};
|
||||
C88BB8B91B07E6C90064D411 = {
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
C88C2B261D67EC5200B01A98 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
DevelopmentTeam = 783T66X79Y;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = C83366DC1AD0293800C668A7;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C83366D81AD0293800C668A7 /* Build configuration list for PBXProject "RxExample" */;
|
||||
@ -952,6 +1012,7 @@
|
||||
C83366DC1AD0293800C668A7 /* RxExample-iOS */,
|
||||
C88BB8B91B07E6C90064D411 /* RxExample-OSX */,
|
||||
C849EF601C3190360048AC4A /* RxExample-iOSTests */,
|
||||
C88C2B261D67EC5200B01A98 /* RxExample-iOSUITests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -1128,6 +1189,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C88C2B251D67EC5200B01A98 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -1172,6 +1240,7 @@
|
||||
C84780061D29DE8C0074454A /* RxTableViewSectionedReloadDataSource.swift in Sources */,
|
||||
C843A0901C1CE39900CBA4BD /* GitHubSearchRepositoriesViewController.swift in Sources */,
|
||||
C803973A1BD3E17D009D8B26 /* ActivityIndicator.swift in Sources */,
|
||||
C8CDF0C11D688DF700C18F99 /* UITableView+Extensions.swift in Sources */,
|
||||
C849EF821C3193B10048AC4A /* GithubSignupViewModel1.swift in Sources */,
|
||||
C864BADD1C3332F10083833C /* TableViewWithEditingCommandsViewController.swift in Sources */,
|
||||
C8F8C4A01C277F5A0047640B /* Operation.swift in Sources */,
|
||||
@ -1193,6 +1262,7 @@
|
||||
C8984CD51C36BC3E001E4272 /* PartialUpdatesViewController.swift in Sources */,
|
||||
8479BC721C3BDAD400FB8B54 /* ImagePickerController.swift in Sources */,
|
||||
C8477FFF1D29DE8C0074454A /* SectionModelType.swift in Sources */,
|
||||
C8CDF0AB1D67F8FC00C18F99 /* UIApplication+Extensions.swift in Sources */,
|
||||
C864BAE11C3332F10083833C /* User.swift in Sources */,
|
||||
0744CDED1C4DB78600720FD2 /* GeolocationViewController.swift in Sources */,
|
||||
C83367231AD029AE00C668A7 /* Example.swift in Sources */,
|
||||
@ -1264,6 +1334,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
C88C2B231D67EC5200B01A98 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C88C2B2A1D67EC5200B01A98 /* FlowTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
@ -1272,6 +1350,11 @@
|
||||
target = C83366DC1AD0293800C668A7 /* RxExample-iOS */;
|
||||
targetProxy = C849EF661C3190360048AC4A /* PBXContainerItemProxy */;
|
||||
};
|
||||
C88C2B2D1D67EC5200B01A98 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = C83366DC1AD0293800C668A7 /* RxExample-iOS */;
|
||||
targetProxy = C88C2B2C1D67EC5200B01A98 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@ -1407,6 +1490,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "RxExample-iOSTests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
@ -1423,6 +1507,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "RxExample-iOSTests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
@ -1440,6 +1525,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = "RxExample-iOSTests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
@ -1477,6 +1563,69 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C88C2B2F1D67EC5200B01A98 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
INFOPLIST_FILE = "RxExample-iOSUITests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "rx.RxExample-iOSUITests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_TARGET_NAME = "RxExample-iOS";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C88C2B301D67EC5200B01A98 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
INFOPLIST_FILE = "RxExample-iOSUITests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "rx.RxExample-iOSUITests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_TARGET_NAME = "RxExample-iOS";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C88C2B311D67EC5200B01A98 /* Release-Tests */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 783T66X79Y;
|
||||
INFOPLIST_FILE = "RxExample-iOSUITests/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "rx.RxExample-iOSUITests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_TARGET_NAME = "RxExample-iOS";
|
||||
};
|
||||
name = "Release-Tests";
|
||||
};
|
||||
C8DF92ED1B0B3DFA009BCF9A /* Release-Tests */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -1594,6 +1743,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C88C2B2E1D67EC5200B01A98 /* Build configuration list for PBXNativeTarget "RxExample-iOSUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C88C2B2F1D67EC5200B01A98 /* Debug */,
|
||||
C88C2B301D67EC5200B01A98 /* Release */,
|
||||
C88C2B311D67EC5200B01A98 /* Release-Tests */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = C83366D51AD0293800C668A7 /* Project object */;
|
||||
|
@ -38,6 +38,16 @@
|
||||
ReferencedContainer = "container:RxExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C88C2B261D67EC5200B01A98"
|
||||
BuildableName = "RxExample-iOSUITests.xctest"
|
||||
BlueprintName = "RxExample-iOSUITests"
|
||||
ReferencedContainer = "container:RxExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
@ -52,7 +62,7 @@
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
|
@ -83,9 +83,13 @@ class APIWrappersViewController: ViewController {
|
||||
|
||||
// MARK: UISwitch
|
||||
|
||||
/*
|
||||
// also test two way binding
|
||||
let switchValue = Variable(true)
|
||||
_ = switcher.rx.value <-> switchValue
|
||||
/***⚠️Unlike other controls, Apple is reusing instances of UISwitch or a there is a leak,
|
||||
so underlying observable sequence won't complete when nothing holds a strong reference
|
||||
to UISwitch.⚠️***/
|
||||
(switcher.rx.value <-> switchValue).addDisposableTo(disposeBag)
|
||||
|
||||
switchValue.asObservable()
|
||||
.subscribe(onNext: { [weak self] x in
|
||||
@ -98,7 +102,7 @@ class APIWrappersViewController: ViewController {
|
||||
switcher.rx.value
|
||||
.bindTo(activityIndicator.rx.animating)
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
*/
|
||||
|
||||
// MARK: UIButton
|
||||
|
||||
|
@ -54,14 +54,16 @@ class PartialUpdatesViewController : ViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
self.navigationItem.rightBarButtonItem?.accessibilityLabel = "Randomize"
|
||||
|
||||
// For UICollectionView, if another animation starts before previous one is finished, it will sometimes crash :(
|
||||
// It's not deterministic (because Randomizer generates deterministic updates), and if you click fast
|
||||
// It sometimes will and sometimes wont crash, depending on tapping speed.
|
||||
// I guess you can maybe try some tricks with timeout, hard to tell :( That's on Apple side.
|
||||
|
||||
if generateCustomSize {
|
||||
let nSections = 10
|
||||
let nItems = 100
|
||||
let nSections = UIApplication.isInUITest ? 10 : 10
|
||||
let nItems = UIApplication.isInUITest ? 20 : 100
|
||||
|
||||
var sections = [AnimatableSectionModel<String, Int>]()
|
||||
|
||||
|
@ -23,7 +23,7 @@ class DetailViewController: ViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
imageView.makeRoundedCorners(5)
|
||||
imageView.makeRoundedCorners(40)
|
||||
|
||||
let url = URL(string: user.imageURL)!
|
||||
let request = URLRequest(url: url)
|
||||
|
@ -11,10 +11,11 @@ import UIKit
|
||||
extension UIImageView {
|
||||
|
||||
func makeRoundedCorners(_ radius: CGFloat) {
|
||||
self.layer.cornerRadius = self.frame.size.width / 2
|
||||
self.layer.borderColor = UIColor.darkGray.cgColor
|
||||
self.layer.borderWidth = radius
|
||||
self.layer.cornerRadius = radius
|
||||
self.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
|
||||
func makeRoundedCorners() {
|
||||
self.makeRoundedCorners(self.frame.size.width / 2)
|
||||
}
|
||||
}
|
||||
|
@ -13,21 +13,9 @@ import RxCocoa
|
||||
#endif
|
||||
|
||||
class WikipediaSearchViewController: ViewController {
|
||||
@IBOutlet var searchBarContainer: UIView!
|
||||
|
||||
private let searchController = UISearchController(searchResultsController: UITableViewController())
|
||||
|
||||
private var resultsViewController: UITableViewController {
|
||||
return (self.searchController.searchResultsController as? UITableViewController)!
|
||||
}
|
||||
|
||||
private var resultsTableView: UITableView {
|
||||
return self.resultsViewController.tableView!
|
||||
}
|
||||
|
||||
private var searchBar: UISearchBar {
|
||||
return self.searchController.searchBar
|
||||
}
|
||||
@IBOutlet var searchBar: UISearchBar!
|
||||
@IBOutlet var resultsTableView: UITableView!
|
||||
@IBOutlet var emptyView: UIView!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
@ -37,15 +25,8 @@ class WikipediaSearchViewController: ViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let searchBar = self.searchBar
|
||||
let searchBarContainer = self.searchBarContainer
|
||||
|
||||
searchBarContainer?.addSubview(searchBar)
|
||||
searchBar.frame = (searchBarContainer?.bounds)!
|
||||
searchBar.autoresizingMask = .flexibleWidth
|
||||
|
||||
resultsViewController.edgesForExtendedLayout = UIRectEdge()
|
||||
self.edgesForExtendedLayout = .all
|
||||
|
||||
configureTableDataSource()
|
||||
configureKeyboardDismissesOnScroll()
|
||||
@ -57,14 +38,12 @@ class WikipediaSearchViewController: ViewController {
|
||||
resultsTableView.register(UINib(nibName: "WikipediaSearchCell", bundle: nil), forCellReuseIdentifier: "WikipediaSearchCell")
|
||||
|
||||
resultsTableView.rowHeight = 194
|
||||
resultsTableView.hideEmptyCells()
|
||||
|
||||
// This is for clarity only, don't use static dependencies
|
||||
let API = DefaultWikipediaAPI.sharedAPI
|
||||
|
||||
resultsTableView.delegate = nil
|
||||
resultsTableView.dataSource = nil
|
||||
|
||||
searchBar.rx.text
|
||||
let results = searchBar.rx.text
|
||||
.asDriver()
|
||||
.throttle(0.3)
|
||||
.distinctUntilChanged()
|
||||
@ -78,24 +57,27 @@ class WikipediaSearchViewController: ViewController {
|
||||
.map { results in
|
||||
results.map(SearchResultViewModel.init)
|
||||
}
|
||||
|
||||
results
|
||||
.drive(resultsTableView.rx.items(cellIdentifier: "WikipediaSearchCell", cellType: WikipediaSearchCell.self)) { (_, viewModel, cell) in
|
||||
cell.viewModel = viewModel
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
results
|
||||
.map { $0.count != 0 }
|
||||
.drive(self.emptyView.rx.hidden)
|
||||
.addDisposableTo(disposeBag)
|
||||
}
|
||||
|
||||
func configureKeyboardDismissesOnScroll() {
|
||||
let searchBar = self.searchBar
|
||||
let searchController = self.searchController
|
||||
|
||||
resultsTableView.rx.contentOffset
|
||||
.asDriver()
|
||||
.filter { _ -> Bool in
|
||||
return !searchController.isBeingPresented
|
||||
}
|
||||
.drive(onNext: { _ in
|
||||
if searchBar.isFirstResponder {
|
||||
_ = searchBar.resignFirstResponder()
|
||||
if searchBar?.isFirstResponder ?? false {
|
||||
_ = searchBar?.resignFirstResponder()
|
||||
}
|
||||
})
|
||||
.addDisposableTo(disposeBag)
|
||||
|
@ -79,7 +79,7 @@ class ViewController: OSViewController {
|
||||
|
||||
If somebody knows more about why this delay happens, you can make a PR with explanation here.
|
||||
*/
|
||||
let when = DispatchTime.now() + DispatchTimeInterval.milliseconds(20)
|
||||
let when = DispatchTime.now() + DispatchTimeInterval.milliseconds(UIApplication.isInUITest ? 1000 : 10)
|
||||
|
||||
mainQueue.asyncAfter (deadline: when) {
|
||||
|
||||
@ -92,7 +92,7 @@ class ViewController: OSViewController {
|
||||
//
|
||||
// If this crashes when you've been clicking slowly, then it would be interesting to find out why.
|
||||
// ¯\_(ツ)_/¯
|
||||
assert(resourceCount <= numberOfResourcesThatShouldRemain, "Resources weren't cleaned properly")
|
||||
assert(resourceCount <= numberOfResourcesThatShouldRemain, "Resources weren't cleaned properly, \(resourceCount) remaned, \(numberOfResourcesThatShouldRemain) expected")
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -12,6 +12,11 @@ import UIKit
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func applicationDidFinishLaunching(_ application: UIApplication) {
|
||||
if UIApplication.isInUITest {
|
||||
UIView.setAnimationsEnabled(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
15
RxExample/RxExample/iOS/UIApplication+Extensions.swift
Normal file
15
RxExample/RxExample/iOS/UIApplication+Extensions.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// UIApplication+Extensions.swift
|
||||
// RxExample
|
||||
//
|
||||
// Created by Krunoslav Zaher on 8/20/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIApplication {
|
||||
static var isInUITest: Bool {
|
||||
return ProcessInfo.processInfo.environment["isUITest"] != nil;
|
||||
}
|
||||
}
|
15
RxExample/RxExample/iOS/UITableView+Extensions.swift
Normal file
15
RxExample/RxExample/iOS/UITableView+Extensions.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// UITableView+Extensions.swift
|
||||
// RxExample
|
||||
//
|
||||
// Created by Krunoslav Zaher on 8/20/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UITableView {
|
||||
func hideEmptyCells() {
|
||||
self.tableFooterView = UIView(frame: .zero)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user