Skip to content

Commit 33939dd

Browse files
authored
Merge pull request #17 from eddiekaiger/swift-4
Swift 4 and 3.2
2 parents 28ad388 + 8b27637 commit 33939dd

22 files changed

+732
-248
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
language: objective-c
2-
osx_image: xcode8
2+
osx_image: xcode9
33

44
env:
55
- PLATFORM=iOS CODECOV=ios DESTINATION='platform=iOS Simulator,name=iPhone 6S'

Gemfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
source 'https://rubygems.org'
22

3-
gem 'cocoapods', '~> 1.1.1'
3+
gem 'cocoapods', '~> 1.3.0'

Gemfile.lock

+31-28
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,72 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
activesupport (4.2.7.1)
4+
CFPropertyList (2.3.5)
5+
activesupport (4.2.9)
56
i18n (~> 0.7)
6-
json (~> 1.7, >= 1.7.7)
77
minitest (~> 5.1)
88
thread_safe (~> 0.3, >= 0.3.4)
99
tzinfo (~> 1.1)
10-
claide (1.0.1)
11-
cocoapods (1.1.1)
10+
claide (1.0.2)
11+
cocoapods (1.3.1)
1212
activesupport (>= 4.0.2, < 5)
13-
claide (>= 1.0.1, < 2.0)
14-
cocoapods-core (= 1.1.1)
13+
claide (>= 1.0.2, < 2.0)
14+
cocoapods-core (= 1.3.1)
1515
cocoapods-deintegrate (>= 1.0.1, < 2.0)
16-
cocoapods-downloader (>= 1.1.2, < 2.0)
16+
cocoapods-downloader (>= 1.1.3, < 2.0)
1717
cocoapods-plugins (>= 1.0.0, < 2.0)
1818
cocoapods-search (>= 1.0.0, < 2.0)
1919
cocoapods-stats (>= 1.0.0, < 2.0)
20-
cocoapods-trunk (>= 1.1.1, < 2.0)
20+
cocoapods-trunk (>= 1.2.0, < 2.0)
2121
cocoapods-try (>= 1.1.0, < 2.0)
22-
colored (~> 1.2)
22+
colored2 (~> 3.1)
2323
escape (~> 0.0.4)
2424
fourflusher (~> 2.0.1)
2525
gh_inspector (~> 1.0)
26-
molinillo (~> 0.5.1)
26+
molinillo (~> 0.5.7)
2727
nap (~> 1.0)
28-
xcodeproj (>= 1.3.3, < 2.0)
29-
cocoapods-core (1.1.1)
30-
activesupport (>= 4.0.2, < 5)
28+
ruby-macho (~> 1.1)
29+
xcodeproj (>= 1.5.1, < 2.0)
30+
cocoapods-core (1.3.1)
31+
activesupport (>= 4.0.2, < 6)
3132
fuzzy_match (~> 2.0.4)
3233
nap (~> 1.0)
3334
cocoapods-deintegrate (1.0.1)
34-
cocoapods-downloader (1.1.2)
35+
cocoapods-downloader (1.1.3)
3536
cocoapods-plugins (1.0.0)
3637
nap
3738
cocoapods-search (1.0.0)
3839
cocoapods-stats (1.0.0)
39-
cocoapods-trunk (1.1.1)
40+
cocoapods-trunk (1.2.0)
4041
nap (>= 0.8, < 2.0)
4142
netrc (= 0.7.8)
4243
cocoapods-try (1.1.0)
43-
colored (1.2)
44+
colored2 (3.1.2)
4445
escape (0.0.4)
4546
fourflusher (2.0.1)
4647
fuzzy_match (2.0.4)
47-
gh_inspector (1.0.2)
48-
i18n (0.7.0)
49-
json (1.8.3)
50-
minitest (5.9.1)
51-
molinillo (0.5.2)
48+
gh_inspector (1.0.3)
49+
i18n (0.8.6)
50+
minitest (5.10.3)
51+
molinillo (0.5.7)
52+
nanaimo (0.2.3)
5253
nap (1.1.0)
5354
netrc (0.7.8)
54-
thread_safe (0.3.5)
55-
tzinfo (1.2.2)
55+
ruby-macho (1.1.0)
56+
thread_safe (0.3.6)
57+
tzinfo (1.2.3)
5658
thread_safe (~> 0.1)
57-
xcodeproj (1.3.3)
58-
activesupport (>= 3)
59-
claide (>= 1.0.1, < 2.0)
60-
colored (~> 1.2)
59+
xcodeproj (1.5.1)
60+
CFPropertyList (~> 2.3.3)
61+
claide (>= 1.0.2, < 2.0)
62+
colored2 (~> 3.1)
63+
nanaimo (~> 0.2.3)
6164

