{"id":5577,"date":"2022-04-24T10:56:33","date_gmt":"2022-04-24T02:56:33","guid":{"rendered":"http:\/\/123.57.164.21\/?p=5577"},"modified":"2022-04-24T10:56:33","modified_gmt":"2022-04-24T02:56:33","slug":"swiftui-textfield-%e8%bf%9b%e9%98%b6-%e4%ba%8b%e4%bb%b6%e3%80%81%e7%84%a6%e7%82%b9%e3%80%81%e9%94%ae%e7%9b%98","status":"publish","type":"post","link":"https:\/\/92it.top\/?p=5577","title":{"rendered":"SwiftUI TextField \u8fdb\u9636 \u2014\u2014 \u4e8b\u4ef6\u3001\u7126\u70b9\u3001\u952e\u76d8"},"content":{"rendered":"\n<p>\u672c\u6587\u5c06\u63a2\u8ba8\u6d89\u53ca SwiftUI TextField \u7684\u4e8b\u4ef6\u3001\u7126\u70b9\u5207\u6362\u3001\u952e\u76d8\u8bbe\u7f6e\u7b49\u76f8\u5173\u7684\u7ecf\u9a8c\u3001\u6280\u5de7\u548c\u6ce8\u610f\u4e8b\u9879\u3002<\/p>\n\n\n\n<p>\u8f6c\u8f7d\uff1ahttps:\/\/www.fatbobman.com\/posts\/textfield-event-focus-keyboard\/<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">\u4e8b\u4ef6<\/h6>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><strong>onEditingChanged<\/strong><\/p>\n\n\n\n<p>    \u5f53 TextField \u83b7\u5f97\u7126\u70b9\u65f6\uff08\u8fdb\u5165\u53ef\u7f16\u8f91\u72b6\u6001\uff09\uff0c<code>onEditingChanged<\/code>\u5c06\u8c03\u7528\u7ed9\u5b9a\u7684\u65b9\u6cd5\u5e76\u4f20\u9012<code>true<\/code>\u503c\uff1b\u5f53 TextField \u5931\u53bb\u7126\u70b9\u65f6\uff0c\u518d\u6b21\u8c03\u7528\u65b9\u6cd5\u5e76\u4f20\u9012<code>false<\/code>\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnEditingChangedDemo:View{\n    @State var name = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text:$name,onEditingChanged: getFocus)\n        }\n    }\n\n    func getFocus(focused:Bool) {\n        print(\"get focus:\\(focused ? \"true\" : \"false\")\")\n    }\n}\n<\/pre>\n\n\n\n<p>    \u8be5\u53c2\u6570\u7684\u540d\u79f0\u5bb9\u6613\u8ba9\u4f7f\u7528\u8005\u4ea7\u751f\u6b67\u4e49\uff0c<strong>\u4e0d\u8981\u4f7f\u7528<code>onEditingChanged<\/code>\u5224\u65ad\u7528\u6237\u662f\u5426\u8f93\u5165\u4e86\u5185\u5bb9<\/strong>\u3002<\/p>\n\n\n\n<p>    \u5728 iOS 15 \u4e2d\uff0c\u65b0\u589e\u7684\u652f\u6301 ParseableFormatStyle \u7684\u6784\u9020\u65b9\u6cd5\u4e0d\u63d0\u4f9b\u8be5\u53c2\u6570\uff0c\u56e0\u6b64\u5bf9\u4e8e\u4f7f\u7528\u65b0 Formatter \u7684 TextField \u9700\u8981\u4f7f\u7528\u5176\u4ed6\u7684\u624b\u6bb5\u6765\u5224\u65ad\u662f\u5426\u83b7\u5f97\u6216\u5931\u53bb\u7126\u70b9\u3002<\/p>\n\n\n\n<p id=\"onCommit\"><strong>onCommit<\/strong><\/p>\n\n\n\n<p>    \u5f53\u7528\u6237\u5728\u8f93\u5165\u8fc7\u7a0b\u4e2d\u6309\u4e0b\uff08\u6216\u70b9\u51fb\uff09<code>return<\/code>\u952e\u65f6\u89e6\u53d1 onCommit\uff08\u65e0\u6cd5\u901a\u8fc7\u4ee3\u7801\u6a21\u62df\u89e6\u53d1\uff09\u3002<strong>\u5982\u679c\u7528\u6237\u6ca1\u6709\u70b9\u51fb<code>return<\/code>\u952e\uff08\u6bd4\u5982\u76f4\u63a5\u5207\u6362\u81f3\u5176\u4ed6\u7684 TextField\uff09\uff0c\u5c06\u4e0d\u4f1a\u89e6\u53d1 onCommit<\/strong>\u3002\u89e6\u53d1 onCommit \u7684\u540c\u65f6\uff0cTextField \u4e5f\u5c06\u5931\u53bb\u7126\u70b9\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnCommitDemo:View{\n    @State var name = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text: $name,onCommit: {print(\"commit\")})\n        }\n    }\n}\n<\/pre>\n\n\n\n<p>\u5982\u679c\u4f60\u9700\u8981\u5728\u7528\u6237\u8f93\u5165\u540e\u5bf9\u7528\u6237\u7684\u5f55\u5165\u5185\u5bb9\u8fdb\u884c\u5224\u65ad\uff0c\u6700\u597d\u7ed3\u5408 onCommit \u548c onEdtingChanged \u4e00\u8d77\u6765\u5904\u7406\u3002\u5982\u679c\u60f3\u5b9e\u65f6\u7684\u5bf9\u7528\u6237\u7684\u5f55\u5165\u6570\u636e\u8fdb\u884c\u5904\u7406\uff0c\u8bf7\u53c2\u9605 <a href=\"https:\/\/www.fatbobman.com\/posts\/textfield-1\/\">SwiftUI TextField \u8fdb\u9636\u2014\u2014\u683c\u5f0f\u4e0e\u6821\u9a8c<\/a>\u3002<\/p>\n\n\n\n<p>onCommit \u5bf9 SecureField \u540c\u6837\u9002\u7528\u3002<\/p>\n\n\n\n<p>\u5728 iOS 15 \u4e2d\uff0c\u65b0\u589e\u7684\u652f\u6301 ParseableFormatStyle \u7684\u6784\u9020\u65b9\u6cd5\u4e0d\u63d0\u4f9b\u8be5\u53c2\u6570\uff0c\u53ef\u4ee5\u4f7f\u7528\u65b0\u589e\u7684 onSubmit \u6765\u5b9e\u73b0\u540c\u6837\u6548\u679c\u3002<\/p>\n\n\n\n<p><strong>onSubmit<\/strong><\/p>\n\n\n\n<p>onSubmit \u662fSwiftUI 3.0 \u7684\u65b0\u589e\u529f\u80fd\u3002onCommit \u548c onEditingChanged \u662f\u6bcf\u4e2a TextField \u5bf9\u81ea\u8eab\u72b6\u6001\u7684\u63cf\u8ff0\uff0conSubmit \u5219\u53ef\u4ee5\u4ece\u66f4\u9ad8\u7684\u89d2\u5ea6\u5bf9\u89c6\u56fe\u4e2d\u591a\u4e2a TextField \u8fdb\u884c\u7edf\u4e00\u7ba1\u7406\u548c\u8c03\u5ea6\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ onSubmit \u7684\u5b9a\u4e49\nextension View {\n    public func onSubmit(of triggers: SubmitTriggers = .text, _ action: @escaping (() -> Void)) -> some View\n}<\/pre>\n\n\n\n<p>\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u5b9e\u73b0\u540c\u4e0a\u9762 onCommit \u4e00\u6837\u7684\u884c\u4e3a\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnSubmitDemo:View{\n    @State var name = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text: $name)\n                .onSubmit {\n                    print(\"commit\")\n                }\n        }\n    }\n}<\/pre>\n\n\n\n<p>onSubmit \u7684\u89e6\u53d1\u6761\u4ef6\u540c onCommit \u4e00\u81f4\uff0c\u9700\u8981\u7528\u6237\u4e3b\u52a8\u70b9\u51fb<code>return<\/code>\u3002<\/p>\n\n\n\n<p>onSubmit \u540c\u6837\u9002\u7528\u4e8e SecureField\u3002<\/p>\n\n\n\n<p id=\"\u4f5c\u7528\u57df\u53ca\u5d4c\u5957\"><strong>\u4f5c\u7528\u57df\u53ca\u5d4c\u5957<\/strong><\/p>\n\n\n\n<p>onSubmit \u80cc\u540e\u7684\u662f\u901a\u8fc7\u8bbe\u7f6e\u73af\u5883\u503c<code>TriggerSubmitAction<\/code>\uff08\u5c1a\u672a\u5bf9\u5f00\u53d1\u8005\u5f00\u653e\uff09\u6765\u5b9e\u73b0\u7684\uff0c\u56e0\u6b64 onSubmit \u662f\u6709\u4f5c\u7528\u57df\u8303\u56f4\u7684\uff08\u53ef\u5728\u89c6\u56fe\u6811\u5411\u4e0a\u4f20\u9012\uff09\uff0c\u4e14\u53ef\u5d4c\u5957\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnSubmitDemo: View {\n    @State var text1 = \"\"\n    @State var text2 = \"\"\n    @State var text3 = \"\"\n    var body: some View {\n        Form {\n            Group {\n                TextField(\"text1\", text: $text1)\n                    .onSubmit { print(\"text1 commit\") }\n                TextField(\"text2\", text: $text2)\n                    .onSubmit { print(\"text2 commit\") }\n            }\n            .onSubmit { print(\"textfield in group commit\") }\n            TextField(\"text3\", text: $text3)\n                .onSubmit { print(\"text3 commit\") }\n        }\n        .onSubmit { print(\"textfield in form commit1\") }\n        .onSubmit { print(\"textfield in form commit2\") }\n    }\n}\n<\/pre>\n\n\n\n<p>\u5f53 TextField\uff08text1\uff09 commit \u65f6\uff0c\u63a7\u5236\u53f0\u8f93\u51fa\u4e3a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">textfield in form commit2\ntextfield in form commit1\ntextfield in group commit\ntext1 commit\n<\/pre>\n\n\n\n<p>\u8bf7\u6ce8\u610f\uff0c<strong>\u8c03\u7528\u7684\u987a\u5e8f\u662f\u4ece\u5916\u5c42\u5411\u5185\u7684<\/strong>\u3002<\/p>\n\n\n\n<p><strong>\u9650\u5b9a\u4f5c\u7528\u57df<\/strong><\/p>\n\n\n\n<p>\u53ef\u4ee5\u4f7f\u7528<code>submitScope<\/code>\u963b\u65ad\u4f5c\u7528\u57df\uff08\u9650\u5236\u5728\u89c6\u56fe\u6811\u4e0a\u8fdb\u4e00\u6b65\u4f20\u9012\uff09\u3002\u6bd4\u5982\uff0c\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u5728 Group \u540e\u9762\u6dfb\u52a0<code>submitScope<\/code><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   Group {\n                TextField(\"text1\", text: $text1)\n                    .onSubmit { print(\"text1 commit\") }\n                TextField(\"text2\", text: $text2)\n                    .onSubmit { print(\"text2 commit\") }\n            }\n            .submitScope()  \/\/ \u963b\u65ad\u4f5c\u7528\u57df\n            .onSubmit { print(\"textfield in group commit\") }<\/pre>\n\n\n\n<p>\u5f53 TextField1 commit \u65f6\uff0c\u63a7\u5236\u53f0\u8f93\u51fa\u4e3a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">text1 commit<\/pre>\n\n\n\n<p>\u6b64\u65f6 onSubmit \u7684\u4f5c\u7528\u57df\u5c06\u88ab\u9650\u5b9a\u5728 Group \u4e4b\u5185\u3002<\/p>\n\n\n\n<p>\u5f53\u89c6\u56fe\u4e2d\u6709\u591a\u4e2a TextField \u65f6\uff0c\u901a\u8fc7 onSubmit \u548c FocusState\uff08\u4e0b\u6587\u4ecb\u7ecd\uff09\u7684\u7ed3\u5408\uff0c\u53ef\u4ee5\u7ed9\u7528\u6237\u5e26\u6765\u975e\u5e38\u597d\u7684\u4f7f\u7528\u4f53\u9a8c\u3002<\/p>\n\n\n\n<p><strong>\u5bf9 searchable \u7684\u652f\u6301<\/strong><\/p>\n\n\n\n<p>iOS 15 \u65b0\u589e\u7684\u641c\u7d22\u6846\u5728\u70b9\u51fb<code>return<\/code>\u65f6\u540c\u6837\u4f1a\u89e6\u53d1 onSubmit\uff0c\u4e0d\u8fc7\u9700\u8981\u5c06 triggers \u8bbe\u7f6e\u4e3a search\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnSubmitForSearchableDemo:View{\n    @State var name = \"\"\n    @State var searchText = \"\"\n    var body: some View{\n        NavigationView{\n            Form{\n                TextField(\"name:\",text:$name)\n                    .onSubmit {print(\"textField commit\")}\n            }\n            .searchable(text: $searchText)\n            .onSubmit(of: .search) { \/\/ \n                print(\"searchField commit\")\n            }\n        }\n    }\n}\n<\/pre>\n\n\n\n<p>\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cSubmitTriggers \u4e3a <strong>OptionSet<\/strong> \u7c7b\u578b\uff0conSubmit \u5bf9\u4e8e<code>SubmitTriggers<\/code>\u5185\u5305\u542b\u7684\u503c\u4f1a\u901a\u8fc7\u73af\u5883\u5728\u89c6\u56fe\u6811\u4e2d\u6301\u7eed\u4f20\u9012\u3002\u5f53\u63a5\u53d7\u5230\u7684<code>SubmitTriggers<\/code>\u503c\u4e0d\u5305\u542b\u5728 onSubmit \u8bbe\u7f6e\u7684<code>SubmitTriggers<\/code>\u65f6\uff0c\u4f20\u9012\u5c06\u7ec8\u6b62\u3002\u7b80\u5355\u7684\u8bf4\uff0c<code>onSubmit(of:.search)<\/code>\u5c06\u963b\u65ad TextFiled \u4ea7\u751f\u7684 commit \u72b6\u6001\u3002\u53cd\u4e4b\u4ea6\u7136\u3002<\/p>\n\n\n\n<p>\u4f8b\u5982\uff0c\u4e0a\u9762\u7684\u4ee3\u7801\uff0c\u5982\u679c\u6211\u4eec\u5728 searchable \u540e\u9762\u518d\u6dfb\u52a0\u4e00\u4e2a<code>onSubmt(of:.text)<\/code>, \u5c06\u65e0\u6cd5\u5bf9 TextField \u7684 commit \u4e8b\u4ef6\u8fdb\u884c\u54cd\u5e94\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> .searchable(text: $searchText)\n            .onSubmit(of: .search) {\n                print(\"searchField commit1\")\n            }\n            .onSubmit {print(\"textField commit\")} \/\/\u65e0\u6cd5\u89e6\u53d1\uff0c\u88ab search \u963b\u65ad <\/pre>\n\n\n\n<p>\u56e0\u6b64\u5f53\u540c\u65f6\u5bf9 TextFiled \u4ee5\u53ca\u641c\u7d22\u6846\u505a\u5904\u7406\u65f6\uff0c\u9700\u8981\u7279\u522b\u6ce8\u610f\u5b83\u4eec\u4e4b\u95f4\u7684\u8c03\u7528\u987a\u5e8f\u3002<\/p>\n\n\n\n<p>\u53ef\u4ee5\u901a\u8fc7\u5982\u4e0b\u4ee3\u7801\u5728\u4e00\u4e2a onSubmit \u4e2d\u540c\u65f6\u652f\u6301 TextField \u548c\u641c\u7d22\u6846\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">.onSubmit(of: [.text, .search]) {\n  print(\"Something has been submitted\")\n}\n<\/pre>\n\n\n\n<p>\u4e0b\u9762\u4ee3\u7801\u7531\u4e8e<code>onSubmit(of:search)<\/code>\u88ab\u653e\u7f6e\u5728<code>searchable<\/code>\u4e4b\u524d\u4e5f\u4e00\u6837\u4e0d\u4f1a\u89e6\u53d1\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> NavigationView{\n            Form{\n                TextField(\"name:\",text:$name)\n                    .onSubmit {print(\"textField commit\")}\n            }\n            .onSubmit(of: .search) { \/\/ \u4e0d\u4f1a\u89e6\u53d1\n                print(\"searchField commit1\")\n            }\n            .searchable(text: $searchText)\n        }\n<\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">\u7126\u70b9<\/h6>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>\u5728 iOS 15 \/ macOS Moterey\u4e4b\u524d\uff0cSwiftUI \u6ca1\u6709\u4e3a TextField \u63d0\u4f9b\u83b7\u5f97\u7126\u70b9\u7684\u65b9\u6cd5\uff08\u4f8b\u5982\uff1a<code>becomeFirstResponder<\/code>\uff09\uff0c\u56e0\u6b64\u5728\u76f8\u5f53\u957f\u7684\u65f6\u95f4\u91cc\uff0c\u5f00\u53d1\u8005\u53ea\u80fd\u901a\u8fc7\u975e SwiftUI \u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u7c7b\u4f3c\u7684\u529f\u80fd\u3002<\/p>\n\n\n\n<p>\u5728 SwiftUI 3.0 \u4e2d\uff0c\u82f9\u679c\u4e3a\u5f00\u53d1\u8005\u63d0\u4f9b\u4e86\u4e00\u4e2a\u8fdc\u597d\u4e8e\u9884\u671f\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u540c onSubmit \u7c7b\u4f3c\uff0c\u53ef\u4ee5\u4ece\u66f4\u9ad8\u7684\u89c6\u56fe\u5c42\u6b21\u6765\u7edf\u4e00\u5bf9\u89c6\u56fe\u4e2d\u7684 TextField \u8fdb\u884c\u7126\u70b9\u7684\u5224\u65ad\u548c\u7ba1\u7406\u3002<\/p>\n\n\n\n<p><strong>\u57fa\u7840\u7528\u6cd5<\/strong><\/p>\n\n\n\n<p>SwiftUI \u63d0\u4f9b\u4e86\u4e00\u4e2a\u65b0\u7684 FocusState \u5c5e\u6027\u5305\u88c5\u5668\uff0c\u7528\u6765\u5e2e\u52a9\u6211\u4eec\u5224\u65ad\u8be5\u89c6\u56fe\u5185\u7684 TextField \u662f\u5426\u83b7\u5f97\u7126\u70b9\u3002\u901a\u8fc7<code>focused<\/code>\u5c06<code>FocusState<\/code>\u4e0e\u7279\u5b9a\u7684 TextField \u5173\u8054\u8d77\u6765\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo:View{\n    @FocusState var isNameFocused:Bool\n    @State var name = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text:$name)\n                .focused($isNameFocused)\n        }\n        .onChange(of:isNameFocused){ value in\n            print(value)\n        }\n    }\n}\n<\/pre>\n\n\n\n<p>\u4e0a\u9762\u7684\u4ee3\u7801\u5c06\u5728 TextField \u83b7\u5f97\u7126\u70b9\u65f6\u5c06<code>isNameFocused<\/code>\u8bbe\u7f6e\u4e3a<code>true<\/code>\uff0c\u5931\u53bb\u7126\u70b9\u65f6\u8bbe\u7f6e\u4e3a<code>false<\/code>\u3002<\/p>\n\n\n\n<p>\u5bf9\u4e8e\u540c\u4e00\u4e2a\u89c6\u56fe\u4e2d\u7684\u591a\u4e2a TextField\uff0c\u4f60\u53ef\u4ee5\u521b\u5efa\u591a\u4e2a FocusState \u6765\u5206\u522b\u5173\u8054\u5bf9\u5e94\u7684 TextField\uff0c\u4f8b\u5982\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo:View{\n    @FocusState var isNameFocused:Bool\n    @FocusState var isPasswordFocused:Bool\n    @State var name = \"\"\n    @State var password = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text:$name)\n                .focused($isNameFocused)\n            SecureField(\"password:\",text:$password)\n                .focused($isPasswordFocused)\n        }\n        .onChange(of:isNameFocused){ value in\n            print(value)\n        }\n        .onChange(of:isPasswordFocused){ value in\n            print(value)\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u4e0a\u8ff0\u65b9\u6cd5\u5f53\u89c6\u56fe\u4e2d\u62e5\u6709\u66f4\u591a\u7684 TextField \u65f6\u5c06\u53d8\u5f97\u5f88\u9ebb\u70e6\uff0c\u800c\u4e14\u4e0d\u5229\u4e8e\u7edf\u4e00\u7ba1\u7406\u3002\u597d\u5728\uff0cFocusState \u4e0d\u4ec5\u652f\u6301\u5e03\u5c14\u503c\uff0c\u8fd8\u652f\u6301\u4efb\u4f55\u54c8\u5e0c\u7c7b\u578b\u3002\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u7b26\u5408 Hashable \u534f\u8bae\u7684\u679a\u4e3e\u6765\u7edf\u4e00\u7ba1\u7406\u89c6\u56fe\u4e2d\u591a\u4e2a TextField \u7684\u7126\u70b9\u3002\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u5b9e\u73b0\u540c\u4e0a\u9762\u4e00\u6837\u7684\u529f\u80fd\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo:View{\n    @FocusState var focus:FocusedField?\n    @State var name = \"\"\n    @State var password = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text:$name)\n                .focused($focus, equals: .name)\n            SecureField(\"password:\",text:$password)\n                .focused($focus,equals: .password)\n        }\n        .onChange(of: focus, perform: {print($0)})\n    }\n\n    enum FocusedField:Hashable{\n        case name,password\n    }\n}<\/pre>\n\n\n\n<p><strong>\u663e\u793a\u89c6\u56fe\u540e\u7acb\u523b\u8ba9\u6307\u5b9a TextField \u83b7\u5f97\u7126\u70b9<\/strong><\/p>\n\n\n\n<p>\u901a\u8fc7 FocusState\uff0c\u53ef\u4ee5\u65b9\u4fbf\u7684\u5b9e\u73b0\u5728\u89c6\u56fe\u663e\u793a\u540e\uff0c\u7acb\u523b\u8ba9\u6307\u5b9a\u7684 TextField \u83b7\u5f97\u7126\u70b9\u5e76\u5f39\u51fa\u952e\u76d8\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo:View{\n    @FocusState var focus:FocusedField?\n    @State var name = \"\"\n    @State var password = \"\"\n    var body: some View{\n        List{\n            TextField(\"name:\",text:$name)\n                .focused($focus, equals: .name)\n            SecureField(\"password:\",text:$password)\n                .focused($focus,equals: .password)\n        }\n        .onAppear{\n            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5){\n                focus = .name\n            }\n        }\n    }\n\n    enum FocusedField:Hashable{\n        case name,password\n    }\n}\n<\/pre>\n\n\n\n<p>\u5728\u89c6\u56fe\u521d\u59cb\u5316\u9636\u6bb5\u8d4b\u503c\u662f\u65e0\u6548\u7684\u3002\u5373\u4f7f<strong>\u5728<code>onAppear<\/code>\u4e2d\uff0c\u4e5f\u5fc5\u987b\u8981\u6709\u4e00\u5b9a\u5ef6\u65f6\u624d\u80fd\u8ba9 TextField \u7126\u70b9<\/strong>\u3002<\/p>\n\n\n\n<p><strong>\u5728\u591a\u4e2a\u7684 TextFiled \u4e4b\u95f4\u5207\u6362\u7126\u70b9<\/strong><\/p>\n\n\n\n<p>\u901a\u8fc7\u4f7f\u7528 focused \u548c onSubmit \u7684\u7ed3\u5408\uff0c\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u5f53\u7528\u6237\u5728\u4e00\u4e2a TextField \u4e2d\u8f93\u5165\u5b8c\u6210\u540e\uff08\u70b9\u51fb<code>return<\/code>\uff09\uff0c\u81ea\u52a8\u8ba9\u7126\u70b9\u5207\u6362\u5230\u4e0b\u4e00\u4e2a TextField \u7684\u6548\u679c\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo:View{\n    @FocusState var focus:FocusedField?\n    @State var name = \"\"\n    @State var email = \"\"\n    @State var phoneNumber = \"\"\n    var body: some View{\n        List{\n            TextField(\"Name:\",text:$name)\n                .focused($focus, equals: .name)\n                .onSubmit {\n                    focus = .email\n                }\n            TextField(\"Email:\",text:$email)\n                .focused($focus,equals: .email)\n                .onSubmit {\n                    focus = .phone\n                }\n            TextField(\"PhoneNumber:\",text:$phoneNumber)\n                .focused($focus, equals: .phone)\n                .onSubmit {\n                    if !name.isEmpty &amp;&amp; !email.isEmpty &amp;&amp; !phoneNumber.isEmpty {\n                        submit()\n                    }\n                }\n        }\n    }\n\n    private func submit(){\n        \/\/ submit all infos\n        print(\"submit\")\n    }\n\n    enum FocusedField:Hashable{\n        case name,email,phone\n    }\n}<\/pre>\n\n\n\n<p>\u4e0a\u8ff0\u4ee3\u7801\u4e5f\u53ef\u4ee5\u5229\u7528 onSubmit \u7684\u4f20\u9012\u7279\u6027\u53d8\u6210\u5982\u4e0b\u7684\u6a21\u6837\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">List {\n            TextField(\"Name:\", text: $name)\n                .focused($focus, equals: .name)\n            TextField(\"Email:\", text: $email)\n                .focused($focus, equals: .email)\n            TextField(\"PhoneNumber:\", text: $phoneNumber)\n                .focused($focus, equals: .phone)\n        }\n        .onSubmit {\n            switch focus {\n            case .name:\n                focus = .email\n            case .email:\n                focus = .phone\n            case .phone:\n                if !name.isEmpty, !email.isEmpty, !phoneNumber.isEmpty {\n                    submit()\n                }\n            default:\n                break\n            }\n        }<\/pre>\n\n\n\n<p>\u7ed3\u5408\u8bbe\u5b9a\u7684\u5c4f\u5e55\u6309\u94ae\uff08\u4f8b\u5982\u8f85\u52a9\u952e\u76d8\u89c6\u56fe\uff09\u6216\u8005\u5feb\u6377\u952e\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u8ba9\u7126\u70b9\u5411\u524d\u6539\u53d8\u6216\u8005\u8df3\u8f6c\u5230\u5176\u4ed6\u7279\u5b9a\u7684 TextField \u4e0a\u3002<\/p>\n\n\n\n<p><strong>\u4f7f\u7528\u5feb\u6377\u952e\u83b7\u5f97\u7126\u70b9<\/strong><\/p>\n\n\n\n<p>\u5f53\u4e00\u4e2a\u89c6\u56fe\u4e2d\u6709\u591a\u4e2a TextField\uff08\u5305\u62ec SecureField\uff09\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528<code>Tab<\/code>\u952e\u6309\u987a\u5e8f\u5728 TextField \u4e2d\u5207\u6362\u7126\u70b9\uff0c\u4f46 SwiftUI \u5e76\u6ca1\u6709\u76f4\u63a5\u63d0\u4f9b\u4f7f\u7528\u5feb\u6377\u952e\u8ba9\u67d0\u4e2a TextField \u83b7\u5f97\u7126\u70b9\u7684\u529f\u80fd\u3002\u901a\u8fc7\u7ed3\u5408<code>FocusState<\/code>\u548c<code>keyboardShortcut<\/code>\u53ef\u4ee5\u5728 iPadOS \u548c MacOS \u4e0b\u83b7\u5f97\u8fd9\u79cd\u80fd\u529b\u3002<\/p>\n\n\n\n<p>\u521b\u5efa\u652f\u6301\u5feb\u6377\u952e\u7ed1\u5b9a\u7684<code>focused<\/code>\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public extension View {\n    func focused(_ condition: FocusState&lt;Bool>.Binding, key: KeyEquivalent, modifiers: EventModifiers = .command) -> some View {\n        focused(condition)\n            .background(Button(\"\") {\n                condition.wrappedValue = true\n            }\n            .keyboardShortcut(key, modifiers: modifiers)\n            .hidden()\n            )\n    }\n\n    func focused&lt;Value>(_ binding: FocusState&lt;Value>.Binding, equals value: Value, key: KeyEquivalent, modifiers: EventModifiers = .command) -> some View where Value: Hashable {\n        focused(binding, equals: value)\n            .background(Button(\"\") {\n                binding.wrappedValue = value\n            }\n            .keyboardShortcut(key, modifiers: modifiers)\n            .hidden()\n            )\n    }\n}<\/pre>\n\n\n\n<p>\u8c03\u7528\u4ee3\u7801\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct ShortcutFocusDemo: View {\n    @FocusState var focus: FouceField?\n    @State private var email = \"\"\n    @State private var address = \"\"\n    var body: some View {\n        Form {\n            TextField(\"email\", text: $email)\n                .focused($focus, equals: .email, key: \"t\")\n            TextField(\"address\", text: $address)\n                .focused($focus, equals: .address, key: \"a\", modifiers: [.command, .shift,.option])\n        }\n    }\n\n    enum FouceField: Hashable {\n        case email\n        case address\n    }\n}\n<\/pre>\n\n\n\n<p>\u5f53\u7528\u6237\u8f93\u5165 \u2318 + T \u65f6\uff0c\u8d1f\u8d23 email \u7684 TextField \u5c06\u83b7\u5f97\u7126\u70b9\uff0c\u7528\u6237\u8f93\u5165\u2318 + \u2325 + \u21e7 + A \u65f6\uff0c\u8d1f\u8d23 address \u7684 TextField \u83b7\u5f97\u7126\u70b9\u3002<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-1024x60.png\" alt=\"\" class=\"wp-image-5583\" width=\"782\" height=\"46\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-1024x60.png 1024w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-300x18.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-768x45.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-1536x90.png 1536w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-2048x120.png 2048w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-830x48.png 830w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-230x13.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-350x20.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-149-480x28.png 480w\" sizes=\"(max-width: 782px) 100vw, 782px\" \/><\/figure><\/div>\n\n\n\n<p><strong>\u521b\u5efa\u81ea\u5df1\u7684 onEditingChanged<\/strong><\/p>\n\n\n\n<p>\u5224\u65ad\u5355\u4e2a TextField \u7684\u7126\u70b9\u72b6\u6001\u6700\u4f73\u9009\u62e9\u4ecd\u662f\u4f7f\u7528<code>onEditingChanged<\/code>\uff0c\u4f46\u5bf9\u4e8e\u67d0\u4e9b\u65e0\u6cd5\u4f7f\u7528 onEditingChanged \u7684\u573a\u5408\uff08\u6bd4\u5982\u65b0\u7684 Formatter\uff09\uff0c\u6211\u4eec\u53ef\u4ee5\u5229\u7528 FocusState \u6765\u5b9e\u73b0\u7c7b\u4f3c\u7684\u6548\u679c\u3002<\/p>\n\n\n\n<ul><li>\u5bf9\u5355\u4e2a TextField \u8fdb\u884c\u5224\u65ad<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public extension View {\n    func focused(_ condition: FocusState&lt;Bool>.Binding, onFocus: @escaping (Bool) -> Void) -> some View {\n        focused(condition)\n            .onChange(of: condition.wrappedValue) { value in\n                onFocus(value == true)\n            }\n    }\n}\n<\/pre>\n\n\n\n<p>\u8c03\u7528\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct onEditingChangedFocusVersion:View{\n    @FocusState var focus:Bool\n    @State var price = 0\n    var body: some View{\n        Form{\n            TextField(\"Price:\",value:$price,format: .number)\n                .focused($focus){ focused in\n                    print(focused)\n                }\n        }\n    }\n}\n<\/pre>\n\n\n\n<ul><li>\u5bf9\u591a\u4e2a TextField \u8fdb\u884c\u5224\u65ad<\/li><\/ul>\n\n\n\n<p>\u4e3a\u4e86\u907f\u514d\u5728 TextField \u5931\u53bb\u7126\u70b9\u540e\u51fa\u73b0\u591a\u6b21\u8c03\u7528\u7684\u60c5\u51b5\uff0c\u6211\u4eec\u9700\u8981\u5728\u89c6\u56fe\u5c42\u6b21\u4fdd\u5b58\u4e0a\u6b21\u83b7\u5f97\u7126\u70b9\u7684 TextField \u7684 FocusState \u503c\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public extension View {\n    func storeLastFocus&lt;Value: Hashable>(current: FocusState&lt;Value?>.Binding, last: Binding&lt;Value?>) -> some View {\n        onChange(of: current.wrappedValue) { _ in\n            if current.wrappedValue != last.wrappedValue {\n                last.wrappedValue = current.wrappedValue\n            }\n        }\n    }\n\n    func focused&lt;Value>(_ binding: FocusState&lt;Value>.Binding, equals value: Value, last: Value?, onFocus: @escaping (Bool) -> Void) -> some View where Value: Hashable {\n        return focused(binding, equals: value)\n            .onChange(of: binding.wrappedValue) { focusValue in\n                if focusValue == value {\n                    onFocus(true)\n                } else if last == value { \/\/\u53ea\u89e6\u53d1\u4e00\u6b21\n                    onFocus(false)\n                }\n            }\n    }\n}<\/pre>\n\n\n\n<p>\u8c03\u7528\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusView: View {\n    @FocusState private var focused: Focus?\n    @State private var lastFocused: Focus?\n    @State private var name = \"\"\n    @State private var email = \"\"\n    @State private var address = \"\"\n    var body: some View {\n        List {\n            TextField(\"Name:\", text: $name)\n                .focused($focused, equals: .name, last: lastFocused) {\n                    print(\"name:\", $0)\n                }\n            TextField(\"Email:\", text: $email)\n                .focused($focused, equals: .email, last: lastFocused) {\n                    print(\"email:\", $0)\n                }\n            TextField(\"Address:\", text: $address)\n                .focused($focused, equals: .address, last: lastFocused) {\n                    print(\"address:\", $0)\n                }\n        }\n        .storeLastFocus(current: $focused, last: $lastFocused) \/\/\u4fdd\u5b58\u4e0a\u6b21\u7684 focsed \u503c\n    }\n\n    enum Focus {\n        case name, email, address\n    }\n}\n<\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">\u952e\u76d8<\/h6>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>\u4f7f\u7528 TextField \u4e0d\u53ef\u907f\u514d\u7684\u9700\u8981\u540c\u8f6f\u952e\u76d8\u6253\u4ea4\u9053\uff0c\u672c\u8282\u5c06\u4ecb\u7ecd\u51e0\u4e2a\u540c\u952e\u76d8\u6709\u5173\u4f8b\u5b50\u3002<\/p>\n\n\n\n<p><strong>\u952e\u76d8\u7c7b\u578b<\/strong><\/p>\n\n\n\n<p>\u5728 iPhone \u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7<code>keyboardType<\/code>\u6765\u8bbe\u5b9a\u8f6f\u952e\u76d8\u7c7b\u578b\uff0c\u65b9\u4fbf\u7528\u6237\u7684\u5f55\u5165\u6216\u9650\u5236\u5f55\u5165\u5b57\u7b26\u8303\u56f4\u3002<\/p>\n\n\n\n<p>\u6bd4\u5982\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct KeyboardTypeDemo:View{\n    @State var price:Double = 0\n    var body: some View{\n        Form{\n            TextField(\"Price:\",value:$price,format: .number.precision(.fractionLength(2)))\n                .keyboardType(.decimalPad) \/\/\u652f\u6301\u5c0f\u6570\u70b9\u7684\u6570\u5b57\u952e\u76d8\n        }\n    }\n}<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150.png\" alt=\"\" class=\"wp-image-5584\" width=\"391\" height=\"244\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150.png 762w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150-300x187.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150-230x144.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150-350x219.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-150-480x300.png 480w\" sizes=\"(max-width: 391px) 100vw, 391px\" \/><\/figure><\/div>\n\n\n\n<p>\u76ee\u524d\u652f\u6301\u7684\u952e\u76d8\u7c7b\u578b\u5171\u6709 11 \u79cd\uff0c\u5206\u522b\u4e3a\uff1a<\/p>\n\n\n\n<ul><li>asciiCapable<\/li><\/ul>\n\n\n\n<p>ASCII \u5b57\u7b26\u952e\u76d8<\/p>\n\n\n\n<ul><li>numbersAndPunctuation<\/li><\/ul>\n\n\n\n<p>\u6570\u5b57\u53ca\u6807\u70b9\u7b26\u53f7<\/p>\n\n\n\n<ul><li>URL<\/li><\/ul>\n\n\n\n<p>\u4fbf\u4e8e\u8f93\u5165 URL\uff0c\u5305\u542b\u5b57\u7b26\u548c<code>.<\/code>\u3001<code>\/<\/code>\u3001<code>.com<\/code><\/p>\n\n\n\n<ul><li>numberPad<\/li><\/ul>\n\n\n\n<p>\u4f7f\u7528\u533a\u57df\u8bbe\u7f6e\u7684\u6570\u5b57\u952e\u76d8\uff080-9\u3001\u06f0-\u06f9\u3001\u0966-\u096f \u7b49\uff09\u3002\u9002\u7528\u4e8e\u6b63\u6574\u6570\u6216 PIN<\/p>\n\n\n\n<ul><li>phonePad<\/li><\/ul>\n\n\n\n<p>\u6570\u5b57\u53ca\u5176\u4ed6\u7535\u8bdd\u4e2d\u4f7f\u7528\u7684\u7b26\u53f7\uff0c\u5982<code>*#+<\/code><\/p>\n\n\n\n<ul><li>namePhonePad<\/li><\/ul>\n\n\n\n<p>\u65b9\u4fbf\u5f55\u5165\u6587\u5b57\u53ca\u7535\u8bdd\u53f7\u7801\u3002\u5b57\u7b26\u72b6\u6001\u540c asciiCapable \u7c7b\u4f3c\uff0c\u6570\u5b57\u72b6\u6001\u540c numberPad \u7c7b\u4f3c<\/p>\n\n\n\n<ul><li>emailAddress<\/li><\/ul>\n\n\n\n<p>\u4fbf\u4e8e\u5f55\u5165<code>@.<\/code>\u7684 assiiCapable \u952e\u76d8<\/p>\n\n\n\n<ul><li>decimalPad<\/li><\/ul>\n\n\n\n<p>\u5305\u542b\u5c0f\u6570\u70b9\u7684 numberPad\uff0c\u5177\u4f53\u89c1\u4e0a\u56fe<\/p>\n\n\n\n<ul><li>twitter<\/li><\/ul>\n\n\n\n<p>\u5305\u542b<code>@#<\/code>\u7684 asciiCapable \u952e\u76d8<\/p>\n\n\n\n<ul><li>webSearch<\/li><\/ul>\n\n\n\n<p>\u5305\u542b<code>.<\/code>\u7684 asciiCapable \u952e\u76d8\uff0c<code>return<\/code>\u952e\u6807\u8bb0\u4e3a<code>go<\/code><\/p>\n\n\n\n<ul><li>asciiCapableNumberPad<\/li><\/ul>\n\n\n\n<p>\u5305\u542b\u6570\u5b57\u7684 asciiCapable \u952e\u76d8<\/p>\n\n\n\n<p>\u5c3d\u7ba1\u82f9\u679c\u9884\u7f6e\u4e86\u4e0d\u5c11\u952e\u76d8\u6a21\u5f0f\u53ef\u4ee5\u9009\u62e9\uff0c\u4e0d\u8fc7\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u4ecd\u65e0\u6cd5\u6ee1\u8db3\u4f7f\u7528\u7684\u9700\u8981\u3002<\/p>\n\n\n\n<p>\u6bd4\u5982\uff1anumberPad\u3001decimalPad \u6ca1\u6709<code>-<\/code>\u53ca<code>return<\/code>\u3002\u5728 SwiftUI 3.0 \u4e4b\u524d\uff0c\u6211\u4eec\u5fc5\u987b\u5728\u4e3b\u89c6\u56fe\u4e0a\u53e6\u5916\u7ed8\u5236\u6216\u8005\u4f7f\u7528\u975e SwiftUI \u7684\u65b9\u5f0f\u6765\u89e3\u51b3\u95ee\u9898\uff0c\u5728 SwiftUI 3.0 \u4e2d\uff0c\u7531\u4e8e\u6dfb\u52a0\u4e86\u539f\u751f\u8bbe\u7f6e\u952e\u76d8\u8f85\u52a9\u89c6\u56fe\uff08\u4e0b\u6587\u5177\u4f53\u4ecb\u7ecd\uff09\u7684\u529f\u80fd\uff0c\u89e3\u51b3\u4e0a\u8ff0\u95ee\u9898\u5c06\u4e0d\u518d\u56f0\u96be\u3002<\/p>\n\n\n\n<p><strong>\u901a\u8fc7 TextContentType \u83b7\u5f97\u5efa\u8bae<\/strong><\/p>\n\n\n\n<p>\u5728\u4f7f\u7528\u67d0\u4e9b iOS app \u65f6\uff0c\u5728\u5f55\u5165\u6587\u5b57\u65f6\u4f1a\u5728\u8f6f\u952e\u76d8\u4e0a\u65b9\u81ea\u52a8\u63d0\u793a\u6211\u4eec\u9700\u8981\u8f93\u5165\u7684\u5185\u5bb9\uff0c\u6bd4\u5982\u7535\u8bdd\u3001\u90ae\u4ef6\u3001\u9a8c\u8bc1\u7801\u7b49\u7b49\u3002\u8fd9\u4e9b\u90fd\u662f\u4f7f\u7528<code>textContentType<\/code>\u5f97\u5230\u7684\u6548\u679c\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u7ed9 TextField \u8bbe\u5b9a UITextContentType\uff0c\u7cfb\u7edf\u5728\u8f93\u5165\u65f6\u667a\u80fd\u5730\u63a8\u65ad\u51fa\u53ef\u80fd\u60f3\u8981\u5f55\u5165\u7684\u5185\u5bb9\uff0c\u5e76\u663e\u793a\u63d0\u793a\u3002<\/p>\n\n\n\n<p>\u4e0b\u9762\u7684\u4ee3\u7801\u5728\u5f55\u5165\u5bc6\u7801\u65f6\uff0c\u5c06\u5141\u8bb8\u4f7f\u7528\u94a5\u5319\u4e32\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct KeyboardTypeDemo: View {\n    @State var password = \"\"\n    var body: some View {\n        Form {\n            SecureField(\"\", text: $password)\n                .textContentType(.password)\n        }\n    }\n}<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151.png\" alt=\"\" class=\"wp-image-5586\" width=\"352\" height=\"299\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151-300x255.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151-230x196.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151-350x298.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-151-480x409.png 480w\" sizes=\"(max-width: 352px) 100vw, 352px\" \/><\/figure><\/div>\n\n\n\n<p>\u4e0b\u9762\u7684\u4ee3\u7801\u5728\u5f55\u5165\u90ae\u7bb1\u5730\u5740\u65f6\uff0c\u5c06\u4ece\u4f60\u7684\u901a\u8baf\u5f55\u548c\u90ae\u4ef6\u4e2d\u67e5\u627e\u76f8\u4f3c\u7684\u5730\u5740\u4e88\u4ee5\u63d0\u793a\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct KeyboardTypeDemo: View {\n    @State var email = \"\"\n    var body: some View {\n        Form {\n            TextField(\"\", text: $email)\n                .textContentType(.emailAddress)\n        }\n    }\n}\n<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152.png\" alt=\"\" class=\"wp-image-5587\" width=\"389\" height=\"273\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152.png 776w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152-300x210.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152-768x538.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152-230x161.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152-350x245.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-152-480x336.png 480w\" sizes=\"(max-width: 389px) 100vw, 389px\" \/><\/figure><\/div>\n\n\n\n<p>\u53ef\u4ee5\u8bbe\u5b9a\u7684 UITextContentType \u79cd\u7c7b\u6709\u5f88\u591a\uff0c\u5176\u4e2d\u4f7f\u7528\u7684\u6bd4\u8f83\u591a\u7684\u6709\uff1a<\/p>\n\n\n\n<ul><li>password<\/li><li>\u59d3\u540d\u7684\u9009\u9879\uff0c\u5982\uff1aname\u3001givenName\u3001middleName \u7b49\u7b49<\/li><li>\u5730\u5740\u9009\u9879\uff0c\u5982 addressCity\u3001fullStreetAddress\u3001postalCode \u7b49\u7b49<\/li><li>telephoneNumber<\/li><li>emailAddress<\/li><li>oneTimeCode\uff08\u9a8c\u8bc1\u7801\uff09<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-1024x54.png\" alt=\"\" class=\"wp-image-5588\" width=\"747\" height=\"39\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-1024x54.png 1024w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-300x16.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-768x41.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-1536x81.png 1536w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-830x44.png 830w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-230x12.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-350x18.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153-480x25.png 480w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-153.png 2044w\" sizes=\"(max-width: 747px) 100vw, 747px\" \/><\/figure><\/div>\n\n\n\n<p><strong>\u53d6\u6d88\u952e\u76d8<\/strong><\/p>\n\n\n\n<p>\u6709\u4e9b\u60c5\u51b5\u4e0b\uff0c\u5728\u7528\u6237\u8f93\u5165\u5b8c\u6bd5\u540e\uff0c\u6211\u4eec\u9700\u8981\u53d6\u6d88\u8f6f\u952e\u76d8\u7684\u663e\u793a\uff0c\u4ee5\u4fbf\u7559\u51fa\u66f4\u5927\u7684\u663e\u793a\u7a7a\u95f4\u3002\u67d0\u4e9b\u952e\u76d8\u7c7b\u578b\u5e76\u6ca1\u6709<code>return<\/code>\u6309\u952e\uff0c\u56e0\u6b64\u6211\u4eec\u9700\u8981\u4f7f\u7528\u7f16\u7a0b\u7684\u65b9\u5f0f\u8ba9\u952e\u76d8\u6d88\u5931\u3002<\/p>\n\n\n\n<p>\u53e6\u5916\uff0c\u6709\u65f6\u5019\u4e3a\u4e86\u63d0\u9ad8\u4ea4\u4e92\u4f53\u9a8c\uff0c\u6211\u4eec\u53ef\u4ee5\u5e0c\u671b\u7528\u6237\u5728\u5f55\u5165\u7ed3\u675f\u540e\uff0c\u65e0\u9700\u70b9\u51fb<code>return<\/code>\u6309\u952e\uff0c\u901a\u8fc7\u70b9\u51fb\u5c4f\u5e55\u5176\u4ed6\u533a\u57df\u6216\u8005\u4ee5\u6eda\u52a8\u5217\u8868\u7684\u65b9\u5f0f\u6765\u53d6\u6d88\u952e\u76d8\u3002\u540c\u6837\u4e5f\u9700\u8981\u4f7f\u7528\u7f16\u7a0b\u7684\u65b9\u5f0f\u8ba9\u952e\u76d8\u6d88\u5931\u3002<\/p>\n\n\n\n<ul><li>\u4f7f\u7528 FocusState \u53d6\u6d88\u952e\u76d8<\/li><\/ul>\n\n\n\n<p>\u5982\u679c\u4e3a TextField \u8bbe\u7f6e\u4e86\u5bf9\u5e94\u7684 FocusState\uff0c\u901a\u8fc7\u5c06\u8be5\u503c\u8bbe\u7f6e\u4e3a<code>false<\/code>\u6216<code>nil<\/code>\u5373\u53ef\u53d6\u6d88\u952e\u76d8<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct HideKeyboardView: View {\n    @State private var name = \"\"\n    @FocusState private var nameIsFocused: Bool\n\n    var body: some View {\n        Form {\n            TextField(\"Enter your name\", text: $name)\n                .focused($nameIsFocused)\n\n            Button(\"dismiss Keyboard\") {\n                nameIsFocused = false\n            }\n        }\n    }\n}\n<\/pre>\n\n\n\n<ul><li>\u5176\u4ed6\u60c5\u51b5<\/li><\/ul>\n\n\n\n<p>\u66f4\u591a\u7684\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u4ee5\u76f4\u63a5\u901a\u8fc7 UIkit \u63d0\u4f9b\u7684\u65b9\u6cd5\u6765\u53d6\u6d88\u952e\u76d8<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)<\/pre>\n\n\n\n<p>\u4f8b\u5982\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u5728\u7528\u6237\u5bf9\u89c6\u56fe\u8fdb\u884c\u62d6\u62fd\u65f6\u53d6\u6d88\u952e\u76d8\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct ResignKeyboardOnDragGesture: ViewModifier {\n    var gesture = DragGesture().onChanged { _ in\n        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)\n    }\n\n    func body(content: Content) -> some View {\n        content.gesture(gesture)\n    }\n}\n\nextension View {\n    func dismissKeyboard() -> some View {\n        return modifier(ResignKeyboardOnDragGesture())\n    }\n}\n\nstruct HideKeyboardView: View {\n    @State private var name = \"\"\n    var body: some View {\n        Form {\n            TextField(\"Enter your name\", text: $name)\n        }\n        .dismissKeyboard()\n    }\n}<\/pre>\n\n\n\n<p><strong>\u952e\u76d8\u8f85\u52a9\u89c6\u56fe<\/strong><\/p>\n\n\n\n<p>\u901a\u8fc7 toolbar \u521b\u5efa<\/p>\n\n\n\n<p>\u5728 SwiftUI 3.0 \u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7<code>ToolbarItem(placement: .keyboard, content: View)<\/code>\u6765\u81ea\u521b\u5efa\u952e\u76d8\u7684\u8f85\u52a9\u89c6\u56fe\uff08inputAccessoryView\uff09\u3002<\/p>\n\n\n\n<p>\u901a\u8fc7\u8f93\u5165\u8f85\u52a9\u89c6\u56fe\uff0c\u53ef\u4ee5\u89e3\u51b3\u5f88\u591a\u4e4b\u524d\u96be\u4ee5\u5e94\u5bf9\u7684\u95ee\u9898\uff0c\u5e76\u4e3a\u4ea4\u4e92\u63d0\u4f9b\u66f4\u591a\u7684\u624b\u6bb5\u3002<\/p>\n\n\n\n<p>\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u4e3a\u8f93\u5165\u6d6e\u70b9\u6570\u65f6\u6dfb\u52a0\u6b63\u8d1f\u8f6c\u6362\u4ee5\u53ca\u786e\u8ba4\u6309\u94ae\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import Introspect\nstruct ToolbarKeyboardDemo: View {\n    @State var price = \"\"\n    var body: some View {\n        Form {\n            TextField(\"Price:\", text: $price)\n                .keyboardType(.decimalPad)\n                .toolbar {\n                    ToolbarItem(placement: .keyboard) {\n                        HStack {\n                            Button(\"-\/+\") {\n                                if price.hasPrefix(\"-\") {\n                                    price.removeFirst()\n                                } else {\n                                    price = \"-\" + price\n                                }\n                            }\n                            .buttonStyle(.bordered)\n                            Spacer()\n                            Button(\"Finish\") {\n                                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)\n                                \/\/ do something\n                            }\n                            .buttonStyle(.bordered)\n                        }\n                        .padding(.horizontal, 30)\n                    }\n                }\n        }\n    }\n}\n<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154.png\" alt=\"\" class=\"wp-image-5590\" width=\"381\" height=\"272\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154-300x214.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154-230x164.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154-350x250.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-154-480x343.png 480w\" sizes=\"(max-width: 381px) 100vw, 381px\" \/><\/figure><\/div>\n\n\n\n<p>\u9057\u61be\u7684\u65f6\uff0c\u901a\u8fc7 ToolbarItem \u8bbe\u7f6e\u8f93\u5165\u8f85\u52a9\u89c6\u56fe\u76ee\u524d\u8fd8\u6709\u4ee5\u4e0b\u4e0d\u8db3\uff1a<\/p>\n\n\n\n<ul><li>\u663e\u793a\u5185\u5bb9\u53d7\u9650<\/li><\/ul>\n\n\n\n<p>\u9ad8\u5ea6\u56fa\u5b9a\uff0c\u4e14\u65e0\u6cd5\u5229\u7528\u8f85\u52a9\u89c6\u56fe\u7684\u5b8c\u6574\u663e\u793a\u533a\u57df\u3002\u540c\u5176\u4ed6\u7c7b\u578b\u7684 Toolbar \u7c7b\u4f3c\uff0cSwiftUI \u4f1a\u5e72\u9884\u5185\u5bb9\u7684\u6392\u7248\u3002<\/p>\n\n\n\n<ul><li>\u65e0\u6cd5\u5bf9\u540c\u4e00\u89c6\u56fe\u4e2d\u591a\u4e2a TextField \u5206\u522b\u8bbe\u5b9a\u8f85\u52a9\u89c6\u56fe<\/li><\/ul>\n\n\n\n<p>\u5728 ToolbarItem \u4e2d\u65e0\u6cd5\u4f7f\u7528\u7a0d\u5fae\u590d\u6742\u4e00\u70b9\u7684\u5224\u65ad\u8bed\u6cd5\u3002\u5982\u679c\u5206\u522b\u5bf9\u4e0d\u540c\u7684 TextField \u8fdb\u884c\u8bbe\u5b9a\uff0cSwiftUI \u4f1a\u5c06\u6240\u6709\u7684\u5185\u5bb9\u5408\u5e76\u8d77\u6765\u663e\u793a\u3002<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-1024x98.png\" alt=\"\" class=\"wp-image-5591\" width=\"614\" height=\"58\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-1024x98.png 1024w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-300x29.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-768x74.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-1536x148.png 1536w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-830x80.png 830w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-230x22.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-350x34.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155-480x46.png 480w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-155.png 2040w\" sizes=\"(max-width: 614px) 100vw, 614px\" \/><\/figure><\/div>\n\n\n\n<p><strong>\u901a\u8fc7 UIKit \u521b\u5efa<\/strong><\/p>\n\n\n\n<p>\u5f53\u524d\u9636\u6bb5\uff0c\u901a\u8fc7 UIKit \u6765\u521b\u5efa\u952e\u76d8\u8f85\u52a9\u89c6\u56fe\u4ecd\u662f SwiftUI \u4e0b\u7684\u6700\u4f18\u65b9\u6848\u3002\u4e0d\u4ec5\u53ef\u4ee5\u83b7\u5f97\u5b8c\u5168\u7684\u89c6\u56fe\u663e\u793a\u63a7\u5236\u80fd\u529b\uff0c\u5e76\u4e14\u53ef\u4ee5\u5bf9\u540c\u4e00\u89c6\u56fe\u4e0b\u7684\u591a\u4e2a TextField \u8fdb\u884c\u5206\u522b\u8bbe\u7f6e\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">extension UIView {\n    func constrainEdges(to other: UIView) {\n        translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            leadingAnchor.constraint(equalTo: other.leadingAnchor), \n            trailingAnchor.constraint(equalTo: other.trailingAnchor), \n            topAnchor.constraint(equalTo: other.topAnchor), \n            bottomAnchor.constraint(equalTo: other.bottomAnchor), \n        ])\n    }\n}\n\nextension View {\n    func inputAccessoryView&lt;Content: View>(@ViewBuilder content: @escaping () -> Content) -> some View {\n        introspectTextField { td in\n            let viewController = UIHostingController(rootView: content())\n            viewController.view.constrainEdges(to: viewController.view)\n            td.inputAccessoryView = viewController.view\n        }\n    }\n    \n    func inputAccessoryView&lt;Content: View>(content: Content) -> some View {\n        introspectTextField { td in\n            let viewController = UIHostingController(rootView: content)\n            viewController.view.constrainEdges(to: viewController.view)\n            td.inputAccessoryView = viewController.view\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u8c03\u7528\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">struct OnFocusDemo: View {\n    @FocusState var focus: FocusedField?\n    @State var name = \"\"\n    @State var email = \"\"\n    @State var phoneNumber = \"\"\n    var body: some View {\n        Form {\n            TextField(\"Name:\", text: $name)\n                .focused($focus, equals: .name)\n                .inputAccessoryView(content: accessoryView(focus: .name))\n\n            TextField(\"Email:\", text: $email)\n                .focused($focus, equals: .email)\n                .inputAccessoryView(content: accessoryView(focus: .email))\n\n            TextField(\"PhoneNumber:\", text: $phoneNumber)\n                .focused($focus, equals: .phone)\n        }\n        .onSubmit {\n            switch focus {\n            case .name:\n                focus = .email\n            case .email:\n                focus = .phone\n            case .phone:\n                if !name.isEmpty, !email.isEmpty, !phoneNumber.isEmpty {}\n            default:\n                break\n            }\n        }\n    }\n}\n\nstruct accessoryView: View {\n    let focus: FocusedField?\n    var body: some View {\n        switch focus {\n        case .name:\n            Button(\"name\") {}.padding(.vertical, 10)\n        case .email:\n            Button(\"email\") {}.padding(.vertical, 10)\n        default:\n            EmptyView()\n        }\n    }\n}<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-1024x109.png\" alt=\"\" class=\"wp-image-5592\" width=\"708\" height=\"75\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-1024x109.png 1024w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-300x32.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-768x82.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-1536x164.png 1536w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-830x89.png 830w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-230x25.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-350x37.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156-480x51.png 480w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-156.png 2040w\" sizes=\"(max-width: 708px) 100vw, 708px\" \/><\/figure><\/div>\n\n\n\n<p><strong>\u81ea\u5b9a\u4e49 SubmitLabel<\/strong><\/p>\n\n\n\n<p>\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cTextField\uff08SecureField\uff09\u5728\u952e\u76d8\u4e0a\u5bf9\u5e94\u7684 submit \u884c\u4e3a\u6309\u94ae\u4e3a<code>return<\/code>\uff0c\u901a\u8fc7\u4f7f\u7528 SwiftUI 3.0 \u4e2d\u65b0\u589e\u4e86<code>submitLabel<\/code>\u4fee\u9970\u5668\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06<code>return<\/code>\u6309\u94ae\u4fee\u6539\u6210\u66f4\u7b26\u5408\u8f93\u5165\u4e0a\u4e0b\u6587\u7684\u663e\u793a\u6587\u5b57\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">TextField(\"Username\", text: $username)\n            .submitLabel(.next)<\/pre>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/123.57.164.21\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157.png\" alt=\"\" class=\"wp-image-5593\" width=\"429\" height=\"245\" srcset=\"https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157.png 774w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157-300x171.png 300w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157-768x439.png 768w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157-230x131.png 230w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157-350x200.png 350w, https:\/\/92it.top\/wp-content\/uploads\/2022\/04\/\u56fe\u7247-157-480x274.png 480w\" sizes=\"(max-width: 429px) 100vw, 429px\" \/><\/figure><\/div>\n\n\n\n<p>\u76ee\u524d\u652f\u6301\u7684\u79cd\u7c7b\u6709\uff1a<\/p>\n\n\n\n<ul><li>continue<\/li><li>done<\/li><li>go<\/li><li>join<\/li><li>next<\/li><li>return<\/li><li>route<\/li><li>search<\/li><li>send<\/li><\/ul>\n\n\n\n<p>\u4f8b\u5982\u4e4b\u524d\u7684\u4ee3\u7801\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u5206\u522b\u4e3a<code>name<\/code>\u3001<code>email<\/code>\u3001<code>phoneNumber<\/code>\u8bbe\u5b9a\u4e0d\u540c\u7684\u5bf9\u5e94\u663e\u793a\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">            TextField(\"Name:\", text: $name)\n                .focused($focus, equals: .name)\n                .submitLabel(.next)\n\n            TextField(\"Email:\", text: $email)\n                .focused($focus, equals: .email)\n                .submitLabel(.next)\n\n            TextField(\"PhoneNumber:\", text: $phoneNumber)\n                .focused($focus, equals: .phone)\n                .submitLabel(.return)\n<\/pre>\n\n\n\n<h6 class=\"wp-block-heading\">\u603b\u7ed3<\/h6>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>\u4ece SwiftUI 1.0 \u5f00\u59cb\uff0c\u82f9\u679c\u6301\u7eed\u4e0d\u65ad\u5730\u5b8c\u5584 TextField \u7684\u529f\u80fd\u3002\u5728 3.0 \u7248\u672c\u4e2d\uff0cSwiftUI \u4e0d\u4ec5\u63d0\u4f9b\u4e86\u66f4\u591a\u7684\u539f\u751f\u4fee\u9970\u5668\uff0c\u800c\u4e14\u63d0\u4f9b\u4e86 FocusState\u3001onSubmit \u6b64\u7c7b\u7684\u7edf\u5408\u7ba1\u7406\u903b\u8f91\u3002\u76f8\u4fe1\u518d\u6709 2-3 \u5e74\uff0cSwiftUI \u7684\u4e3b\u8981\u63a7\u4ef6\u7684\u539f\u751f\u529f\u80fd\u5c31\u53ef\u4ee5\u6bd4\u80a9\u5bf9\u5e94\u7684 UIKit \u63a7\u4ef6\u4e86\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u5c06\u63a2\u8ba8\u6d89\u53ca SwiftUI TextField \u7684\u4e8b\u4ef6\u3001\u7126\u70b9\u5207\u6362\u3001\u952e\u76d8\u8bbe\u7f6e\u7b49\u76f8\u5173\u7684\u7ecf\u9a8c\u3001\u6280\u5de7\u548c\u6ce8\u610f\u4e8b\u9879\u3002  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/5577"}],"collection":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5577"}],"version-history":[{"count":8,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/5577\/revisions"}],"predecessor-version":[{"id":5594,"href":"https:\/\/92it.top\/index.php?rest_route=\/wp\/v2\/posts\/5577\/revisions\/5594"}],"wp:attachment":[{"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5577"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5577"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/92it.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}