47 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
30 changed files with 410 additions and 862 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
-64
View File
@@ -1,64 +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: SPM @ Xcode 10.2 / macOS
script: swift test --disable-automatic-resolution
- <<: *spm
name: SPM 5.0 / Linux
os: linux
language: generic
env: SWIFT_VERSION=5.0
install: eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
- &cocoapods
name: CocoaPods & Xcode 10.2 / pod lib lint
script: pod lib lint
- &carthage
name: Carthage & Xcode 10.2 / carthage build --archive
script: carthage build --archive
- &xcode
name: Xcode 10.2 / macOS
xcode_workspace: Identifier.xcworkspace
xcode_scheme: Identifier
xcode_destination: 'platform=macOS'
- <<: *xcode
name: Xcode 10.2 / iOS
xcode_destination: 'OS=12.2,name=iPhone SE'
- <<: *xcode
name: Xcode 10.2 / tvOS
xcode_destination: 'OS=12.2,name=Apple TV'
- <<: *xcode
name: Xcode 10.2 / watchOS
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" ~> 1.0
github "Quick/Nimble" ~> 8.0
-2
View File
@@ -1,2 +0,0 @@
github "Quick/Nimble" "v8.0.1"
github "jspahrsummers/xcconfigs" "1.0"
-19
View File
@@ -1,19 +0,0 @@
Pod::Spec.new do |spec|
spec.name = "Identifier"
spec.version = "1.1.0"
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
-378
View File
@@ -1,378 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXAggregateTarget section */
C9425DEB227555DC00EF93BD /* Lint Identifier */ = {
isa = PBXAggregateTarget;
buildConfigurationList = C9425DEE227555DD00EF93BD /* Build configuration list for PBXAggregateTarget "Lint Identifier" */;
buildPhases = (
C9425DEF227555EA00EF93BD /* Run SwiftLint */,
);
dependencies = (
);
name = "Lint Identifier";
productName = "Lint Identifier";
};
/* End PBXAggregateTarget section */
/* 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 = {
C9425DEB227555DC00EF93BD = {
CreatedOnToolsVersion = 10.2.1;
};
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 */,
C9425DEB227555DC00EF93BD /* Lint Identifier */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
C9425DEF227555EA00EF93BD /* Run SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Run SwiftLint";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint is not installed. (https://github.com/realm/SwiftLint)\"\nfi\n";
};
/* End PBXShellScriptBuildPhase 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 */
C9425DEC227555DD00EF93BD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Debug;
};
C9425DED227555DD00EF93BD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
C9798106224FE68800132BEC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C979812C224FF07C00132BEC /* Debug.xcconfig */;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_DYNAMIC_NO_PIC = NO;
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_ENABLE_OBJC_WEAK = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
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 */
C9425DEE227555DD00EF93BD /* Build configuration list for PBXAggregateTarget "Lint Identifier" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C9425DEC227555DD00EF93BD /* Debug */,
C9425DED227555DD00EF93BD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
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,114 +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>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C9425DEB227555DC00EF93BD"
BuildableName = "Lint Identifier"
BlueprintName = "Lint 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"]),
]
)
+9 -39
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 {
@@ -32,37 +33,6 @@ struct Comment: Equatable, Codable {
## Installation
### [Carthage][]
Add the following line to your [Cartfile][]:
````config
github "mattrubin/Identifier" ~> 1.1
````
Then run `carthage update Identifier` to install the latest version of the framework.
Be sure to check the Carthage README file for the latest instructions on [adding frameworks to an application][carthage-instructions].
[Carthage]: https://github.com/Carthage/Carthage
[Cartfile]: https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile
[carthage-instructions]: https://github.com/Carthage/Carthage/blob/master/README.md#adding-frameworks-to-an-application
### [CocoaPods][]
Add the following line to your [Podfile][]:
````ruby
pod 'Identifier', '~> 1.1'
````
Identifier, like all pods written in Swift, can only be integrated as a framework. Make sure to add the line `use_frameworks!` to your Podfile or target to opt into frameworks instead of static libraries.
Then run `pod install` to install the latest version of the framework.
[CocoaPods]: https://cocoapods.org
[Podfile]: https://guides.cocoapods.org/using/the-podfile.html
### [SPM][]
Add the following line to the dependencies section of your [package manifest][Package.swift]:
@@ -71,10 +41,10 @@ Add the following line to the dependencies section of your [package manifest][Pa
.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
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/apple/swift-package-manager/tree/master/Documentation
[Package.swift]: https://github.com/swiftlang/swift-package-manager/tree/main/Documentation
## License
+11 -11
View File
@@ -1,14 +1,14 @@
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())
}
}
@@ -20,19 +20,19 @@ extension Identifier: LosslessStringConvertible {
guard let uuid = UUID(uuidString: description) else {
return nil
}
self.init(uuid: uuid)
self.init(rawValue: uuid)
}
/// A string representation of this identifier.
public var description: String {
return uuid.uuidString
rawValue.uuidString
}
}
extension Identifier: CustomDebugStringConvertible {
/// A detailed string representation of this identifier, for use in debugging.
public var debugDescription: String {
return "Identifier<\(T.self)>(uuid: \(uuid))"
"Identifier<\(T.self)>(rawValue: \(rawValue))"
}
}
@@ -40,10 +40,10 @@ extension Identifier: CustomDebugStringConvertible {
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>1.1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
+84 -50
View File
@@ -1,113 +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>(uuid: firstUUID)
let firstFromUUID = Identifier<Int>(rawValue: firstUUID)
let firstDescription = "B9212942-B5B9-4547-A994-375921769411"
let firstFromDescription = Identifier<Int>(firstDescription)
XCTAssertEqual(firstFromDescription, firstFromUUID)
#expect(firstFromDescription == firstFromUUID)
let secondRandom = Identifier<String>.random()
let secondDescription = secondRandom.uuid.uuidString
let secondDescription = secondRandom.rawValue.uuidString
let secondFromDescription = Identifier<String>(secondDescription)
XCTAssertEqual(secondFromDescription, secondRandom)
#expect(secondFromDescription == secondRandom)
let validDescription = UUID().uuidString
let validIdentifier = Identifier<Float>(validDescription)
XCTAssertNotNil(validIdentifier)
#expect(validIdentifier != nil)
let invalidDescription = "12345"
let invalidIdentifier = Identifier<Float>(invalidDescription)
XCTAssertNil(invalidIdentifier)
#expect(invalidIdentifier == nil)
}
@Test
func testDescription() {
let first = Identifier<Int>(uuid: firstUUID)
let first = Identifier<Int>(rawValue: firstUUID)
let firstExpectedDebugDescription = "B9212942-B5B9-4547-A994-375921769411"
XCTAssertEqual(first.description, firstExpectedDebugDescription)
#expect(first.description == firstExpectedDebugDescription)
let second = Identifier<String>.random()
let secondExpectedDebugDescription = second.uuid.uuidString
XCTAssertEqual(second.description, secondExpectedDebugDescription)
let secondExpectedDebugDescription = second.rawValue.uuidString
#expect(second.description == secondExpectedDebugDescription)
}
@Test
func testDebugDescription() {
let first = Identifier<Int>(uuid: firstUUID)
let firstExpectedDebugDescription = "Identifier<Int>(uuid: B9212942-B5B9-4547-A994-375921769411)"
XCTAssertEqual(first.debugDescription, firstExpectedDebugDescription)
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>(uuid: " + second.uuid.uuidString + ")"
XCTAssertEqual(second.debugDescription, secondExpectedDebugDescription)
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>1.1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
@@ -1,25 +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 = [
("testDebugDescription", testDebugDescription),
("testDecode", testDecode),
("testDescription", testDescription),
("testEncode", testEncode),
("testEquality", testEquality),
("testInitWithDescription", testInitWithDescription),
("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)