6265
PLATFORMS
6366
ruby
6467

6568
DEPENDENCIES
66-
cocoapods (~> 1.1.1)
69+
cocoapods (~> 1.3.0)
6770

6871
BUNDLED WITH
6972
1.13.6

README.md

+8-17
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
#### *A Swifty API for attributed strings.*
44

5-
![Swift Version](https://img.shields.io/badge/swift-3.0-orange.svg?style=flat)
5+
![Swift Version](https://img.shields.io/badge/swift-4-orange.svg?style=flat)
6+
![Swift Version](https://img.shields.io/badge/swift-3.2-orange.svg?style=flat)
67
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
78
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/SwiftyAttributes.svg)](https://img.shields.io/cocoapods/v/SwiftyAttributes.svg)
89
[![Platform](https://img.shields.io/cocoapods/p/SwiftyAttributes.svg?style=flat)](http://cocoapods.org/pods/SwiftyAttributes)
@@ -38,29 +39,19 @@ let fancyString = "Hello".withFont(.systemFont(ofSize: 12)) + " World!".withFont
3839
# Requirements
3940

4041
* iOS 8.0+, macOS 10.11+, watchOS 2.0+, tvOS 9.0+
42+
* Swift 4.0 or 3.2
43+
* Xcode 9
4144

4245
# Installation
4346

4447
### With CocoaPods
4548

46-
#### For **Swift 3**:
47-
4849
`pod 'SwiftyAttributes'`
4950

50-
#### For **Swift 4 Beta**:
51-
52-
`pod 'SwiftyAttributes', :git => 'https://github.com/eddiekaiger/SwiftyAttributes.git', :branch => 'swift-4'`
53-
5451
### With Carthage
5552

56-
#### For **Swift 3**:
57-
5853
`github "eddiekaiger/SwiftyAttributes"`
5954

60-
#### For **Swift 4 Beta**:
61-
62-
`github "eddiekaiger/SwiftyAttributes" "swift-4"`
63-
6455
# Usage
6556

6657
Initializing attributed strings in `SwiftyAttributes` can be done several ways:
@@ -82,7 +73,7 @@ Initializing attributed strings in `SwiftyAttributes` can be done several ways:
8273

8374
You can retrieve the attribute at a specific location using an attribute name from the `Attribute.Name` enum:
8475
````swift
85-
let attr: Attribute? = myAttributedString.attribute(.shadow, at: 5)
76+
let attr: Attribute? = myAttributedString.swiftyAttribute(.shadow, at: 5)
8677
````
8778

8879
Several API methods are provided to use these new enums as well as Swift's `Range` type instead of `NSRange`. Some of the method signatures include:
@@ -96,18 +87,18 @@ extension NSMutableAttributedString {
9687
func replaceCharacters(in range: Range<Int>, with str: String)
9788
func replaceCharacters(in range: Range<Int>, with attrString: NSAttributedString)
9889
func deleteCharacters(in range: Range<Int>)
99-
func removeAttribute(_ name: Attribute.Name, range: Range<Int>)
90+
func removeAttribute(_ name: NSAttributedStringKey, range: Range<Int>)
10091
}
10192

10293
extension NSAttributedString {
10394
convenience init(string str: String, attributes: [Attribute])
10495
func withAttributes(_ attributes: [Attribute]) -> NSMutableAttributedString
10596
func withAttribute(_ attribute: Attribute) -> NSMutableAttributedString
10697
func attributedSubstring(from range: Range<Int>) -> NSAttributedString
107-
func attribute(_ attrName: Attribute.Name, at location: Int, effectiveRange range: NSRangePointer? = nil) -> Attribute?
98+
func swiftyAttribute(_ attrName: NSAttributedStringKey, at location: Int, effectiveRange range: NSRangePointer? = nil) -> Attribute?
10899
func attributes(in range: Range<Int>, options: NSAttributedString.EnumerationOptions = []) -> [([Attribute], Range<Int>)]
109100
func enumerateAttributes(in enumerationRange: Range<Int>, options: NSAttributedString.EnumerationOptions = [], using block: (_ attrs: [Attribute], _ range: Range<Int>, _ stop: UnsafeMutablePointer<ObjCBool>) -> Void)
110-
func enumerateAttribute(_ attrName: Attribute.Name, in enumerationRange: Range<Int>, options: NSAttributedString.EnumerationOptions = [], using block: (_ value: Any?, _ range: Range<Int>, _ stop: UnsafeMutablePointer<ObjCBool>) -> Void)
101+
func enumerateAttribute(_ attrName: NSAttributedStringKey, in enumerationRange: Range<Int>, options: NSAttributedString.EnumerationOptions = [], using block: (_ value: Any?, _ range: Range<Int>, _ stop: UnsafeMutablePointer<ObjCBool>) -> Void)
111102
}
112103

113104
extension String {

SwiftyAttributes.podspec

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Pod::Spec.new do |s|
33

44
s.name = "SwiftyAttributes"
5-
s.version = "3.2.0"
5+
s.version = "4.0.0"
66
s.summary = "A Swifty API for attributed strings."
77

88
s.description = <<-DESC
@@ -14,7 +14,7 @@ Pod::Spec.new do |s|
1414
s.homepage = "https://github.com/eddiekaiger/SwiftyAttributes"
1515
s.license = { :type => "MIT", :file => "LICENSE" }
1616
s.author = { "Eddie Kaiger" => "eddiekaiger@gmail.com" }
17-
s.source = { :git => "https://github.com/eddiekaiger/SwiftyAttributes.git", :tag => "v3.2.0" }
17+
s.source = { :git => "https://github.com/eddiekaiger/SwiftyAttributes.git", :tag => "v4.0.0" }
1818

1919
s.source_files = "SwiftyAttributes/Sources/common/*.swift"
2020
s.osx.source_files = "SwiftyAttributes/Sources/macOS/*.swift"

SwiftyAttributes.xcodeproj/project.pbxproj

+2-4
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,6 @@
631631
PRODUCT_BUNDLE_PACKAGE_TYPE = FMWK;
632632
PRODUCT_NAME = SwiftyAttributes;
633633
SKIP_INSTALL = YES;
634-
SWIFT_VERSION = 3.0;
635634
};
636635
name = Debug;
637636
};
@@ -652,7 +651,6 @@
652651
PRODUCT_BUNDLE_PACKAGE_TYPE = FMWK;
653652
PRODUCT_NAME = SwiftyAttributes;
654653
SKIP_INSTALL = YES;
655-
SWIFT_VERSION = 3.0;
656654
};
657655
name = Release;
658656
};
@@ -665,7 +663,6 @@
665663
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks";
666664
PRODUCT_BUNDLE_IDENTIFIER = com.eddiekaiger.SwiftyAttributesTests;
667665
PRODUCT_NAME = "$(TARGET_NAME)";
668-
SWIFT_VERSION = 3.0;
669666
};
670667
name = Debug;
671668
};
@@ -678,7 +675,6 @@
678675
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks";
679676
PRODUCT_BUNDLE_IDENTIFIER = com.eddiekaiger.SwiftyAttributesTests;
680677
PRODUCT_NAME = "$(TARGET_NAME)";
681-
SWIFT_VERSION = 3.0;
682678
};
683679
name = Release;
684680
};
@@ -731,6 +727,7 @@
731727
SUPPORTED_PLATFORMS = "watchsimulator watchos appletvos appletvsimulator iphoneos iphonesimulator macosx";
732728
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
733729
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
730+
SWIFT_VERSION = 4.0;
734731
TARGETED_DEVICE_FAMILY = "1,2,3,4";
735732
TVOS_DEPLOYMENT_TARGET = 9.0;
736733
VERSIONING_SYSTEM = "apple-generic";
@@ -780,6 +777,7 @@
780777
PRODUCT_BUNDLE_PACKAGE_TYPE = BNDL;
781778
SUPPORTED_PLATFORMS = "watchsimulator watchos appletvos appletvsimulator iphoneos iphonesimulator macosx";
782779
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
780+
SWIFT_VERSION = 4.0;
783781
TARGETED_DEVICE_FAMILY = "1,2,3,4";
784782
TVOS_DEPLOYMENT_TARGET = 9.0;
785783
VALIDATE_PRODUCT = YES;

