Skip to content

Commit 531b8ea

Browse files
committed
Merge develop into master
2 parents 13daed5 + 30b129a commit 531b8ea

File tree

11 files changed

+183
-13
lines changed

11 files changed

+183
-13
lines changed

ThunderTable.xcodeproj/project.pbxproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@
413413
B14F944D20444E810014F694 = {
414414
CreatedOnToolsVersion = 9.2;
415415
DevelopmentTeam = 25H7BM6YWK;
416+
LastSwiftMigration = 1120;
416417
ProvisioningStyle = Automatic;
417418
};
418419
B17BAA311D89639100844421 = {
@@ -592,7 +593,7 @@
592593
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
593594
PRODUCT_BUNDLE_IDENTIFIER = com.3sidedcube.ThunderTableDemo;
594595
PRODUCT_NAME = "$(TARGET_NAME)";
595-
SWIFT_VERSION = 4.0;
596+
SWIFT_VERSION = 5.0;
596597
TARGETED_DEVICE_FAMILY = "1,2";
597598
};
598599
name = Debug;
@@ -614,7 +615,7 @@
614615
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
615616
PRODUCT_BUNDLE_IDENTIFIER = com.3sidedcube.ThunderTableDemo;
616617
PRODUCT_NAME = "$(TARGET_NAME)";
617-
SWIFT_VERSION = 4.0;
618+
SWIFT_VERSION = 5.0;
618619
TARGETED_DEVICE_FAMILY = "1,2";
619620
};
620621
name = Release;
@@ -751,7 +752,7 @@
751752
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
752753
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
753754
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
754-
MARKETING_VERSION = 1.3.4;
755+
MARKETING_VERSION = 1.3.5;
755756
PRODUCT_BUNDLE_IDENTIFIER = com.threesidedcube.ThunderTable;
756757
PRODUCT_NAME = "$(TARGET_NAME)";
757758
SKIP_INSTALL = YES;
@@ -776,7 +777,7 @@
776777
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
777778
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
778779
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
779-
MARKETING_VERSION = 1.3.4;
780+
MARKETING_VERSION = 1.3.5;
780781
PRODUCT_BUNDLE_IDENTIFIER = com.threesidedcube.ThunderTable;
781782
PRODUCT_NAME = "$(TARGET_NAME)";
782783
SKIP_INSTALL = YES;

ThunderTable/InputSliderRow.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,23 @@ open class InputSliderRow: InputTableRow {
2020
return InputSliderViewCell.self
2121
}
2222

23+
// Defines whether to group the label and slider as a single accessibility element
24+
/// - Note: Defaults to true!
25+
public var accessibilityGroupLabelsAndSlider = true
26+
27+
/// The minimum value that can be chosen by the slider
2328
open var minValue: Float
2429

30+
/// The maximum value that can be chosen by the slider
2531
open var maxValue: Float
26-
32+
33+
/// The interval at which the slider increments or decrements
2734
open var interval: Float
2835

