Skip to content

Commit 1fa1449

Browse files
committed
might be finished updating chapter 10 examples
1 parent 59b249e commit 1fa1449

File tree

12 files changed

+168
-78
lines changed

12 files changed

+168
-78
lines changed

bk2ch10p497downloadableFonts/ch23p770font2downloadableFont.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
322C69B11B94D72D0021A09F /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
2222
328BC5C5198ABB690062D99A /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
2323
C9DDA0D9180DC5E900E9E0CC /* ch23p770font2downloadableFont.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ch23p770font2downloadableFont.app; sourceTree = BUILT_PRODUCTS_DIR; };
24-
C9DDA0E4180DC5E900E9E0CC /* ch23p770font2downloadableFont-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ch23p770font2downloadableFont-Info.plist"; sourceTree = "<group>"; };
24+
C9DDA0E4180DC5E900E9E0CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2525
C9DDA0EF180DC5E900E9E0CC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
2626
C9DDA0F4180DC5E900E9E0CC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2727
/* End PBXFileReference section */
@@ -62,7 +62,7 @@
6262
C9DDA0F4180DC5E900E9E0CC /* Assets.xcassets */,
6363
322C69AF1B94D7060021A09F /* LaunchScreen.storyboard */,
6464
32299BE5198AD45900017BF4 /* SourceCodePro-Regular.ttf */,
65-
C9DDA0E4180DC5E900E9E0CC /* ch23p770font2downloadableFont-Info.plist */,
65+
C9DDA0E4180DC5E900E9E0CC /* Info.plist */,
6666
);
6767
name = ch23p770font1dynamicType;
6868
path = ch23p670font1dynamicType;

bk2ch10p507tabStops/TextTabTest.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@
245245
GCC_PRECOMPILE_PREFIX_HEADER = YES;
246246
GCC_PREFIX_HEADER = "TextTabTest/TextTabTest-Prefix.pch";
247247
INFOPLIST_FILE = "TextTabTest/TextTabTest-Info.plist";
248-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
248+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
249249
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
250250
ONLY_ACTIVE_ARCH = NO;
251251
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -266,7 +266,7 @@
266266
GCC_PRECOMPILE_PREFIX_HEADER = YES;
267267
GCC_PREFIX_HEADER = "TextTabTest/TextTabTest-Prefix.pch";
268268
INFOPLIST_FILE = "TextTabTest/TextTabTest-Info.plist";
269-
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
269+
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
270270
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
271271
ONLY_ACTIVE_ARCH = NO;
272272
PRODUCT_NAME = "$(TARGET_NAME)";

bk2ch10p507tabStops/TextTabTest/ViewController.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ class ViewController : UIViewController {
129129

130130
}
131131

132-
@available(iOS 10.0, *)
133132
extension ViewController : UITextViewDelegate {
134133
func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction:UITextItemInteraction) -> Bool {
135-
print(interaction.rawValue)
134+
print("attachment", interaction.rawValue)
135+
if interaction == .preview {return false}
136136
return true
137137
}
138138

