70 Commits

Author SHA1 Message Date
Matt Rubin 4ff4757744 Merge pull request #30 from mattrubin/modernize
Modernize for Xcode 16 and Swift 6
2024-12-10 17:02:55 -05:00
Matt Rubin 465027697e Clean up Xcode CI config
- This project no longer uses submodules.
- `xcpretty` 0.4.0 does not support the output of the new Swift Testing framework
2024-12-09 23:50:14 -05:00
Matt Rubin 3476694148 [CI] Build and test with Xcode on macOS 2024-12-09 23:40:43 -05:00
Matt Rubin ff08c0b97a Tweak triggers for CI tests 2024-12-09 23:25:36 -05:00
Matt Rubin 3fcfc60c6b Update copyright date and README 2024-12-09 23:16:31 -05:00
Matt Rubin 574ed9a8ce Update .gitignore
https://github.com/github/gitignore/blob/1c3dda043afe2b8191e5009a1048c38487b4dd36/Swift.gitignore
2024-12-09 23:03:25 -05:00
Matt Rubin 244201c9e5 Delete Hound config
SwiftLint is now run via GitHub Actions, with a newer version of SwiftLint and with the analyzer as well as the linter.
2024-12-09 22:52:52 -05:00
Matt Rubin 13a1507b14 Add a swiftlint GitHub Actions workflow 2024-12-09 22:40:26 -05:00
Matt Rubin 86cf27a3f3 Convert tests to Swift Testing 2024-12-08 23:38:05 -05:00
Matt Rubin d641dfb1ae Add CI tests of SPM on Linux 2024-12-08 23:03:31 -05:00
Matt Rubin fb7f422b98 Drop Carthage support
Now that there is no longer an `xcodeproj`, there is no shared scheme for Carthage to build from.
2024-12-08 22:38:19 -05:00
Matt Rubin 39b78b413d Delete unused Info.plist files 2024-12-08 22:29:34 -05:00
Matt Rubin c8241d8cf1 Delete unused xcconfigs dependency 2024-12-08 22:27:38 -05:00
Matt Rubin 168a29deec Run CI tests on watchOS, tvOS, and visionOS
- The watchOS destination can now be used for testing, not just for building.
- Logic for getting device and runtime IDs was updated to handle devices and runtimes where the name is not easily converted to an identifier.
- The visionOS jobs only test on 1.x, because installing the 2.x runtimes via `xcodes` would report success, but the installed runtime would not appear in the available runtimes list.
2024-12-08 22:24:18 -05:00
Matt Rubin 44bde6592e Delete Identifier.xcodeproj 2024-12-08 17:52:04 -05:00
Matt Rubin f7846bd77b Drop CocoaPods support 2024-12-08 16:34:28 -05:00
Matt Rubin fc37a5408e Delete Travis CI config and README badge 2024-12-08 16:28:51 -05:00
Matt Rubin b2199d69be Add workflows for CI on GitHub Actions 2024-12-08 15:23:53 -05:00
Matt Rubin db2db2aa5d Bump deployment targets to the minimum simulators available in Xcode 16
https://developer.apple.com/support/xcode/#minimum-requirements
2024-12-08 14:38:40 -05:00
Matt Rubin 025ac3c6af Bump Swift package tools and platform versions and fix warnings 2024-12-08 14:30:49 -05:00
Matt Rubin 6a45caa46e Migrate to Swift 6 and add Sendable conformance 2024-12-08 14:29:38 -05:00
Matt Rubin e73a038640 Upgrade SwiftLint and update configuration 2024-12-08 12:37:41 -05:00
Matt Rubin 75a786f59e Accept some suggestions from Xcode project upgrade check 2024-12-08 11:47:11 -05:00
Matt Rubin 7863325aae Update xcconfigs dependency 2024-12-08 11:40:14 -05:00
Matt Rubin a4f1969cb7 Update Xcode project format version 2024-12-08 11:33:03 -05:00
Matt Rubin 525acc3a0c Bump OS deployment targets to the minimum supported by Xcode 16.1
https://developer.apple.com/support/xcode/#minimum-requirements
2024-12-08 11:32:37 -05:00
Matt Rubin 3741bd8265 Merge pull request #29 from mattrubin/raw-representable
Add `RawRepresentable` conformance
2020-10-17 18:51:33 -04:00
Matt Rubin 62384b2a6d Update Linux test manifest 2020-10-17 17:58:55 -04:00
Matt Rubin 19576cf76b Add conformance to RawRepresentable
Instead of re-exposing the internal UUID as a second `rawValue` property, this change renames the stored property and the initializer parameter to match the requirements of `RawRepresentable`.
2020-10-17 17:55:19 -04:00
Matt Rubin d56e172218 Merge pull request #28 from mattrubin/swiftlint
Update SwiftLint configuration
2020-10-17 17:55:07 -04:00
Matt Rubin 448a56d39e [Travis] Test SPM builds on Linux with Swift 5.1 2020-10-17 17:25:07 -04:00
Matt Rubin 8d4ffd8286 [Travis] Use Xcode 11, which has the required Swift 5.1 support 2020-10-17 17:25:07 -04:00
Matt Rubin f7787e07e6 [Lint] Don't ignore function declarations when checking line length 2020-10-17 17:24:33 -04:00
Matt Rubin e9f7d26662 [Lint] Use implicit returns where possible 2020-10-17 17:24:33 -04:00
Matt Rubin ca53446049 [Lint] Wrap both arguments of a line-wrapped function call 2020-10-17 17:24:33 -04:00
Matt Rubin 64cbaf1abf [Lint] Disallow force-unwrapping outside of tests 2020-10-17 17:24:33 -04:00
Matt Rubin dcf67216a3 [Lint] Opt in to several new SwiftLint rules 2020-10-17 17:24:33 -04:00
Matt Rubin 48b517b3f6 [Lint] Replace obsolete unused_private_declaration rule
https://github.com/realm/SwiftLint/releases/tag/0.34.0
2020-10-17 17:24:33 -04:00
Matt Rubin 8dff13e165 Merge pull request #27 from mattrubin/modernize
Update for Xcode 12 and remove Nimble dependency
2020-10-17 17:08:41 -04:00
Matt Rubin 282e6c007d [Travis] Fix build script to not reference the deleted xcode workspace 2020-10-17 16:50:10 -04:00
Matt Rubin 93734fca88 Update .gitignore to exclude Xcode's generated package workspace 2020-10-17 15:36:18 -04:00
Matt Rubin 164abc7277 Apply Xcode 12's recommended changes 2020-10-17 15:31:08 -04:00
Matt Rubin fd1e013b90 Delete Identifier.xcworkspace
It is no longer needed since the project has no linked dependencies.
2020-10-17 15:28:12 -04:00
Matt Rubin aa9ae26905 Refactor IdentifierTests to not require Nimble 2020-10-17 15:12:30 -04:00
Matt Rubin ffc793fe9a Merge pull request #25 from mattrubin/readme
README updates
2019-04-30 17:18:04 -04:00
Matt Rubin c29f9f7880 Link the package managers README badge to the installation instructions 2019-04-30 15:49:52 -04:00
Matt Rubin dc745cdba6 Add a missing full stop to a sentence in the README 2019-04-30 15:46:23 -04:00
Matt Rubin 03609ce6c5 Release Identifier 1.1.0 2019-04-28 23:38:36 -04:00
Matt Rubin 2367635a26 Merge pull request #23 from mattrubin/version-number
Bump the version number to 1.1.0
2019-04-28 23:13:06 -04:00
Matt Rubin 1ad2eda81e Bump the version number to 1.1.0 2019-04-28 22:50:47 -04:00
Matt Rubin 06265eacbe Merge pull request #22 from mattrubin/string-convertible
Add conformance to LosslessStringConvertible and CustomDebugStringConvertible
2019-04-28 22:38:07 -04:00
Matt Rubin 193cfda81b Add documentation comments to the string conversion methods 2019-04-28 21:05:56 -04:00
Matt Rubin 8a98345904 Add tests for LosslessStringConvertible conformance 2019-04-28 21:01:30 -04:00
Matt Rubin be47d08f35 Add conformance to LosslessStringConvertible 2019-04-28 20:52:08 -04:00
Matt Rubin f38f7744d5 Add a debugDescription test 2019-04-28 20:28:38 -04:00
Matt Rubin 69da13b577 Add conformance to CustomDebugStringConvertible 2019-04-28 20:21:47 -04:00
Matt Rubin f15450916b Merge pull request #21 from mattrubin/swiftlint-build-phase
Add a SwiftLint build phase
2019-04-28 00:53:25 -04:00
Matt Rubin 0a8e7b1e17 Add a SwiftLint build phase in a dedicated aggregate target
This setup allows the project to be linted on every build during development, because the lint target is included in the Identifier scheme's build list, but the linter will not be run on build if the framework is being built as a dependency of another project with its own scheme.
2019-04-27 23:36:45 -04:00
Matt Rubin e59fe9d421 Merge pull request #20 from mattrubin/xcconfigs
Upgrade xcconfigs
2019-04-06 00:02:10 -04:00
Matt Rubin 8654fd7dac Delete project build settings already present in the xcconfigs 2019-04-05 23:32:34 -04:00
Matt Rubin c1da9e7986 Upgrade xcconfigs 2019-04-05 23:26:36 -04:00
Matt Rubin 8205e964eb Identifier 1.0.0 2019-04-03 23:30:21 -04:00
Matt Rubin f2f271cd6a Bump the version number to 1.0 2019-04-03 18:23:09 -04:00
Matt Rubin 01e22dcf0b Merge pull request #18 from mattrubin/installation-instructions
Add installation instructions to the README
2019-04-03 16:15:15 -04:00
Matt Rubin a823fcd07f Add installation instructions to the README 2019-04-03 13:09:39 -04:00
Matt Rubin 666cb96f09 Merge pull request #17 from mattrubin/carthage-on-ci
Add a Carthage CI job
2019-04-03 12:25:23 -04:00
Matt Rubin c820d12476 Don't manually specify swift version for SPM builds on Travis
Until the project (maybe, eventually) supports building with multiple Swift versions, it's better to test that SPM is automatically using the correct Swift version as defined in the package manifest.
2019-04-03 11:33:55 -04:00
Matt Rubin 70264c5c07 Rename Carthage and CocoaPods Travis jobs for clarity 2019-04-03 11:31:59 -04:00
Matt Rubin d0f50d72af Rename Travis jobs to clarify build tool usage 2019-04-03 11:30:21 -04:00
Matt Rubin f2f16435d3 Add a carthage build --archive job to the Travis config 2019-04-03 11:16:17 -04:00
30 changed files with 473 additions and 739 deletions
@@ -0,0 +1,48 @@
name: "Prepare simulator"
description: "Creates and boots a custom simulator"
inputs:
runtime:
description: "Runtime name"
required: true
device:
description: "Device name"
required: true
outputs:
destination-id:
description: "Destination simulator ID"
value: ${{ steps.simulator.outputs.destination-id }}
runs:
using: composite
steps:
- name: "Install runtime"
shell: bash
run: |
RUNTIME="${{ inputs.runtime }}"
if xcrun simctl list | grep "$RUNTIME"
then
echo "$RUNTIME is already installed.";
else
echo "::group::Available runtimes:"
xcodes runtimes
echo "::endgroup::"
sudo xcodes runtimes install "$RUNTIME" --keep-archive;
fi
- name: "Create and boot simulator"
id: simulator
shell: bash
run: |
RUNTIME="${{ inputs.runtime }}"
DEVICE="${{ inputs.device }}"
DEVICE_ID=$(xcrun simctl list devicetypes -j | jq -r ".devicetypes.[] | select(.name==\"$DEVICE\").identifier")
echo $DEVICE_ID
if [ $(echo $DEVICE_ID | wc -l) != 1 ] || [ "$DEVICE_ID" = "" ]; then echo "Invalid Device ID"; exit 1; fi
RUNTIME_ID=$(xcrun simctl list runtimes -j | jq -r ".runtimes.[] | select(.name==\"$RUNTIME\").identifier")
echo $RUNTIME_ID
if [ $(echo $RUNTIME_ID | wc -l) != 1 ] || [ "$RUNTIME_ID" = "" ]; then echo "Invalid Runtime ID"; exit 1; fi
DESTINATION_ID=$(xcrun simctl create "Custom: $DEVICE, $RUNTIME" $DEVICE_ID $RUNTIME_ID)
xcrun simctl boot $DESTINATION_ID
echo "destination-id=$(echo $DESTINATION_ID)" >> $GITHUB_OUTPUT
+25
View File
@@ -0,0 +1,25 @@
name: "Select Xcode version"
description: "Selects the specified version of Xcode"
inputs:
version:
description: "Version number"
required: true
runs:
using: composite
steps:
- run: |
echo "::group::Selecting Xcode ${{ inputs.version }}…"
sudo xcode-select -s /Applications/Xcode_${{ inputs.version }}.app
xcode-select -p
echo "::endgroup::"
shell: bash
- run: |
echo "::group::xcodebuild -version -sdk"
xcodebuild -version -sdk
echo "::endgroup::"
shell: bash
- run: |
echo "::group::xcrun simctl list"
xcrun simctl list
echo "::endgroup::"
shell: bash
+40
View File
@@ -0,0 +1,40 @@
name: SPM
on:
pull_request:
push:
branches: [develop, release]
jobs:
macOS:
name: "macOS, Xcode ${{ matrix.xcode }}"
runs-on: macOS-14
strategy:
fail-fast: false
matrix:
xcode:
- "16.1"
steps:
- uses: actions/checkout@v4
- name: "Select Xcode ${{ matrix.xcode }}"
uses: ./.github/actions/xcode-select
with:
version: ${{ matrix.xcode }}
- run: swift --version
- run: swift build --build-tests -Xswiftc -warnings-as-errors
- run: swift test
Linux:
name: Linux, Swift ${{ matrix.swift }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
swift:
- "6.0"
container:
image: swift:${{ matrix.swift }}
steps:
- uses: actions/checkout@v4
- run: swift --version
- run: swift build --build-tests -Xswiftc -warnings-as-errors
- run: swift test
+26
View File
@@ -0,0 +1,26 @@
name: SwiftLint
on:
pull_request:
workflow_dispatch:
jobs:
lint:
name: "Lint"
runs-on: ubuntu-latest
container:
image: ghcr.io/realm/swiftlint:latest
steps:
- uses: actions/checkout@v4
- name: "Lint"
run: swiftlint lint --strict --reporter github-actions-logging
analyze:
name: "Analyze"
runs-on: macOS-latest
steps:
- uses: actions/checkout@v4
- run: sudo xcodes select 16.1
- run: brew install swiftlint
- run: |
xcodebuild -scheme Identifier -destination "name=My Mac" > xcodebuild.log
swiftlint analyze --strict --reporter github-actions-logging --compiler-log-path xcodebuild.log
+87
View File
@@ -0,0 +1,87 @@
name: Xcode
on:
pull_request:
push:
branches: [develop, release]
jobs:
simulator:
name: "Xcode ${{ matrix.env.xcode }}, ${{ matrix.env.runtime }}, ${{ matrix.env.device }}"
runs-on: macOS-14
strategy:
matrix:
env:
- xcode: 16.1
runtime: "iOS 18.1"
device: "iPhone 16 Plus"
- xcode: 16.1
runtime: "iOS 17.0"
device: "iPhone Xs"
- xcode: 16.1
runtime: "watchOS 11.1"
device: "Apple Watch Series 10 (46mm)"
- xcode: 16.1
runtime: "watchOS 10.0"
device: "Apple Watch Series 4 (40mm)"
- xcode: 16.1
runtime: "tvOS 18.1"
device: "Apple TV 4K (3rd generation)"
- xcode: 16.1
runtime: "tvOS 17.0"
device: "Apple TV"
- xcode: 16.1
runtime: "visionOS 1.2"
device: "Apple Vision Pro"
- xcode: 16.1
runtime: "visionOS 1.0"
device: "Apple Vision Pro"
steps:
- uses: actions/checkout@v4
- name: "Select Xcode ${{ matrix.env.xcode }}"
uses: ./.github/actions/xcode-select
with:
version: ${{ matrix.env.xcode }}
- name: "Cache downloaded simulator runtimes"
uses: actions/cache@v4
with:
path: ~/Downloads/*.dmg
key: Xcode ${{ matrix.env.xcode }}+${{ matrix.env.runtime }}
- name: "Prepare simulator"
id: prepare-simulator
uses: ./.github/actions/prepare-simulator
with:
runtime: ${{ matrix.env.runtime }}
device: ${{ matrix.env.device }}
- name: "Build and test"
run: xcodebuild test -scheme "Identifier" -destination "id=${{ steps.prepare-simulator.outputs.destination-id }}"
- uses: sersoft-gmbh/swift-coverage-action@v4
with:
target-name-filter: ^Identifier$
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
macos:
name: "Xcode ${{ matrix.xcode }}, macOS 14"
runs-on: macOS-14
strategy:
matrix:
xcode:
- "16.1"
steps:
- uses: actions/checkout@v4
- name: "Select Xcode ${{ matrix.xcode }}"
uses: ./.github/actions/xcode-select
with:
version: ${{ matrix.xcode }}
- name: "Build and test"
run: xcodebuild test -scheme "Identifier" -destination "name=My Mac"
- uses: sersoft-gmbh/swift-coverage-action@v4
with:
target-name-filter: ^Identifier$
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
+14 -28
View File
@@ -1,29 +1,16 @@
/.swiftpm/xcode/package.xcworkspace/
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## User settings
xcuserdata/
## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
@@ -38,6 +25,12 @@ playground.xcworkspace
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
@@ -56,12 +49,12 @@ playground.xcworkspace
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
Carthage/Build/
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
@@ -69,10 +62,3 @@ fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
-6
View File
@@ -1,6 +0,0 @@
[submodule "Carthage/Checkouts/xcconfigs"]
path = Carthage/Checkouts/xcconfigs
url = https://github.com/jspahrsummers/xcconfigs.git
[submodule "Carthage/Checkouts/Nimble"]
path = Carthage/Checkouts/Nimble
url = https://github.com/Quick/Nimble.git
-4
View File
@@ -1,4 +0,0 @@
# Configuration for Hound (https://houndci.com)
swiftlint:
config_file: .swiftlint.yml
+57 -10
View File
@@ -2,76 +2,123 @@
excluded:
- .build
- Carthage
- Tests/LinuxMain.swift
- Tests/IdentifierTests/XCTestManifests.swift
analyzer_rules:
- capture_variable
- typesafe_array_init
- unused_declaration
- unused_import
opt_in_rules:
- anonymous_argument_in_multiline_closure
- array_init
- attributes
- balanced_xctest_lifecycle
- closure_body_length
- closure_end_indentation
- closure_spacing
- collection_alignment
- comma_inheritance
- conditional_returns_on_newline
- contains_over_filter_count
- contains_over_filter_is_empty
- contains_over_first_not_nil
- contains_over_range_nil_comparison
- convenience_type
- direct_return
- discouraged_assert
- discouraged_none_name
- discouraged_object_literal
- discouraged_optional_boolean
- discouraged_optional_collection
- empty_collection_literal
- empty_count
- empty_string
- empty_xctest_method
- enum_case_associated_values_count
- expiring_todo
- explicit_enum_raw_value
- explicit_init
- extension_access_modifier
- fallthrough
- fatal_error_message
- file_name
- file_name_no_space
- final_test_case
- first_where
- flatmap_over_map_reduce
- force_unwrapping
- function_default_parameter_at_end
- ibinspectable_in_extension
- identical_operands
- implicit_return
- implicitly_unwrapped_optional
- indentation_width
- joined_default_parameter
- last_where
- legacy_random
- legacy_multiple
- legacy_objc_type
- let_var_whitespace
- literal_expression_end_indentation
- local_doc_comment
- lower_acl_than_parent
- missing_docs
- modifier_order
- multiline_arguments
- multiline_function_chains
- multiline_literal_brackets
- multiline_parameters
- nimble_operator
- multiline_parameters_brackets
- no_empty_block
- no_magic_numbers
- non_overridable_class_declaration
- nslocalizedstring_key
- nslocalizedstring_require_bundle
- number_separator
- operator_usage_whitespace
- optional_enum_case_matching
- overridden_super_call
- override_in_extension
- pattern_matching_keywords
- period_spacing
- prefer_key_path
- prefer_self_in_static_references
- prefer_self_type_over_type_of_self
- prefer_zero_over_explicit_init
- private_action
- private_outlet
- prohibited_interface_builder
- prohibited_super_call
- raw_value_for_camel_cased_codable_enum
- reduce_into
- redundant_nil_coalescing
- redundant_type_annotation
- return_value_from_void_function
- self_binding
- shorthand_argument
- shorthand_optional_binding
- single_test_class
- sorted_first_last
- sorted_imports
- static_operator
- strict_fileprivate
- strong_iboutlet
- switch_case_on_newline
- test_case_accessibility
- toggle_bool
- unavailable_function
- unhandled_throwing_task
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- untyped_error_in_catch
- unused_import
- unused_private_declaration
- unused_parameter
- vertical_parameter_alignment_on_call
- vertical_whitespace_between_cases
- vertical_whitespace_closing_braces
- vertical_whitespace_opening_braces
- weak_delegate
- xct_specific_matcher
- yoda_condition
line_length:
ignores_function_declarations: true
trailing_comma:
mandatory_comma: true
-60
View File
@@ -1,60 +0,0 @@
# Configuration for Travis (https://travis-ci.com)
os: osx
osx_image: xcode10.2
language: swift
stages:
- pretest
- test
jobs:
include:
- stage: pretest
name: Validate Linux test manifest
install: swift test --generate-linuxmain --disable-automatic-resolution
script: git diff --exit-code
- &spm
stage: test
name: macOS / SPM 5.0 / Swift 5.0
script: swift test --disable-automatic-resolution -Xswiftc -swift-version -Xswiftc 5
- <<: *spm
name: Linux / SPM 5.0 / Swift 5.0
os: linux
language: generic
env: SWIFT_VERSION=5.0
install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
- &cocoapods
name: CocoaPods / pod lib lint
script: pod lib lint
- &xcode
name: macOS / Xcode 10.2 / Swift 5.0
xcode_workspace: Identifier.xcworkspace
xcode_scheme: Identifier
xcode_destination: 'platform=macOS'
- <<: *xcode
name: iOS / Xcode 10.2 / Swift 5.0
xcode_destination: 'OS=12.2,name=iPhone SE'
- <<: *xcode
name: tvOS / Xcode 10.2 / Swift 5.0
xcode_destination: 'OS=12.2,name=Apple TV'
- <<: *xcode
name: watchOS / Xcode 10.2 / Swift 5.0
xcode_destination: 'OS=5.2,name=Apple Watch Series 2 - 38mm'
script: set -o pipefail && xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -destination "$TRAVIS_XCODE_DESTINATION" build | xcpretty
- name: Gather test coverage
xcode_project: Identifier.xcodeproj
xcode_scheme: Identifier-Package
xcode_destination: 'platform=macOS'
before_install:
- rm -r Identifier.xcodeproj
- echo "@available(*, unavailable) func doNothing() {}" > Sources/Identifier/_CoverageHack.swift # Add a second source file to appease Codecov processing
install: swift package generate-xcodeproj --enable-code-coverage
after_success: bash <(curl -s https://codecov.io/bash)
notifications:
email: false
-4
View File
@@ -1,4 +0,0 @@
# Configuration for Carthage (https://github.com/Carthage/Carthage)
github "jspahrsummers/xcconfigs"
github "Quick/Nimble" ~> 8.0
-2
View File
@@ -1,2 +0,0 @@
github "Quick/Nimble" "v8.0.1"
github "jspahrsummers/xcconfigs" "0.12"
-19
View File
@@ -1,19 +0,0 @@
Pod::Spec.new do |spec|
spec.name = "Identifier"
spec.version = "0.1.1"
spec.summary = "Unique, strongly-typed identifiers in Swift."
spec.description = "`Identifier` is a generic struct backed by a UUID, which can be specialized for the model type it identifies and provides unique, decentralized identity in a value type. It is Equatable, Hashable, and Codable, serializing to a simple UUID string."
spec.homepage = "https://github.com/mattrubin/Identifier"
spec.license = { :type => "MIT", :file => "LICENSE.md" }
spec.author = "Matt Rubin"
spec.source = { :git => "https://github.com/mattrubin/Identifier.git", :tag => "#{spec.version}" }
spec.source_files = "Sources/Identifier/**/*.swift"
spec.frameworks = "Foundation"
spec.swift_version = "5.0"
spec.ios.deployment_target = "8.0"
spec.osx.deployment_target = "10.10"
spec.tvos.deployment_target = "9.0"
spec.watchos.deployment_target = "2.0"
end
-327
View File
@@ -1,327 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
C97980FE224FE68800132BEC /* Identifier.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C97980F4224FE68800132BEC /* Identifier.framework */; };
C9798103224FE68800132BEC /* IdentifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9798102224FE68800132BEC /* IdentifierTests.swift */; };
C9798105224FE68800132BEC /* Identifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97980F7224FE68800132BEC /* Identifier.swift */; };
C97B1BA32250701D00EAC849 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C97B1BA22250701D00EAC849 /* Nimble.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
C97980FF224FE68800132BEC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C97980EB224FE68800132BEC /* Project object */;
proxyType = 1;
remoteGlobalIDString = C97980F3224FE68800132BEC;
remoteInfo = Identifier;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
C950E96522529A2500583754 /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Framework.xcconfig; path = Base/Targets/Framework.xcconfig; sourceTree = "<group>"; };
C950E96622529BA500583754 /* Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Application.xcconfig; path = Base/Targets/Application.xcconfig; sourceTree = "<group>"; };
C97980F4224FE68800132BEC /* Identifier.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Identifier.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C97980F7224FE68800132BEC /* Identifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identifier.swift; sourceTree = "<group>"; };
C97980FD224FE68800132BEC /* IdentifierTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IdentifierTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C9798102224FE68800132BEC /* IdentifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifierTests.swift; sourceTree = "<group>"; };
C979812C224FF07C00132BEC /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Base/Configurations/Debug.xcconfig; sourceTree = "<group>"; };
C979812D224FF07C00132BEC /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Base/Configurations/Release.xcconfig; sourceTree = "<group>"; };
C97B1BA22250701D00EAC849 /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C97980FA224FE68800132BEC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C97980FE224FE68800132BEC /* Identifier.framework in Frameworks */,
C97B1BA32250701D00EAC849 /* Nimble.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C97980EA224FE68800132BEC = {
isa = PBXGroup;
children = (
C97980F6224FE68800132BEC /* Identifier */,
C9798101224FE68800132BEC /* IdentifierTests */,
C979810F224FF07B00132BEC /* Configurations */,
C97B1BA12250701D00EAC849 /* Frameworks */,
C97980F5224FE68800132BEC /* Products */,
);
sourceTree = "<group>";
};
C97980F5224FE68800132BEC /* Products */ = {
isa = PBXGroup;
children = (
C97980F4224FE68800132BEC /* Identifier.framework */,
C97980FD224FE68800132BEC /* IdentifierTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
C97980F6224FE68800132BEC /* Identifier */ = {
isa = PBXGroup;
children = (
C97980F7224FE68800132BEC /* Identifier.swift */,
);
name = Identifier;
path = Sources/Identifier;
sourceTree = "<group>";
};
C9798101224FE68800132BEC /* IdentifierTests */ = {
isa = PBXGroup;
children = (
C9798102224FE68800132BEC /* IdentifierTests.swift */,
);
name = IdentifierTests;
path = Tests/IdentifierTests;
sourceTree = "<group>";
};
C979810F224FF07B00132BEC /* Configurations */ = {
isa = PBXGroup;
children = (
C979812C224FF07C00132BEC /* Debug.xcconfig */,
C979812D224FF07C00132BEC /* Release.xcconfig */,
C950E96522529A2500583754 /* Framework.xcconfig */,
C950E96622529BA500583754 /* Application.xcconfig */,
);
name = Configurations;
path = Carthage/Checkouts/xcconfigs;
sourceTree = "<group>";
};
C97B1BA12250701D00EAC849 /* Frameworks */ = {
isa = PBXGroup;
children = (
C97B1BA22250701D00EAC849 /* Nimble.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
C97980F3224FE68800132BEC /* Identifier */ = {
isa = PBXNativeTarget;
buildConfigurationList = C9798108224FE68800132BEC /* Build configuration list for PBXNativeTarget "Identifier" */;
buildPhases = (
C97980F0224FE68800132BEC /* Sources */,
);
buildRules = (
);
dependencies = (
);
name = Identifier;
productName = Identifier;
productReference = C97980F4224FE68800132BEC /* Identifier.framework */;
productType = "com.apple.product-type.framework";
};
C97980FC224FE68800132BEC /* IdentifierTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C979810B224FE68800132BEC /* Build configuration list for PBXNativeTarget "IdentifierTests" */;
buildPhases = (
C97980F9224FE68800132BEC /* Sources */,
C97980FA224FE68800132BEC /* Frameworks */,
);
buildRules = (
);
dependencies = (
C9798100224FE68800132BEC /* PBXTargetDependency */,
);
name = IdentifierTests;
productName = IdentifierTests;
productReference = C97980FD224FE68800132BEC /* IdentifierTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C97980EB224FE68800132BEC /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1020;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Matt Rubin";
TargetAttributes = {
C97980F3224FE68800132BEC = {
CreatedOnToolsVersion = 10.2;
};
C97980FC224FE68800132BEC = {
CreatedOnToolsVersion = 10.2;
};
};
};
buildConfigurationList = C97980EE224FE68800132BEC /* Build configuration list for PBXProject "Identifier" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = C97980EA224FE68800132BEC;
productRefGroup = C97980F5224FE68800132BEC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C97980F3224FE68800132BEC /* Identifier */,
C97980FC224FE68800132BEC /* IdentifierTests */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
C97980F0224FE68800132BEC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C9798105224FE68800132BEC /* Identifier.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C97980F9224FE68800132BEC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C9798103224FE68800132BEC /* IdentifierTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
C9798100224FE68800132BEC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C97980F3224FE68800132BEC /* Identifier */;
targetProxy = C97980FF224FE68800132BEC /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
C9798106224FE68800132BEC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C979812C224FF07C00132BEC /* Debug.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_DYNAMIC_NO_PIC = NO;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator";
SWIFT_VERSION = 5.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
name = Debug;
};
C9798107224FE68800132BEC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C979812D224FF07C00132BEC /* Release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
ENABLE_NS_ASSERTIONS = NO;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator";
SWIFT_VERSION = 5.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
name = Release;
};
C9798109224FE68800132BEC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C950E96522529A2500583754 /* Framework.xcconfig */;
buildSettings = {
INFOPLIST_FILE = Sources/Identifier/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "me.mattrubin.$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Debug;
};
C979810A224FE68800132BEC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C950E96522529A2500583754 /* Framework.xcconfig */;
buildSettings = {
INFOPLIST_FILE = Sources/Identifier/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "me.mattrubin.$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Release;
};
C979810C224FE68800132BEC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C950E96622529BA500583754 /* Application.xcconfig */;
buildSettings = {
INFOPLIST_FILE = Tests/IdentifierTests/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "me.mattrubin.$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Debug;
};
C979810D224FE68800132BEC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C950E96622529BA500583754 /* Application.xcconfig */;
buildSettings = {
INFOPLIST_FILE = Tests/IdentifierTests/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "me.mattrubin.$(PRODUCT_NAME:c99extidentifier)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C97980EE224FE68800132BEC /* Build configuration list for PBXProject "Identifier" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C9798106224FE68800132BEC /* Debug */,
C9798107224FE68800132BEC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C9798108224FE68800132BEC /* Build configuration list for PBXNativeTarget "Identifier" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C9798109224FE68800132BEC /* Debug */,
C979810A224FE68800132BEC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C979810B224FE68800132BEC /* Build configuration list for PBXNativeTarget "IdentifierTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C979810C224FE68800132BEC /* Debug */,
C979810D224FE68800132BEC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = C97980EB224FE68800132BEC /* Project object */;
}
@@ -1,100 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C97980F3224FE68800132BEC"
BuildableName = "Identifier.framework"
BlueprintName = "Identifier"
ReferencedContainer = "container:Identifier.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C97980FC224FE68800132BEC"
BuildableName = "IdentifierTests.xctest"
BlueprintName = "IdentifierTests"
ReferencedContainer = "container:Identifier.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C97980F3224FE68800132BEC"
BuildableName = "Identifier.framework"
BlueprintName = "Identifier"
ReferencedContainer = "container:Identifier.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C97980F3224FE68800132BEC"
BuildableName = "Identifier.framework"
BlueprintName = "Identifier"
ReferencedContainer = "container:Identifier.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C97980F3224FE68800132BEC"
BuildableName = "Identifier.framework"
BlueprintName = "Identifier"
ReferencedContainer = "container:Identifier.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "container:Identifier.xcodeproj">
</FileRef>
<FileRef
location = "group:Carthage/Checkouts/Nimble/Nimble.xcodeproj">
</FileRef>
</Workspace>
@@ -1,8 +0,0 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,8 +0,0 @@
<?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>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Matt Rubin
Copyright (c) 2019-2024 Matt Rubin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
-16
View File
@@ -1,16 +0,0 @@
{
"object": {
"pins": [
{
"package": "Nimble",
"repositoryURL": "https://github.com/Quick/Nimble.git",
"state": {
"branch": null,
"revision": "43304bf2b1579fd555f2fdd51742771c1e4f2b98",
"version": "8.0.1"
}
}
]
},
"version": 1
}
+8 -11
View File
@@ -1,24 +1,21 @@
// swift-tools-version:5.0
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "Identifier",
platforms: [
.iOS(.v8),
.macOS(.v10_10),
.tvOS(.v9),
.watchOS(.v2),
.iOS(.v15),
.macOS(.v11),
.tvOS(.v15),
.visionOS(.v1),
.watchOS(.v8),
],
products: [
.library(name: "Identifier", targets: ["Identifier"]),
],
dependencies: [
.package(url: "https://github.com/Quick/Nimble.git", from: "8.0.0"),
],
targets: [
.target(name: "Identifier"),
.testTarget(name: "IdentifierTests", dependencies: ["Identifier", "Nimble"]),
],
swiftLanguageVersions: [.v5]
.testTarget(name: "IdentifierTests", dependencies: ["Identifier"]),
]
)
+24 -6
View File
@@ -1,14 +1,14 @@
# Identifier
### Unique, strongly-typed identifiers in Swift.
[![Build Status](https://travis-ci.com/mattrubin/Identifier.svg?branch=develop)](https://travis-ci.com/mattrubin/Identifier)
[![Codecov](https://img.shields.io/codecov/c/github/mattrubin/Identifier/develop.svg)](https://codecov.io/gh/mattrubin/Identifier)
![Swift 5.0](https://img.shields.io/badge/swift-5.0-orange.svg)
![Available via Carthage, CocoaPods, or SPM](https://img.shields.io/badge/via-Carthage%20%7C%20CocoaPods%20%7C%20SPM-MediumSlateBlue.svg)
![Platforms: iOS, macOS, tvOS, watchOS, Linux](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux-blue.svg)
[![Xcode CI status](https://github.com/mattrubin/Identifier/actions/workflows/xcode.yml/badge.svg)](https://github.com/mattrubin/Identifier/actions/workflows/xcode.yml)
[![SPM CI status](https://github.com/mattrubin/Identifier/actions/workflows/spm.yml/badge.svg)](https://github.com/mattrubin/Identifier/actions/workflows/spm.yml)
[![Code Coverage](https://img.shields.io/codecov/c/github/mattrubin/Identifier/develop.svg)](https://codecov.io/gh/mattrubin/Identifier)
![Swift 6.0](https://img.shields.io/badge/swift-6.0-orange.svg)
![Platforms: iOS, macOS, tvOS, visionOS, watchOS, Linux](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20visionOS%20%7C%20watchOS%20%7C%20Linux-blue.svg)
[![MIT License](https://img.shields.io/badge/license-MIT-lightgray.svg)](LICENSE.md)
`Identifier` is a generic struct backed by a UUID, which can be specialized for the model type it identifies and provides unique, decentralized identity in a value type. It is Equatable, Hashable, and Codable, serializing to a simple UUID string.
`Identifier` is a generic struct backed by a UUID, which can be specialized for the model type it identifies and provides unique, decentralized identity in a value type. It is Equatable, Hashable, Sendable, and Codable, serializing to a simple UUID string.
Instead of using string identifiers in your models:
```swift
@@ -19,6 +19,7 @@ struct Comment: Equatable, Codable {
let date: Date
}
```
You can use typed identifiers, which help ensure an ID for a model of one type is never accidentally used in place of another:
```swift
struct Comment: Equatable, Codable {
@@ -29,6 +30,23 @@ struct Comment: Equatable, Codable {
}
```
## Installation
### [SPM][]
Add the following line to the dependencies section of your [package manifest][Package.swift]:
```swift
.package(url: "https://github.com/mattrubin/Identifier.git", from: "1.1.0"),
```
Then add `"Identifier"` to the dependencies array of any target which should be linked with this library.
[SPM]: https://swift.org/package-manager/
[Package.swift]: https://github.com/swiftlang/swift-package-manager/tree/main/Documentation
## License
Identifier is released under the [MIT License](LICENSE.md).
+32 -8
View File
@@ -1,14 +1,38 @@
import struct Foundation.UUID
public struct Identifier<T>: Equatable, Hashable {
public let uuid: UUID
public struct Identifier<T>: Equatable, Hashable, RawRepresentable, Sendable {
public let rawValue: UUID
public init(uuid: UUID) {
self.uuid = uuid
public init(rawValue: UUID) {
self.rawValue = rawValue
}
public static func random() -> Identifier {
return self.init(uuid: UUID())
public static func random() -> Self {
self.init(rawValue: UUID())
}
}
// MARK: - String Convertible
extension Identifier: LosslessStringConvertible {
/// Instantiates an identifier from a string representation.
public init?(_ description: String) {
guard let uuid = UUID(uuidString: description) else {
return nil
}
self.init(rawValue: uuid)
}
/// A string representation of this identifier.
public var description: String {
rawValue.uuidString
}
}
extension Identifier: CustomDebugStringConvertible {
/// A detailed string representation of this identifier, for use in debugging.
public var debugDescription: String {
"Identifier<\(T.self)>(rawValue: \(rawValue))"
}
}
@@ -16,10 +40,10 @@ public struct Identifier<T>: Equatable, Hashable {
extension Identifier: Codable {
public init(from decoder: Decoder) throws {
uuid = try UUID(from: decoder)
rawValue = try UUID(from: decoder)
}
public func encode(to encoder: Encoder) throws {
try uuid.encode(to: encoder)
try rawValue.encode(to: encoder)
}
}
-22
View File
@@ -1,22 +0,0 @@
<?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>$(DEVELOPMENT_LANGUAGE)</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>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.1.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
+111 -35
View File
@@ -1,71 +1,147 @@
import XCTest
import Nimble
import Foundation
import Testing
import Identifier
let firstUUID = UUID(uuidString: "B9212942-B5B9-4547-A994-375921769411")!
let secondUUID = UUID(uuidString: "1552BA9E-8378-489F-B6BC-E810973931E0")!
struct IdentifierTests {
let firstUUID: UUID
let secondUUID: UUID
final class IdentifierTests: XCTestCase {
func testInitWithUUID() {
let uuid = UUID()
let identifier = Identifier<Void>(uuid: uuid)
XCTAssertEqual(uuid, identifier.uuid)
init() throws {
firstUUID = try #require(UUID(uuidString: "B9212942-B5B9-4547-A994-375921769411"))
secondUUID = try #require(UUID(uuidString: "1552BA9E-8378-489F-B6BC-E810973931E0"))
}
@Test
func testInitWithRawValue() {
let uuid = UUID()
let identifier = Identifier<Void>(rawValue: uuid)
#expect(uuid == identifier.rawValue)
}
@Test
func testRandomIdentifier() {
// Ensure that `.random()` creates a different unique identifier each time it is called.
let first = Identifier<Void>.random()
let second = Identifier<Void>.random()
XCTAssertNotEqual(first, second)
#expect(first != second)
}
@Test
func testEquality() {
let first = Identifier<Void>(uuid: firstUUID)
XCTAssertEqual(first, first)
let first = Identifier<Void>(rawValue: firstUUID)
#expect(first == first) // swiftlint:disable:this identical_operands
let second = Identifier<Void>(uuid: secondUUID)
let secondAgain = Identifier<Void>(uuid: secondUUID)
XCTAssertEqual(second, secondAgain)
let second = Identifier<Void>(rawValue: secondUUID)
let secondAgain = Identifier<Void>(rawValue: secondUUID)
#expect(second == secondAgain)
XCTAssertNotEqual(first, second)
XCTAssertNotEqual(first, secondAgain)
#expect(first != second)
#expect(first != secondAgain)
let third = Identifier<Void>.random()
XCTAssertEqual(third, third)
#expect(third == third) // swiftlint:disable:this identical_operands
let fourth = Identifier<Void>.random()
XCTAssertEqual(fourth, fourth)
#expect(fourth == fourth) // swiftlint:disable:this identical_operands
XCTAssertNotEqual(third, fourth)
#expect(third != fourth)
}
// MARK: - String Convertible
@Test
func testInitWithDescription() {
let firstFromUUID = Identifier<Int>(rawValue: firstUUID)
let firstDescription = "B9212942-B5B9-4547-A994-375921769411"
let firstFromDescription = Identifier<Int>(firstDescription)
#expect(firstFromDescription == firstFromUUID)
let secondRandom = Identifier<String>.random()
let secondDescription = secondRandom.rawValue.uuidString
let secondFromDescription = Identifier<String>(secondDescription)
#expect(secondFromDescription == secondRandom)
let validDescription = UUID().uuidString
let validIdentifier = Identifier<Float>(validDescription)
#expect(validIdentifier != nil)
let invalidDescription = "12345"
let invalidIdentifier = Identifier<Float>(invalidDescription)
#expect(invalidIdentifier == nil)
}
@Test
func testDescription() {
let first = Identifier<Int>(rawValue: firstUUID)
let firstExpectedDebugDescription = "B9212942-B5B9-4547-A994-375921769411"
#expect(first.description == firstExpectedDebugDescription)
let second = Identifier<String>.random()
let secondExpectedDebugDescription = second.rawValue.uuidString
#expect(second.description == secondExpectedDebugDescription)
}
@Test
func testDebugDescription() {
let first = Identifier<Int>(rawValue: firstUUID)
let firstExpectedDebugDescription = "Identifier<Int>(rawValue: B9212942-B5B9-4547-A994-375921769411)"
#expect(first.debugDescription == firstExpectedDebugDescription)
let second = Identifier<String>.random()
let secondExpectedDebugDescription = "Identifier<String>(rawValue: " + second.rawValue.uuidString + ")"
#expect(second.debugDescription == secondExpectedDebugDescription)
}
// MARK: - Codable
func testEncode() {
let uuid = UUID(uuidString: "a80c0fdf-c1fe-4023-8ba3-dd1ad9b3cb94")!
let expectedJSON = "[\"A80C0FDF-C1FE-4023-8BA3-DD1AD9B3CB94\"]".data(using: .utf8)!
@Test
func testEncode() throws {
let uuid = try #require(UUID(uuidString: "a80c0fdf-c1fe-4023-8ba3-dd1ad9b3cb94"))
let expectedJSON = Data("[\"A80C0FDF-C1FE-4023-8BA3-DD1AD9B3CB94\"]".utf8)
let identifier = Identifier<Void>(uuid: uuid)
let identifier = Identifier<Void>(rawValue: uuid)
let encoder = JSONEncoder()
expect(try encoder.encode(JSONFragmentEncodingWrapper(identifier))) == expectedJSON
#expect(try encoder.encode(JSONFragmentEncodingWrapper(identifier)) == expectedJSON)
}
func testDecode() {
let uuid = UUID(uuidString: "3b46cdce-a7d1-424a-ad2c-99fcd200f1a2")!
let json = "[\"3B46CDCE-A7D1-424A-AD2C-99FCD200F1A2\"]".data(using: .utf8)!
@Test
func testDecode() throws {
let uuid = try #require(UUID(uuidString: "3b46cdce-a7d1-424a-ad2c-99fcd200f1a2"))
let json = Data("[\"3B46CDCE-A7D1-424A-AD2C-99FCD200F1A2\"]".utf8)
let decoder = JSONDecoder()
expect(try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: json).value)
== Identifier(uuid: uuid)
#expect(
try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: json).value ==
Identifier(rawValue: uuid))
let emptyJSON = Data()
expect(try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: emptyJSON).value)
.to(throwError())
#expect(throws: DecodingError.self) {
try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: emptyJSON).value
}
let badStringJSON = "[\"3B46CDCE\"]".data(using: .utf8)!
expect(try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: badStringJSON).value)
.to(throwError())
let badStringJSON = Data("[\"3B46CDCE\"]".utf8)
#expect(throws: DecodingError.self) {
try decoder.decode(JSONFragmentEncodingWrapper<Identifier<Void>>.self, from: badStringJSON).value
}
}
// MARK: - Sendable
/// This test will fail to compile if `Identifier` does not conform to `Sendable`.
@Test
func testSendable() async {
actor IdentifierProducer {
func makeIdentifier<T>() -> Identifier<T> {
Identifier.random()
}
}
let producer = IdentifierProducer()
let identifier: Identifier<Void> = await producer.makeIdentifier()
#expect(identifier == identifier) // swiftlint:disable:this identical_operands
}
}
-22
View File
@@ -1,22 +0,0 @@
<?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>$(DEVELOPMENT_LANGUAGE)</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>0.1.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
@@ -1,22 +0,0 @@
#if !canImport(ObjectiveC)
import XCTest
extension IdentifierTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__IdentifierTests = [
("testDecode", testDecode),
("testEncode", testEncode),
("testEquality", testEquality),
("testInitWithUUID", testInitWithUUID),
("testRandomIdentifier", testRandomIdentifier),
]
}
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(IdentifierTests.__allTests__IdentifierTests),
]
}
#endif
-8
View File
@@ -1,8 +0,0 @@
import XCTest
import IdentifierTests
var tests = [XCTestCaseEntry]()
tests += IdentifierTests.__allTests()
XCTMain(tests)