36+
/// A closure that will be called in order to format the accessibility value for the slider.
37+
/// This can be used to for example make the accessibility value read "2 miles" rather than simply "2"
38+
open var accessibilityValueFormatter: ((Float) -> String)?
39+
2940
public init(title: String?, minValue: Float, maxValue: Float, id: String, required: Bool) {
3041

3142
self.minValue = minValue
@@ -44,10 +55,13 @@ open class InputSliderRow: InputTableRow {
4455
super.configure(cell: cell, at: indexPath, in: tableViewController)
4556

4657
updateTargetsAndSelectors(for: sliderCell.slider)
58+
sliderCell.accessibilityValueFormatter = accessibilityValueFormatter
4759
sliderCell.slider.addTarget(self, action: #selector(handleChange(sender:)), for: .valueChanged)
4860
sliderCell.slider.addTarget(sliderCell, action: #selector(InputSliderViewCell.updateLabel(sender:)), for: .valueChanged)
4961

5062
sliderCell.cellTextLabel?.isHidden = title == nil
63+
64+
sliderCell.accessibilityGroupLabelsAndSlider = accessibilityGroupLabelsAndSlider
5165

5266
sliderCell.slider.interval = interval
5367
sliderCell.slider.minimumValue = minValue

ThunderTable/InputSliderViewCell.swift

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,27 @@ public class IntervalSlider: UISlider {
8585

8686
return finalValue
8787
}
88+
89+
public override func accessibilityIncrement() {
90+
let nextValue = correctedValue + interval
91+
let correctedNextValue = min(nextValue, maximumValue)
92+
self.setValue(correctedNextValue, animated: true)
93+
sendActions(for: .valueChanged)
94+
}
95+
96+
public override func accessibilityDecrement() {
97+
let nextValue = correctedValue - interval
98+
let correctedNextValue = max(nextValue, minimumValue)
99+
self.setValue(correctedNextValue, animated: true)
100+
sendActions(for: .valueChanged)
101+
}
102+
103+
public override var accessibilityValue: String? {
104+
get {
105+
return "\(correctedValue)"
106+
}
107+
set { }
108+
}
88109
}
89110

90111
open class InputSliderViewCell: TableViewCell {
@@ -93,7 +114,58 @@ open class InputSliderViewCell: TableViewCell {
93114

94115
@IBOutlet weak public var slider: IntervalSlider!
95116

117+
/// A closure that will be called in order to format the accessibility value for the slider.
118+
/// This can be used to for example make the accessibility value read "2 miles" rather than simply "2"
119+
public var accessibilityValueFormatter: ((Float) -> String)?
120+
121+
// Defines whether to group the label and slider as a single accessibility element
122+
/// - Note: Defaults to true!
123+
public var accessibilityGroupLabelsAndSlider = true {
124+
didSet {
125+
isAccessibilityElement = accessibilityGroupLabelsAndSlider
126+
}
127+
}
128+
96129
@objc open func updateLabel(sender: IntervalSlider) {
97130
valueLabel.text = "\(sender.correctedValue)"
98131
}
132+
133+
open override var accessibilityTraits: UIAccessibilityTraits {
134+
get {
135+
return slider.accessibilityTraits
136+
}
137+
set {
138+
139+
}
140+
}
141+
142+
open override var accessibilityValue: String? {
143+
get {
144+
return accessibilityValueFormatter?(slider.correctedValue) ?? slider.accessibilityValue
145+
}
146+
set { }
147+
}
148+
149+
open override var accessibilityLabel: String? {
150+
get {
151+
// We don't return the value label's text here as that is covered by `accessibilityLabel`
152+
// and so would be read twice if we put it in this array
153+
return [
154+
cellTextLabel?.accessibilityLabel ?? cellTextLabel?.text,
155+
cellDetailLabel?.accessibilityLabel ?? cellDetailLabel?.text
156+
].compactMap({
157+
guard let text = $0, !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return nil }
158+
return text
159+
}).joined(separator: ",")
160+
}
161+
set { }
162+
}
163+
164+
open override func accessibilityDecrement() {
165+
slider.accessibilityDecrement()
166+
}
167+
168+
open override func accessibilityIncrement() {
169+
slider.accessibilityIncrement()
170+
}
99171
}

ThunderTable/InputSwitchRow.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@
88

99
import UIKit
1010

11+
/// An input row which provides a title, subtitle, and `UISwitch` in it's UI
1112
open class InputSwitchRow: InputTableRow {
1213

1314
public var isEnabled = true
1415

1516
public var isUserInteractionEnabled = true
17+
18+
/// Defines whether to group the label and switch as a single accessibility element
19+
/// - Note: Defaults to true!
20+
public var accessibilityGroupLabelsAndSwitch: Bool = true
1621

1722
override open var cellClass: UITableViewCell.Type? {
1823
return InputSwitchViewCell.self
@@ -22,6 +27,7 @@ open class InputSwitchRow: InputTableRow {
2227

2328
super.init(id: id, required: false)
2429

30+
isAccessibilityElement = true
2531
self.title = title
2632
self.subtitle = subtitle
2733
self.image = image
@@ -41,6 +47,8 @@ open class InputSwitchRow: InputTableRow {
4147
} else {
4248
switchCell.switch.isOn = false
4349
}
50+
51+
switchCell.accessibilityGroupLabelsAndSwitch = accessibilityGroupLabelsAndSwitch
4452

4553
switchCell.switch.isEnabled = isEnabled
4654
switchCell.switch.isUserInteractionEnabled = isUserInteractionEnabled

ThunderTable/InputSwitchViewCell.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,35 @@ import UIKit
1111
open class InputSwitchViewCell: TableViewCell {
1212

1313
@IBOutlet weak public var `switch`: UISwitch!
14+
15+
/// Defines whether to group the label and switch as a single accessibility element
16+
/// - Note: Defaults to true!
17+
public var accessibilityGroupLabelsAndSwitch = true {
18+
didSet {
19+
isAccessibilityElement = accessibilityGroupLabelsAndSwitch
20+
}
21+
}
1422

23+
//MARK: - Accessibility
24+
25+
open override var accessibilityTraits: UIAccessibilityTraits {
26+
get {
27+
return `switch`.accessibilityTraits
28+
}
29+
set { }
30+
}
31+
32+
open override var accessibilityValue: String? {
33+
get {
34+
return `switch`.accessibilityValue
35+
}
36+
set { }
37+
}
38+
39+
open override func accessibilityActivate() -> Bool {
40+
self.switch.setOn(!self.switch.isOn, animated: true)
41+
self.switch.sendActions(for: .valueChanged)
42+
UIAccessibility.post(notification: .announcement, argument: self.switch.accessibilityValue)
43+
return true
44+
}
1545
}

ThunderTable/TableRow.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,16 @@ public protocol Row {
3131

3232
/// A string to be displayed as the title for the row
3333
var title: String? { get }
34+
35+
/// A string to be used as the accessibility label for the row title
36+
var accessibilityTitle: String? { get }
3437

3538
/// A string to be displayed as the subtitle for the row
3639
var subtitle: String? { get }
3740

41+
/// A string to be used as the accessibility label for the row subtitle
42+
var accessibilitySubtitle: String? { get }
43+
3844
/// An image to be displayed in the row
3945
var image: UIImage? { get set }
4046

@@ -154,6 +160,14 @@ extension Row {
154160
return nil
155161
}
156162

163+
public var accessibilityTitle: String? {
164+
return nil
165+
}
166+
167+
public var accessibilitySubtitle: String? {
168+
return nil
169+
}
170+
157171
public var image: UIImage? {
158172
get { return nil }
159173
set {}
@@ -226,13 +240,17 @@ open class TableRow: Row {
226240
public var editHandler: EditHandler?
227241

228242
open var title: String?
243+
244+
open var accessibilityTitle: String?
229245

230246
open var titleTextColor: UIColor = ThemeManager.shared.theme.cellTitleColor
231247

232248
open var subtitleTextColor: UIColor = ThemeManager.shared.theme.cellDetailColor
233249

234250
open var subtitle: String?
235251

252+
open var accessibilitySubtitle: String?
253+
236254
open var image: UIImage?
237255

238256
open var imageSize: CGSize?

ThunderTable/TableViewController.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,7 @@ open class TableViewController: UITableViewController, UIContentSizeCategoryAdju
162162
strongSelf.accessibilitySettingsDidChange()
163163
}
164164

165-
// Notification names that it makes sense to redraw on.
166-
// Note that these differ from `self.accessibilityRedrawNotificationNames`. It is easier, and not too
167-
// expensive to manage which notifications trigger a refresh at the point of receiving the notification
168-
// rather than risking double-adding or double-removing the observers!
169-
let accessibilityNotifications: [Notification.Name] = [
165+
var accessibilityNotifications: [Notification.Name] = [
170166
UIAccessibility.darkerSystemColorsStatusDidChangeNotification,
171167
UIAccessibility.assistiveTouchStatusDidChangeNotification,
172168
UIAccessibility.boldTextStatusDidChangeNotification,
@@ -176,6 +172,14 @@ open class TableViewController: UITableViewController, UIContentSizeCategoryAdju
176172
UIAccessibility.reduceMotionStatusDidChangeNotification,
177173
UIAccessibility.reduceTransparencyStatusDidChangeNotification
178174
]
175+
176+
// Notification names that it makes sense to redraw on.
177+
// Note that these differ from `self.accessibilityRedrawNotificationNames`. It is easier, and not too
178+
// expensive to manage which notifications trigger a refresh at the point of receiving the notification
179+
// rather than risking double-adding or double-removing the observers!
180+
if #available(iOS 11.0, *) {
181+
accessibilityNotifications.append(UIAccessibility.voiceOverStatusDidChangeNotification)
182+
}
179183

180184
accessibilityObservers = accessibilityNotifications.map({ (notificationName) -> Any in
181185
return NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: .main, using: { [weak self] (notification) in
@@ -277,12 +281,24 @@ open class TableViewController: UITableViewController, UIContentSizeCategoryAdju
277281
textLabel?.text = nil
278282
}
279283

284+
if let rowAccessibilityTitle = row.accessibilityTitle {
285+
textLabel?.accessibilityLabel = rowAccessibilityTitle
286+
} else {
287+
textLabel?.accessibilityLabel = nil
288+
}
289+
280290
if let rowSubtitle = row.subtitle {
281291
detailLabel?.text = rowSubtitle
282292
} else {
283293
detailLabel?.text = nil
284294
}
285295

296+
if let rowAccessibilitySubtitle = row.accessibilitySubtitle {
297+
detailLabel?.accessibilityLabel = rowAccessibilitySubtitle
298+
} else {
299+
detailLabel?.accessibilityLabel = nil
300+
}
301+
286302
if let rowImage = row.image {
287303
imageView?.image = rowImage
288304
} else {

ThunderTableDemo/AppDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1414
var window: UIWindow?
1515

1616

17-
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
17+
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
1818
// Override point for customization after application launch.
1919
return true
2020
}

ThunderTableDemo/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,7 @@
5454
<string>UIInterfaceOrientationLandscapeLeft</string>
5555
<string>UIInterfaceOrientationLandscapeRight</string>
5656
</array>
57+
<key>UIUserInterfaceStyle</key>
58+
<string>Light</string>
5759
</dict>
5860
</plist>

ThunderTableDemo/Models/CNContact+Section.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension CNContact: Section {
2222

2323
public var rows: [Row] {
2424

25-
var _rows: [Row] = [
25+
let _rows: [Row] = [
2626
TableRow(title: CNContact.localizedString(forKey: CNContactGivenNameKey), subtitle: givenName, image: nil, selectionHandler: nil),
2727
TableRow(title: CNContact.localizedString(forKey: CNContactFamilyNameKey), subtitle: familyName, image: nil, selectionHandler: nil)
2828
]

0 commit comments

Comments
 (0)