139-
func textView(_ textView: UITextView, shouldInteractWith URL: Foundation.URL, in characterRange: NSRange, interaction:UITextItemInteraction) -> Bool {
140-
print(URL)
139+
func textView(_ textView: UITextView, shouldInteractWith url: Foundation.URL, in characterRange: NSRange, interaction:UITextItemInteraction) -> Bool {
140+
print("URL", url)
141141
print((textView.text as NSString).substring(with:characterRange))
142142
print(interaction.rawValue)
143143
return true

bk2ch10p522textFieldScrollView/ch23p805textFieldSliding/ViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class ViewController: UIViewController, UITextFieldDelegate {
8585
let (state, _) = keyboardState(for:d, in:self.scrollView)
8686
if state == .exiting {
8787
print("really hiding")
88-
// store original setup
88+
// restore original setup
8989
self.scrollView.contentOffset = self.oldOffset
9090
self.scrollView.scrollIndicatorInsets = self.oldIndicatorInset
9191
self.scrollView.contentInset = self.oldContentInset

bk2ch10p524keyboardAccessory/ch21p808keyboardAccessory/ViewController.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import UIKit
33

44
class ViewController: UIViewController, UITextFieldDelegate {
55
@IBOutlet var textFields : [UITextField]!
6-
var fr: UIResponder!
6+
var currentField: UITextField!
77
var accessoryView : UIView!
88

99
override func viewDidLoad() {
@@ -16,19 +16,19 @@ class ViewController: UIViewController, UITextFieldDelegate {
1616
}
1717

1818
func textFieldDidBeginEditing(_ tf: UITextField) {
19-
self.fr = tf // keep track of first responder
19+
self.currentField = tf // keep track of first responder
2020
tf.inputAccessoryView = self.accessoryView
2121
tf.keyboardAppearance = .dark
2222
}
2323

2424
func textFieldShouldReturn(_ tf: UITextField) -> Bool {
25-
self.fr = nil
25+
self.currentField = nil
2626
tf.resignFirstResponder()
2727
return true
2828
}
2929

3030
@objc func doNextButton(_ sender: Any) {
31-
var ix = self.textFields.index(of:self.fr as! UITextField)!
31+
var ix = self.textFields.index(of:self.currentField)!
3232
ix = (ix + 1) % self.textFields.count
3333
let v = self.textFields[ix]
3434
v.becomeFirstResponder()

bk2ch10p525InputViewTest/InputViewTest/ViewController.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,20 @@ class MyDoneButtonViewController : UIInputViewController {
5050
b.leadingAnchor.constraint(equalTo: iv.leadingAnchor),
5151
b.trailingAnchor.constraint(equalTo: iv.trailingAnchor),
5252
])
53-
54-
5553
}
5654

5755
@objc func doDone() {
5856
self.delegate?.view?.endEditing(false)
5957
}
58+
override func viewDidLayoutSubviews() {
59+
super.viewDidLayoutSubviews()
60+
print("did2")
61+
}
62+
63+
override func traitCollectionDidChange(_ prev: UITraitCollection?) {
64+
super.traitCollectionDidChange(prev)
65+
print("trait2")
66+
}
6067

6168

6269
}
@@ -79,6 +86,17 @@ class MyPickerViewController : UIInputViewController {
7986
p.trailingAnchor.constraint(equalTo: iv.trailingAnchor),
8087
])
8188
}
89+
90+
override func viewDidLayoutSubviews() {
91+
super.viewDidLayoutSubviews()
92+
print("did")
93+
}
94+
95+
override func traitCollectionDidChange(_ prev: UITraitCollection?) {
96+
super.traitCollectionDidChange(prev)
97+
print("trait")
98+
}
99+
82100
}
83101

84102
extension MyPickerViewController : UIPickerViewDelegate, UIPickerViewDataSource {
@@ -129,6 +147,7 @@ class ViewController: UIViewController {
129147
override func viewDidLoad() {
130148
super.viewDidLoad()
131149
self.tf.inputView = self.pvc.inputView
150+
// print(self.pvc.view === self.pvc.inputView) // yep
132151
(self.tf as! MyTextField).inputAccessoryViewController = mdbvc
133152
self.mdbvc.delegate = self // for dismissal
134153
}

bk2ch10p526textFieldDelegate/ch23p810textFieldDelegate/MyTextField.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class MyTextField: UITextField {
1616
nil, action:#selector(Dummy.dummy), for:.editingDidEndOnExit)
1717
}
1818

19+
1920
let list : [String:String] = {
2021
let path = Bundle.main.url(forResource:"abbreviations", withExtension:"txt")!
2122
let s = try! String(contentsOf:path)
@@ -33,28 +34,29 @@ class MyTextField: UITextField {
3334

3435

3536
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
36-
if action == #selector(expand),
37-
let r = self.selectedTextRange,
38-
let s = self.text(in:r) {
39-
return s.count == 2 && self.state(for:s) != nil
37+
if action == #selector(expand) {
38+
if let r = self.selectedTextRange, let s = self.text(in:r) {
39+
return (s.count == 2 && self.state(for:s) != nil)
40+
}
4041
}
4142
return super.canPerformAction(action, withSender:sender)
4243
}
4344

4445
@objc func expand(_ sender: Any?) {
45-
if let r = self.selectedTextRange, let s = self.text(in:r),
46-
let ss = self.state(for:s) {
47-
self.replace(r, withText:ss)
46+
if let r = self.selectedTextRange, let s = self.text(in:r) {
47+
if let ss = self.state(for:s) {
48+
self.replace(r, withText:ss)
49+
}
4850
}
4951
}
5052

5153
override func copy(_ sender:Any?) {
5254
super.copy(sender)
5355
let pb = UIPasteboard.general
54-
if let s = pb.string {
56+
if var s = pb.string {
5557
// ... alter s here ...
56-
let ss = s + "surprise!"
57-
pb.string = ss
58+
// s = s + "surprise!"
59+
pb.string = s
5860
}
5961
}
6062
}

bk2ch10p526textFieldDelegate/ch23p810textFieldDelegate/ViewController.swift

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ class ViewController: UIViewController, UITextFieldDelegate {
66

77
@IBOutlet var tf : UITextField!
88

9+
// how to make keyboard initially appear in Russian if enabled
10+
override var textInputMode: UITextInputMode? {
11+
print("get")
12+
// return super.textInputMode
13+
14+
for tim in UITextInputMode.activeInputModes {
15+
if tim.primaryLanguage == "ru-RU" {
16+
return tim
17+
}
18+
}
19+
print("super", super.textInputMode?.primaryLanguage as Any)
20+
return super.textInputMode
21+
}
22+
23+
924
override func viewDidLoad() {
1025
super.viewDidLoad()
1126

@@ -17,29 +32,44 @@ class ViewController: UIViewController, UITextFieldDelegate {
1732

1833
}
1934

35+
func beRed(_ textField : UITextField) {
36+
// user's text is always red, underlined
37+
if var md = textField.typingAttributes {
38+
let d : [String:Any] = [
39+
NSAttributedStringKey.foregroundColor.rawValue:
40+
UIColor.red,
41+
NSAttributedStringKey.underlineStyle.rawValue: NSUnderlineStyle.styleSingle.rawValue
42+
]
43+
md.merge(d) {_,new in new}
44+
textField.typingAttributes = md
45+
}
46+
}
47+
48+
func textFieldDidBeginEditing(_ textField: UITextField) {
49+
print(textField.textInputMode?.primaryLanguage as Any) // wrong
50+
51+
self.beRed(textField)
52+
}
53+
2054
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
21-
print("here '\(string)'")
55+
// print("here '\(string)'")
2256

2357
if string == "\n" {
2458
return true // otherwise, our automatic keyboard dismissal trick won't work
2559
}
2660

27-
// force user to type in red, underlined, lowercase only
28-
61+
// backspace
62+
if string.isEmpty {
63+
return true
64+
}
65+
// user can enter lowercase only
2966
let lc = string.lowercased()
30-
textField.text = (textField.text! as NSString)
31-
.replacingCharacters(in:range, with:lc)
32-
33-
// not very satisfactory but it does show the result
67+
textField.insertText(lc) // from UIKeyInput protocol
68+
69+
self.beRed(textField)
3470

35-
let md = (textField.typingAttributes! as NSDictionary).mutableCopy() as! NSMutableDictionary
36-
let d : [NSAttributedStringKey:Any] = [
37-
.foregroundColor:
38-
UIColor.red,
39-
.underlineStyle: NSUnderlineStyle.styleSingle.rawValue
40-
]
41-
md.addEntries(from:d)
42-
textField.typingAttributes = md.copy() as? [String:Any]
71+
print(textField.textInputMode?.primaryLanguage as Any) // right
72+
4373

4474
return false
4575

bk2ch10p532textViewAndKeyboard/ch23p811selfSizingTextField/ViewController.swift

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ func lend<T> (closure:(T)->()) -> T where T:NSObject {
99

1010
class ViewController: UIViewController, UITextViewDelegate {
1111
@IBOutlet var tv : UITextView!
12-
var keyboardShowing = false
12+
var scrollView : UIScrollView! {
13+
return self.tv
14+
}
15+
var oldContentInset = UIEdgeInsets.zero
16+
var oldIndicatorInset = UIEdgeInsets.zero
17+
var oldOffset = CGPoint.zero
1318

1419
override func viewDidLoad() {
1520
super.viewDidLoad()
@@ -38,48 +43,73 @@ class ViewController: UIViewController, UITextViewDelegate {
3843

3944
}
4045

41-
override var shouldAutorotate : Bool {
42-
return !self.keyboardShowing
43-
}
44-
4546
// as long as you play your part (adjust content offset),
46-
// iOS 8 will play its part (scroll cursor to visible)
47+
// iOS will play its part (scroll cursor to visible)
4748
// and we don't have to animate
4849

50+
// code identical to scroll view example, because a text view _is_ a scroll view
51+
52+
enum KeyboardState {
53+
case unknown
54+
case entering
55+
case exiting
56+
}
57+
58+
func keyboardState(for d:[AnyHashable:Any], in v:UIView?) -> (KeyboardState, CGRect?) {
59+
var rold = d[UIKeyboardFrameBeginUserInfoKey] as! CGRect
60+
var rnew = d[UIKeyboardFrameEndUserInfoKey] as! CGRect
61+
var ks : KeyboardState = .unknown
62+
var newRect : CGRect? = nil
63+
if let v = v {
64+
let co = UIScreen.main.coordinateSpace
65+
rold = co.convert(rold, to:v)
66+
rnew = co.convert(rnew, to:v)
67+
newRect = rnew
68+
if !rold.intersects(v.bounds) && rnew.intersects(v.bounds) {
69+
ks = .entering
70+
}
71+
if rold.intersects(v.bounds) && !rnew.intersects(v.bounds) {
72+
ks = .exiting
73+
}
74+
}
75+
return (ks, newRect)
76+
}
77+
4978
@objc func keyboardShow(_ n:Notification) {
50-
if self.keyboardShowing {
51-
return
79+
let d = n.userInfo!
80+
let (state, rnew) = keyboardState(for:d, in:self.scrollView)
81+
if state == .entering {
82+
print("really showing")
83+
self.oldContentInset = self.scrollView.contentInset
84+
self.oldIndicatorInset = self.scrollView.scrollIndicatorInsets
85+
self.oldOffset = self.scrollView.contentOffset
5286
}
53-
self.keyboardShowing = true
54-
55-
5687
print("show")
57-
58-
let d = n.userInfo!
59-
var r = d[UIKeyboardFrameEndUserInfoKey] as! CGRect
60-
r = self.tv.convert(r, from:nil)
61-
self.tv.contentInset.bottom = r.size.height
62-
self.tv.scrollIndicatorInsets.bottom = r.size.height
63-
64-
65-
88+
// no need to scroll, as the scroll view will do it for us
89+
// so all we have to do is adjust the inset
90+
if let rnew = rnew {
91+
let h = rnew.intersection(self.scrollView.bounds).height
92+
self.scrollView.contentInset.bottom = h
93+
self.scrollView.scrollIndicatorInsets.bottom = h
94+
}
6695
}
6796

6897
@objc func keyboardHide(_ n:Notification) {
69-
if !self.keyboardShowing {
70-
return
98+
let d = n.userInfo!
99+
let (state, _) = keyboardState(for:d, in:self.scrollView)
100+
if state == .exiting {
101+
print("really hiding")
102+
// restore original setup
103+
// we _don't_ do this; let the text view position itself
104+
// self.scrollView.contentOffset = self.oldOffset
105+
self.scrollView.scrollIndicatorInsets = self.oldIndicatorInset
106+
self.scrollView.contentInset = self.oldContentInset
71107
}
72-
self.keyboardShowing = false
73-
74-
print("hide")
75-
76-
self.tv.contentInset = .zero
77-
self.tv.scrollIndicatorInsets = .zero
78-
79-
80108
}
81109

82-
func doDone(_ sender: Any) {
110+
111+
112+
@objc func doDone(_ sender: Any) {
83113
self.view.endEditing(false)
84114
}
85115

0 commit comments

Comments
 (0)