From 030c70a55ed3730cc095e0dfca69a28773ddf72b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 24 Jan 2021 19:50:11 +0700 Subject: [PATCH] Move to GitHub Actions --- .github/workflows/main.yml | 15 ++ .swiftlint.yml | 180 +++++++++++++++++++++ .travis.yml | 3 - Defaults.podspec | 1 - Defaults.xcodeproj/project.pbxproj | 30 +++- Sources/Defaults/Observation+Combine.swift | 16 +- Sources/Defaults/Observation.swift | 2 + Tests/DefaultsTests/DefaultsTests.swift | 30 ++-- readme.md | 4 +- 9 files changed, 245 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 .swiftlint.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..a80cc11 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,15 @@ +name: CI +on: + - push + - pull_request +jobs: + test: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - run: swift test + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: norio-nomura/action-swiftlint@3.2.1 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..49fa3fd --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,180 @@ +only_rules: + - anyobject_protocol + - array_init + - block_based_kvo + - class_delegate_protocol + - closing_brace + - closure_end_indentation + - closure_parameter_position + - closure_spacing + - collection_alignment + - colon + - comma + - compiler_protocol_init + - computed_accessors_order + - conditional_returns_on_newline + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - contains_over_range_nil_comparison + - control_statement + - custom_rules + - discarded_notification_center_observer + - discouraged_direct_init + - discouraged_object_literal + - discouraged_optional_collection + - duplicate_enum_cases + - duplicate_imports + - dynamic_inline + - empty_collection_literal + - empty_count + - empty_enum_arguments + - empty_parameters + - empty_parentheses_with_trailing_closure + - empty_string + - empty_xctest_method + - enum_case_associated_values_count + - explicit_init + - fallthrough + - fatal_error_message + - first_where + - flatmap_over_map_reduce + - for_where + - generic_type_name + - ibinspectable_in_extension + - identical_operands + - identifier_name + - implicit_getter + - implicit_return + - inclusive_language + - inert_defer + - is_disjoint + - joined_default_parameter + - last_where + - leading_whitespace + - legacy_cggeometry_functions + - legacy_constant + - legacy_constructor + - legacy_hashing + - legacy_multiple + - legacy_nsgeometry_functions + - legacy_random + - literal_expression_end_indentation + - lower_acl_than_parent + - mark + - modifier_order + - multiline_arguments + - multiline_function_chains + - multiline_literal_brackets + - multiline_parameters + - multiline_parameters_brackets + - nimble_operator + - no_extension_access_modifier + - no_fallthrough_only + - no_space_in_method_call + - notification_center_detachment + - nsobject_prefer_isequal + - number_separator + - opening_brace + - operator_usage_whitespace + - operator_whitespace + - orphaned_doc_comment + - overridden_super_call + - prefer_self_type_over_type_of_self + - prefer_zero_over_explicit_init + - private_action + - private_outlet + - private_unit_test + - prohibited_super_call + - protocol_property_accessors_order + - reduce_boolean + - reduce_into + - redundant_discardable_let + - redundant_nil_coalescing + - redundant_objc_attribute + - redundant_optional_initialization + - redundant_set_access_control + - redundant_string_enum_value + - redundant_type_annotation + - redundant_void_return + - required_enum_case + - return_arrow_whitespace + - shorthand_operator + - sorted_first_last + - statement_position + - static_operator + - strong_iboutlet + - superfluous_disable_command + - switch_case_alignment + - switch_case_on_newline + - syntactic_sugar + - test_case_accessibility + - toggle_bool + - trailing_closure + - trailing_comma + - trailing_newline + - trailing_semicolon + - trailing_whitespace + - unavailable_function + - unneeded_break_in_switch + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + - unused_capture_list + - unused_closure_parameter + - unused_control_flow_label + - unused_enumerated + - unused_optional_binding + - unused_setter_value + - valid_ibinspectable + - vertical_parameter_alignment + - vertical_parameter_alignment_on_call + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - void_return + - weak_delegate + - xct_specific_matcher + - yoda_condition +analyzer_rules: + - unused_declaration + - unused_import +number_separator: + minimum_length: 5 +identifier_name: + max_length: + warning: 100 + error: 100 + min_length: + warning: 2 + error: 2 + validates_start_with_lowercase: false + allowed_symbols: + - '_' + excluded: + - 'x' + - 'y' + - 'a' + - 'b' + - 'x1' + - 'x2' + - 'y1' + - 'y2' +custom_rules: + no_nsrect: + regex: '\bNSRect\b' + match_kinds: typeidentifier + message: 'Use CGRect instead of NSRect' + no_nssize: + regex: '\bNSSize\b' + match_kinds: typeidentifier + message: 'Use CGSize instead of NSSize' + no_nspoint: + regex: '\bNSPoint\b' + match_kinds: typeidentifier + message: 'Use CGPoint instead of NSPoint' + swiftui_state_private: + regex: '@(State|StateObject)\s+var' + message: "SwiftUI @State/@StateObject properties should be private" + final_class: + regex: '^class [a-zA-Z\d]+[^{]+\{' + message: "Classes should be marked as final whenever possible. If you actually need it to be subclassable, just add `// swiftlint:disable:next final_class`." diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3087b64..0000000 --- a/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: swift -osx_image: xcode11.4 -script: xcodebuild test -project Defaults.xcodeproj -scheme Defaults-macOS diff --git a/Defaults.podspec b/Defaults.podspec index 82d8a4f..ddb2b29 100644 --- a/Defaults.podspec +++ b/Defaults.podspec @@ -13,5 +13,4 @@ Pod::Spec.new do |s| s.ios.deployment_target = '10.0' s.tvos.deployment_target = '10.0' s.watchos.deployment_target = '3.0' - s.weak_framework = 'Combine' end diff --git a/Defaults.xcodeproj/project.pbxproj b/Defaults.xcodeproj/project.pbxproj index 966867d..a89b8b6 100644 --- a/Defaults.xcodeproj/project.pbxproj +++ b/Defaults.xcodeproj/project.pbxproj @@ -336,6 +336,7 @@ isa = PBXNativeTarget; buildConfigurationList = 52D6DA201BF000BD002C0205 /* Build configuration list for PBXNativeTarget "Defaults-macOS" */; buildPhases = ( + E3FD0A4B25BDA35F0011D293 /* SwiftLint */, 52D6DA0A1BF000BD002C0205 /* Sources */, 52D6DA0B1BF000BD002C0205 /* Frameworks */, 52D6DA0C1BF000BD002C0205 /* Headers */, @@ -502,6 +503,27 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + E3FD0A4B25BDA35F0011D293 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "swiftlint\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 52D6D9771BEFF229002C0205 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -657,10 +679,6 @@ MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "-weak_framework", - Combine, - ); SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = singlefile; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -717,10 +735,6 @@ IPHONEOS_DEPLOYMENT_TARGET = 12.0; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "-weak_framework", - Combine, - ); SDKROOT = iphoneos; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Sources/Defaults/Observation+Combine.swift b/Sources/Defaults/Observation+Combine.swift index 201c870..c4e6ee9 100644 --- a/Sources/Defaults/Observation+Combine.swift +++ b/Sources/Defaults/Observation+Combine.swift @@ -138,13 +138,15 @@ extension Defaults { let initial = Empty(completeImmediately: false).eraseToAnyPublisher() let combinedPublisher = - keys.map { key in - DefaultsPublisher(suite: key.suite, key: key.name, options: options) - .map { _ in () } - .eraseToAnyPublisher() - }.reduce(initial) { combined, keyPublisher in - combined.merge(with: keyPublisher).eraseToAnyPublisher() - } + keys + .map { key in + DefaultsPublisher(suite: key.suite, key: key.name, options: options) + .map { _ in () } + .eraseToAnyPublisher() + } + .reduce(initial) { combined, keyPublisher in + combined.merge(with: keyPublisher).eraseToAnyPublisher() + } return combinedPublisher } diff --git a/Sources/Defaults/Observation.swift b/Sources/Defaults/Observation.swift index f0ef82a..9a5e470 100644 --- a/Sources/Defaults/Observation.swift +++ b/Sources/Defaults/Observation.swift @@ -206,6 +206,7 @@ extension Defaults { private var lifetimeAssociation: LifetimeAssociation? public func tieToLifetime(of weaklyHeldObject: AnyObject) -> Self { + // swiftlint:disable:next trailing_closure lifetimeAssociation = LifetimeAssociation(of: self, with: weaklyHeldObject, deinitHandler: { [weak self] in self?.invalidate() }) @@ -294,6 +295,7 @@ extension Defaults { } public func tieToLifetime(of weaklyHeldObject: AnyObject) -> Self { + // swiftlint:disable:next trailing_closure lifetimeAssociation = LifetimeAssociation(of: self, with: weaklyHeldObject, deinitHandler: { [weak self] in self?.invalidate() }) diff --git a/Tests/DefaultsTests/DefaultsTests.swift b/Tests/DefaultsTests/DefaultsTests.swift index 9d4d442..ca5009e 100644 --- a/Tests/DefaultsTests/DefaultsTests.swift +++ b/Tests/DefaultsTests/DefaultsTests.swift @@ -57,7 +57,7 @@ final class DefaultsTests: XCTestCase { } override func tearDown() { - super.setUp() + super.tearDown() Defaults.removeAll() } @@ -81,9 +81,9 @@ final class DefaultsTests: XCTestCase { func testKeyRegistersDefault() { let keyName = "registersDefault" - XCTAssertEqual(UserDefaults.standard.bool(forKey: keyName), false) + XCTAssertFalse(UserDefaults.standard.bool(forKey: keyName)) _ = Defaults.Key(keyName, default: true) - XCTAssertEqual(UserDefaults.standard.bool(forKey: keyName), true) + XCTAssertTrue(UserDefaults.standard.bool(forKey: keyName)) // Test that it works with multiple keys with `Defaults`. let keyName2 = "registersDefault2" @@ -174,9 +174,9 @@ final class DefaultsTests: XCTestCase { .collect(2) let cancellable = publisher.sink { tuples in - for (i, expected) in [(false, true), (true, false)].enumerated() { - XCTAssertEqual(expected.0, tuples[i].0) - XCTAssertEqual(expected.1, tuples[i].1) + for (index, expected) in [(false, true), (true, false)].enumerated() { + XCTAssertEqual(expected.0, tuples[index].0) + XCTAssertEqual(expected.1, tuples[index].1) } expect.fulfill() @@ -594,7 +594,7 @@ final class DefaultsTests: XCTestCase { XCTAssert(Defaults[key1]! == 4) expect.fulfill() } else { - usleep(100000) + usleep(100_000) print("--- Release: \(Thread.isMainThread)") } } @@ -616,6 +616,7 @@ final class DefaultsTests: XCTestCase { let observation1 = Defaults.observe(key2, options: []) { _ in XCTFail() } + let observation2 = Defaults.observe(keys: key1, key2, options: []) { Defaults.withoutPropagation { Defaults[key2] = true @@ -750,14 +751,14 @@ final class DefaultsTests: XCTestCase { Defaults[key1] = newString1 Defaults[key2] = newString2 Defaults.reset(key1) - XCTAssertEqual(Defaults[key1], nil) + XCTAssertNil(Defaults[key1]) XCTAssertEqual(Defaults[key2], newString2) if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, iOSApplicationExtension 11.0, macOSApplicationExtension 10.13, tvOSApplicationExtension 11.0, watchOSApplicationExtension 4.0, *) { let key3 = Defaults.NSSecureCodingOptionalKey("optionalKey3") Defaults[key3] = ExamplePersistentHistory(value: newString3) Defaults.reset(key3) - XCTAssertEqual(Defaults[key3], nil) + XCTAssertNil(Defaults[key3]) } } @@ -772,8 +773,8 @@ final class DefaultsTests: XCTestCase { Defaults[key2] = newFixture2 Defaults[key3] = newFixture3 Defaults.reset(key1, key2) - XCTAssertEqual(Defaults[key1], nil) - XCTAssertEqual(Defaults[key2], nil) + XCTAssertNil(Defaults[key1]) + XCTAssertNil(Defaults[key2]) XCTAssertEqual(Defaults[key3], newFixture3) } @@ -785,7 +786,8 @@ final class DefaultsTests: XCTestCase { observation = Defaults.observe(key, options: []) { _ in observation.invalidate() expect.fulfill() - }.tieToLifetime(of: self) + } + .tieToLifetime(of: self) Defaults[key] = true @@ -798,14 +800,14 @@ final class DefaultsTests: XCTestCase { weak var observation: Defaults.Observation? = Defaults.observe(key, options: []) { _ in }.tieToLifetime(of: self) observation!.removeLifetimeTie() - for i in 1...10 { + for index in 1...10 { if observation == nil { break } sleep(1) - if i == 10 { + if index == 10 { XCTFail() } } diff --git a/readme.md b/readme.md index 1523ef8..2394c4a 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# Defaults [![Build Status](https://travis-ci.org/sindresorhus/Defaults.svg?branch=master)](https://travis-ci.org/sindresorhus/Defaults) +# Defaults > Swifty and modern [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) @@ -33,8 +33,6 @@ For a real-world example, see my [Plash app](https://github.com/sindresorhus/Pla Add `https://github.com/sindresorhus/Defaults` in the [“Swift Package Manager” tab in Xcode](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app). -You also need to set the build setting “Other Linker Flags” to `-weak_framework Combine` to work around [this Xcode bug](https://github.com/feedback-assistant/reports/issues/44). - #### Carthage ```