SwiftyAttributes/Sources/common/Attribute+Sequence.swift

+24-13
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,37 @@
1212
A Sequence with an iterator of (String, Any) is equivalent to [String: Any]
1313
This is a simple syntactic workaround since we can't write "extension Dictionary where Key == String". Thanks Swift :)
1414
*/
15-
extension Sequence where Iterator.Element == (key: String, value: Any) {
16-
17-
/// Returns an array of `Attribute`s converted from the dictionary of attributes. Use this whenever you want to convert [String: Any] to [Attribute].
18-
public var swiftyAttributes: [Attribute] {
19-
return flatMap { name, value in
20-
if let attrName = Attribute.Name(rawValue: name) {
21-
return Attribute(name: attrName, foundationValue: value)
22-
} else {
23-
return nil
24-
}
15+
#if swift(>=4.0)
16+
extension Dictionary where Key == NSAttributedStringKey {
17+
18+
/// Returns an array of `Attribute`s converted from the dictionary of attributes. Use this whenever you want to convert [NSAttributeStringKey: Any] to [Attribute].
19+
public var swiftyAttributes: [Attribute] {
20+
return map(Attribute.init)
2521
}
22+
2623
}
24+
#else
25+
extension Sequence where Iterator.Element == (key: String, value: Any) {
2726

28-
}
27+
/// Returns an array of `Attribute`s converted from the dictionary of attributes. Use this whenever you want to convert [String: Any] to [Attribute].
28+
public var swiftyAttributes: [Attribute] {
29+
return flatMap { name, value in
30+
if let attrName = AttributeName(rawValue: name) {
31+
return Attribute(name: attrName, foundationValue: value)
32+
} else {
33+
return nil
34+
}
35+
}
36+
}
37+
38+
}
39+
#endif
2940

3041
extension Sequence where Iterator.Element == Attribute {
3142

3243
/// Returns the attribute dictionary required by Foundation's API for attributed strings. Use this whenever you need to convert [Attribute] to [String: Any].
33-
public var foundationAttributes: [String: Any] {
34-
return reduce([String: Any]()) { dictionary, attribute in
44+
public var foundationAttributes: [StringKey: Any] {
45+
return reduce([StringKey: Any]()) { dictionary, attribute in
3546
var dict = dictionary
3647
dict[attribute.keyName] = attribute.foundationValue
3748
return dict

SwiftyAttributes/Sources/common/Attribute.swift

+16-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ public typealias Shadow = NSShadow
2828
public typealias TextAttachment = NSTextAttachment
2929
#endif
3030

31+
#if swift(>=4.0)
32+
public typealias AttributeName = NSAttributedStringKey
33+
#else
34+
public typealias AttributeName = Attribute.Name
35+
#endif
36+
3137
/**
3238
Represents attributes that can be applied to NSAttributedStrings.
3339
*/
@@ -130,7 +136,7 @@ public enum Attribute {
130136
/// The writing directions to apply to the attributed string. See `WritingDirection` for values. Only available on iOS 9.0+.
131137
case writingDirections([WritingDirection])
132138

133-
init(name: Attribute.Name, foundationValue: Any) {
139+
init(name: AttributeName, foundationValue: Any) {
134140
func validate<Type>(_ val: Any) -> Type {
135141
assert(val is Type, "Attribute with name \(name.rawValue) must have a value of type \(Type.self)")
136142
return val as! Type
@@ -180,7 +186,7 @@ public enum Attribute {
180186
case .strokeWidth: ret = .strokeWidth(validateDouble(foundationValue))
181187
case .strikethroughColor: ret = .strikethroughColor(validate(foundationValue))
182188
case .strikethroughStyle: ret = .strikethroughStyle(StrikethroughStyle(rawValue: validate(foundationValue))!)
183-
case .textColor: ret = .textColor(validate(foundationValue))
189+
case .foregroundColor: ret = .textColor(validate(foundationValue))
184190
case .textEffect: ret = .textEffect(TextEffect(rawValue: validate(foundationValue))!)
185191
case .underlineColor: ret = .underlineColor(validate(foundationValue))
186192
case .underlineStyle: ret = .underlineStyle(UnderlineStyle(rawValue: validate(foundationValue))!)
@@ -195,9 +201,9 @@ public enum Attribute {
195201
}
196202

197203
/// The key name corresponding to the attribute.
198-
public var keyName: String {
204+
public var keyName: StringKey {
199205

200-
var name: Attribute.Name!
206+
var name: AttributeName!
201207

202208
// Bug in Swift prevents us from putting directives inside switch statements (https://bugs.swift.org/browse/SR-2)
203209

@@ -236,7 +242,7 @@ public enum Attribute {
236242
case .strokeWidth(_): name = .strokeWidth
237243
case .strikethroughColor(_): name = .strikethroughColor
238244
case .strikethroughStyle(_): name = .strikethroughStyle
239-
case .textColor(_): name = .textColor
245+
case .textColor(_): name = .foregroundColor
240246
case .textEffect(_): name = .textEffect
241247
case .underlineColor(_): name = .underlineColor
242248
case .underlineStyle(_): name = .underlineStyle
@@ -245,7 +251,11 @@ public enum Attribute {
245251
default: break
246252
}
247253

248-
return name.rawValue
254+
#if swift(>=4.0)
255+
return name
256+
#else
257+
return name.rawValue
258+
#endif
249259
}
250260

251261
// Convenience getter variable for the associated value of the attribute. See each case to determine the return type.

0 commit comments

Comments
 (0)