├── Resources
└── growing_text_view.gif
├── GrowingTextView
├── SupportingFiles
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── background.colorset
│ │ │ └── Contents.json
│ │ ├── inputBorder.colorset
│ │ │ └── Contents.json
│ │ ├── messageBackground.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Extensions
│ ├── String+OrEmpty.swift
│ └── Color.swift
├── Application
│ ├── SceneDelegate.swift
│ └── AppDelegate.swift
├── GrowinTextView
│ ├── GrowingTextInputView.swift
│ └── TextViewWrapper.swift
└── ExampleView
│ └── ChatView.swift
├── GrowingTextView.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── maciejgomolka.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
├── .gitignore
├── README.md
└── LICENSE
/Resources/growing_text_view.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zaprogramiacz/GrowingTextView/HEAD/Resources/growing_text_view.gif
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/GrowingTextView/Extensions/String+OrEmpty.swift:
--------------------------------------------------------------------------------
1 | extension Optional where Wrapped == String {
2 | var orEmpty: String {
3 | self ?? ""
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/GrowingTextView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/GrowingTextView/Extensions/Color.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | extension Color {
4 | static var background: Color { .init("background") }
5 | static var inputBorder: Color { .init("inputBorder") }
6 | static var messageBackground: Color { .init("messageBackground") }
7 | }
8 |
--------------------------------------------------------------------------------
/GrowingTextView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | xcuserdata/
2 |
3 | *.xcscmblueprint
4 | *.xccheckout
5 |
6 | build/
7 | DerivedData/
8 | *.moved-aside
9 | *.pbxuser
10 | !default.pbxuser
11 | *.mode1v3
12 | !default.mode1v3
13 | *.mode2v3
14 | !default.mode2v3
15 | *.perspectivev3
16 | !default.perspectivev3
17 |
18 | *.hmap
19 |
20 | *.ipa
21 | *.dSYM.zip
22 | *.dSYM
23 |
24 | timeline.xctimeline
25 | playground.xcworkspace
26 |
27 | .build/
28 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Assets.xcassets/background.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "243",
9 | "green" : "238",
10 | "red" : "237"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Assets.xcassets/inputBorder.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.749",
9 | "green" : "0.749",
10 | "red" : "0.749"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/GrowingTextView.xcodeproj/xcuserdata/maciejgomolka.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | GrowingTextView.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Assets.xcassets/messageBackground.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.091",
9 | "green" : "0.715",
10 | "red" : "0.147"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/GrowingTextView/Application/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import SwiftUI
3 |
4 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
5 |
6 | var window: UIWindow?
7 |
8 | func scene(_ scene: UIScene,
9 | willConnectTo session: UISceneSession,
10 | options connectionOptions: UIScene.ConnectionOptions) {
11 | guard let windowScene = scene as? UIWindowScene else { return }
12 | window = UIWindow(windowScene: windowScene)
13 | window?.rootViewController = UIHostingController(rootView: ChatView())
14 | window?.makeKeyAndVisible()
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Growing text view in SwiftUI
2 |
3 | 
4 | 
5 |
6 | If you are planning to write a messaging feature or you are just a SwiftUI enthusiast, this repository can be interesting for you. SwiftUI doesn't provide us the equivalent of UITextView, so to use it in SwiftUI, you need to write a wrapper. Additionally, UITextView can't have a placeholder. I've made a component that can have a placeholder and grow to a predefined height. I hope that this piece of code will help in your SwiftIU adventure.
7 |
8 | 
9 |
10 | # [License](LICENSE)
11 |
--------------------------------------------------------------------------------
/GrowingTextView/Application/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @UIApplicationMain
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 |
6 | func application(_ application: UIApplication,
7 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
8 | true
9 | }
10 |
11 | // MARK: UISceneSession Lifecycle
12 |
13 | func application(_ application: UIApplication,
14 | configurationForConnecting connectingSceneSession: UISceneSession,
15 | options: UIScene.ConnectionOptions) -> UISceneConfiguration {
16 | UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Maciej Gomółka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/GrowingTextView/GrowinTextView/GrowingTextInputView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct GrowingTextInputView: View {
4 | init(text: Binding, placeholder: String?) {
5 | self._text = text
6 | self.placeholder = placeholder
7 | }
8 |
9 | @Binding var text: String?
10 | @State var focused: Bool = false
11 | @State var contentHeight: CGFloat = 0
12 |
13 | let placeholder: String?
14 | let minHeight: CGFloat = 39
15 | let maxHeight: CGFloat = 150
16 |
17 | var countedHeight: CGFloat {
18 | min(max(minHeight, contentHeight), maxHeight)
19 | }
20 |
21 | var body: some View {
22 | ZStack(alignment: .topLeading) {
23 | Color.white
24 | ZStack(alignment: .topLeading) {
25 | placeholderView
26 | TextViewWrapper(text: $text, focused: $focused, contentHeight: $contentHeight)
27 | }.padding(.horizontal, 4)
28 | }.frame(height: countedHeight)
29 | }
30 |
31 | var placeholderView: some View {
32 | ViewBuilder.buildIf(
33 | showPlaceholder ?
34 | placeholder.map {
35 | Text($0)
36 | .foregroundColor(.gray)
37 | .font(.system(size: 16))
38 | .padding(.vertical, 8)
39 | .padding(.horizontal, 4)
40 | } : nil
41 | )
42 | }
43 |
44 | var showPlaceholder: Bool {
45 | !focused && text.orEmpty.isEmpty == true
46 | }
47 | }
48 |
49 | #if DEBUG
50 | struct GrowingTextInputView_Previews: PreviewProvider {
51 | @State static var text: String?
52 |
53 | static var previews: some View {
54 | GrowingTextInputView(
55 | text: $text,
56 | placeholder: "Placeholder"
57 | )
58 | }
59 | }
60 | #endif
61 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/GrowingTextView/ExampleView/ChatView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct ChatView: View {
4 | @State var text: String?
5 | @State var messages: [Message] = []
6 |
7 | var body: some View {
8 | ZStack {
9 | Color.background
10 | .edgesIgnoringSafeArea(.all)
11 | VStack(spacing: 0) {
12 | HStack(alignment: .center) {
13 | GrowingTextInputView(text: $text, placeholder: "Message")
14 | .cornerRadius(10)
15 | Button(action: sendAction) {
16 | Text("Send")
17 | }
18 | }.padding()
19 | Divider()
20 | ScrollView {
21 | VStack(alignment: .trailing, spacing: 16) {
22 | ForEach(messages, id: \.id) {
23 | self.messageView(text: $0.text)
24 | }
25 | }.padding(.top, 16)
26 | .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .trailing)
27 | }.edgesIgnoringSafeArea(.bottom)
28 | }
29 | }
30 | }
31 |
32 | func sendAction() {
33 | guard let text = text, !text.isEmpty else { return }
34 | let newMessage = Message(text: text)
35 | messages.insert(newMessage, at: 0)
36 | self.text = nil
37 | UIApplication.shared.windows.forEach { $0.endEditing(true)}
38 | }
39 |
40 | func messageView(text: String) -> some View {
41 | return Text(text)
42 | .foregroundColor(.white)
43 | .padding(.all, 12)
44 | .background(Color.messageBackground)
45 | .cornerRadius(14)
46 | .padding(.trailing, 12)
47 | .padding(.leading, 32)
48 | }
49 |
50 | struct Message {
51 | let id = UUID()
52 | let text: String
53 | }
54 | }
55 |
56 | #if DEBUG
57 | struct ContentView_Previews: PreviewProvider {
58 | static var previews: some View {
59 | ChatView()
60 | }
61 | }
62 | #endif
63 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 |
37 |
38 |
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 |
50 | UISupportedInterfaceOrientations~ipad
51 |
52 | UIInterfaceOrientationPortrait
53 | UIInterfaceOrientationPortraitUpsideDown
54 | UIInterfaceOrientationLandscapeLeft
55 | UIInterfaceOrientationLandscapeRight
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/GrowingTextView/SupportingFiles/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/GrowingTextView/GrowinTextView/TextViewWrapper.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct TextViewWrapper: UIViewRepresentable {
4 |
5 | init(text: Binding, focused: Binding, contentHeight: Binding) {
6 | self._text = text
7 | self._focused = focused
8 | self._contentHeight = contentHeight
9 | }
10 |
11 | @Binding var text: String?
12 | @Binding var focused: Bool
13 | @Binding var contentHeight: CGFloat
14 |
15 | // MARK: - UIViewRepresentable
16 |
17 | func makeUIView(context: Context) -> UITextView {
18 | let textView = UITextView()
19 | textView.delegate = context.coordinator
20 | textView.font = .systemFont(ofSize: 16)
21 | textView.backgroundColor = .clear
22 | textView.autocorrectionType = .no
23 | return textView
24 | }
25 |
26 | func makeCoordinator() -> Coordinator {
27 | Coordinator(text: $text, focused: $focused, contentHeight: $contentHeight)
28 | }
29 |
30 | func updateUIView(_ uiView: UITextView, context: Context) {
31 | uiView.text = text
32 | }
33 |
34 | class Coordinator: NSObject, UITextViewDelegate {
35 |
36 | init(text: Binding, focused: Binding, contentHeight: Binding) {
37 | self._text = text
38 | self._focused = focused
39 | self._contentHeight = contentHeight
40 | }
41 |
42 | @Binding private var text: String?
43 | @Binding private var focused: Bool
44 | @Binding private var contentHeight: CGFloat
45 |
46 | // MARK: - UITextViewDelegate
47 |
48 | func textViewDidChange(_ textView: UITextView) {
49 | text = textView.text
50 | contentHeight = textView.contentSize.height
51 | }
52 |
53 | func textViewDidBeginEditing(_ textView: UITextView) {
54 | focused = true
55 | }
56 |
57 | func textViewDidEndEditing(_ textView: UITextView) {
58 | focused = false
59 | contentHeight = text == nil ? 0 : textView.contentSize.height
60 | }
61 | }
62 | }
63 |
64 | #if DEBUG
65 | struct TextViewWrapper_Previews: PreviewProvider {
66 | @State static var text: String?
67 |
68 | static var previews: some View {
69 | TextViewWrapper(text: $text, focused: .constant(false), contentHeight: .constant(0))
70 | }
71 | }
72 | #endif
73 |
--------------------------------------------------------------------------------
/GrowingTextView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 47ABE81B2438A16100C870FD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE81A2438A16100C870FD /* AppDelegate.swift */; };
11 | 47ABE81D2438A16100C870FD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE81C2438A16100C870FD /* SceneDelegate.swift */; };
12 | 47ABE81F2438A16100C870FD /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE81E2438A16100C870FD /* ChatView.swift */; };
13 | 47ABE8212438A16400C870FD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 47ABE8202438A16400C870FD /* Assets.xcassets */; };
14 | 47ABE8272438A16400C870FD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 47ABE8252438A16400C870FD /* LaunchScreen.storyboard */; };
15 | 47ABE84C2438AF1A00C870FD /* TextViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE84B2438AF1A00C870FD /* TextViewWrapper.swift */; };
16 | 47ABE84E2438B74E00C870FD /* GrowingTextInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE84D2438B74E00C870FD /* GrowingTextInputView.swift */; };
17 | 47ABE8562438CCC900C870FD /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ABE8552438CCC900C870FD /* Color.swift */; };
18 | 47BF62372444E27000F8223A /* String+OrEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47BF62362444E27000F8223A /* String+OrEmpty.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 47ABE8172438A16100C870FD /* GrowingTextView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GrowingTextView.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | 47ABE81A2438A16100C870FD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | 47ABE81C2438A16100C870FD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
25 | 47ABE81E2438A16100C870FD /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = ""; };
26 | 47ABE8202438A16400C870FD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | 47ABE8262438A16400C870FD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | 47ABE8282438A16400C870FD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | 47ABE84B2438AF1A00C870FD /* TextViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewWrapper.swift; sourceTree = ""; };
30 | 47ABE84D2438B74E00C870FD /* GrowingTextInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GrowingTextInputView.swift; sourceTree = ""; };
31 | 47ABE8552438CCC900C870FD /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; };
32 | 47BF62362444E27000F8223A /* String+OrEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+OrEmpty.swift"; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | 47ABE8142438A16100C870FD /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | 47ABE80E2438A16100C870FD = {
47 | isa = PBXGroup;
48 | children = (
49 | 47ABE8462438AD8300C870FD /* Frameworks */,
50 | 47ABE8192438A16100C870FD /* GrowingTextView */,
51 | 47ABE8182438A16100C870FD /* Products */,
52 | );
53 | sourceTree = "";
54 | };
55 | 47ABE8182438A16100C870FD /* Products */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 47ABE8172438A16100C870FD /* GrowingTextView.app */,
59 | );
60 | name = Products;
61 | sourceTree = "";
62 | };
63 | 47ABE8192438A16100C870FD /* GrowingTextView */ = {
64 | isa = PBXGroup;
65 | children = (
66 | 47ABE83E2438A2FA00C870FD /* Application */,
67 | 47ABE83F2438A30600C870FD /* ExampleView */,
68 | 47ABE8542438CC5800C870FD /* Extensions */,
69 | 47BF62352444E21600F8223A /* GrowinTextView */,
70 | 47ABE83C2438A2BB00C870FD /* SupportingFiles */,
71 | );
72 | path = GrowingTextView;
73 | sourceTree = "";
74 | };
75 | 47ABE83C2438A2BB00C870FD /* SupportingFiles */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 47ABE8202438A16400C870FD /* Assets.xcassets */,
79 | 47ABE8282438A16400C870FD /* Info.plist */,
80 | 47ABE8252438A16400C870FD /* LaunchScreen.storyboard */,
81 | );
82 | path = SupportingFiles;
83 | sourceTree = "";
84 | };
85 | 47ABE83E2438A2FA00C870FD /* Application */ = {
86 | isa = PBXGroup;
87 | children = (
88 | 47ABE81A2438A16100C870FD /* AppDelegate.swift */,
89 | 47ABE81C2438A16100C870FD /* SceneDelegate.swift */,
90 | );
91 | path = Application;
92 | sourceTree = "";
93 | };
94 | 47ABE83F2438A30600C870FD /* ExampleView */ = {
95 | isa = PBXGroup;
96 | children = (
97 | 47ABE81E2438A16100C870FD /* ChatView.swift */,
98 | );
99 | path = ExampleView;
100 | sourceTree = "";
101 | };
102 | 47ABE8462438AD8300C870FD /* Frameworks */ = {
103 | isa = PBXGroup;
104 | children = (
105 | );
106 | name = Frameworks;
107 | sourceTree = "";
108 | };
109 | 47ABE8542438CC5800C870FD /* Extensions */ = {
110 | isa = PBXGroup;
111 | children = (
112 | 47ABE8552438CCC900C870FD /* Color.swift */,
113 | 47BF62362444E27000F8223A /* String+OrEmpty.swift */,
114 | );
115 | path = Extensions;
116 | sourceTree = "";
117 | };
118 | 47BF62352444E21600F8223A /* GrowinTextView */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 47ABE84D2438B74E00C870FD /* GrowingTextInputView.swift */,
122 | 47ABE84B2438AF1A00C870FD /* TextViewWrapper.swift */,
123 | );
124 | path = GrowinTextView;
125 | sourceTree = "";
126 | };
127 | /* End PBXGroup section */
128 |
129 | /* Begin PBXNativeTarget section */
130 | 47ABE8162438A16100C870FD /* GrowingTextView */ = {
131 | isa = PBXNativeTarget;
132 | buildConfigurationList = 47ABE8362438A16500C870FD /* Build configuration list for PBXNativeTarget "GrowingTextView" */;
133 | buildPhases = (
134 | 47ABE8132438A16100C870FD /* Sources */,
135 | 47ABE8142438A16100C870FD /* Frameworks */,
136 | 47ABE8152438A16100C870FD /* Resources */,
137 | );
138 | buildRules = (
139 | );
140 | dependencies = (
141 | );
142 | name = GrowingTextView;
143 | packageProductDependencies = (
144 | );
145 | productName = GrowingTextView;
146 | productReference = 47ABE8172438A16100C870FD /* GrowingTextView.app */;
147 | productType = "com.apple.product-type.application";
148 | };
149 | /* End PBXNativeTarget section */
150 |
151 | /* Begin PBXProject section */
152 | 47ABE80F2438A16100C870FD /* Project object */ = {
153 | isa = PBXProject;
154 | attributes = {
155 | LastSwiftUpdateCheck = 1140;
156 | LastUpgradeCheck = 1140;
157 | ORGANIZATIONNAME = mg;
158 | TargetAttributes = {
159 | 47ABE8162438A16100C870FD = {
160 | CreatedOnToolsVersion = 11.4;
161 | };
162 | };
163 | };
164 | buildConfigurationList = 47ABE8122438A16100C870FD /* Build configuration list for PBXProject "GrowingTextView" */;
165 | compatibilityVersion = "Xcode 9.3";
166 | developmentRegion = en;
167 | hasScannedForEncodings = 0;
168 | knownRegions = (
169 | en,
170 | Base,
171 | );
172 | mainGroup = 47ABE80E2438A16100C870FD;
173 | packageReferences = (
174 | );
175 | productRefGroup = 47ABE8182438A16100C870FD /* Products */;
176 | projectDirPath = "";
177 | projectRoot = "";
178 | targets = (
179 | 47ABE8162438A16100C870FD /* GrowingTextView */,
180 | );
181 | };
182 | /* End PBXProject section */
183 |
184 | /* Begin PBXResourcesBuildPhase section */
185 | 47ABE8152438A16100C870FD /* Resources */ = {
186 | isa = PBXResourcesBuildPhase;
187 | buildActionMask = 2147483647;
188 | files = (
189 | 47ABE8272438A16400C870FD /* LaunchScreen.storyboard in Resources */,
190 | 47ABE8212438A16400C870FD /* Assets.xcassets in Resources */,
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | /* End PBXResourcesBuildPhase section */
195 |
196 | /* Begin PBXSourcesBuildPhase section */
197 | 47ABE8132438A16100C870FD /* Sources */ = {
198 | isa = PBXSourcesBuildPhase;
199 | buildActionMask = 2147483647;
200 | files = (
201 | 47ABE81B2438A16100C870FD /* AppDelegate.swift in Sources */,
202 | 47ABE84E2438B74E00C870FD /* GrowingTextInputView.swift in Sources */,
203 | 47BF62372444E27000F8223A /* String+OrEmpty.swift in Sources */,
204 | 47ABE84C2438AF1A00C870FD /* TextViewWrapper.swift in Sources */,
205 | 47ABE81D2438A16100C870FD /* SceneDelegate.swift in Sources */,
206 | 47ABE81F2438A16100C870FD /* ChatView.swift in Sources */,
207 | 47ABE8562438CCC900C870FD /* Color.swift in Sources */,
208 | );
209 | runOnlyForDeploymentPostprocessing = 0;
210 | };
211 | /* End PBXSourcesBuildPhase section */
212 |
213 | /* Begin PBXVariantGroup section */
214 | 47ABE8252438A16400C870FD /* LaunchScreen.storyboard */ = {
215 | isa = PBXVariantGroup;
216 | children = (
217 | 47ABE8262438A16400C870FD /* Base */,
218 | );
219 | name = LaunchScreen.storyboard;
220 | sourceTree = "";
221 | };
222 | /* End PBXVariantGroup section */
223 |
224 | /* Begin XCBuildConfiguration section */
225 | 47ABE8342438A16500C870FD /* Debug */ = {
226 | isa = XCBuildConfiguration;
227 | buildSettings = {
228 | ALWAYS_SEARCH_USER_PATHS = NO;
229 | CLANG_ANALYZER_NONNULL = YES;
230 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
231 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
232 | CLANG_CXX_LIBRARY = "libc++";
233 | CLANG_ENABLE_MODULES = YES;
234 | CLANG_ENABLE_OBJC_ARC = YES;
235 | CLANG_ENABLE_OBJC_WEAK = YES;
236 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
237 | CLANG_WARN_BOOL_CONVERSION = YES;
238 | CLANG_WARN_COMMA = YES;
239 | CLANG_WARN_CONSTANT_CONVERSION = YES;
240 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
241 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
242 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
243 | CLANG_WARN_EMPTY_BODY = YES;
244 | CLANG_WARN_ENUM_CONVERSION = YES;
245 | CLANG_WARN_INFINITE_RECURSION = YES;
246 | CLANG_WARN_INT_CONVERSION = YES;
247 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
248 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
249 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
251 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
252 | CLANG_WARN_STRICT_PROTOTYPES = YES;
253 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
254 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
255 | CLANG_WARN_UNREACHABLE_CODE = YES;
256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
257 | COPY_PHASE_STRIP = NO;
258 | DEBUG_INFORMATION_FORMAT = dwarf;
259 | ENABLE_STRICT_OBJC_MSGSEND = YES;
260 | ENABLE_TESTABILITY = YES;
261 | GCC_C_LANGUAGE_STANDARD = gnu11;
262 | GCC_DYNAMIC_NO_PIC = NO;
263 | GCC_NO_COMMON_BLOCKS = YES;
264 | GCC_OPTIMIZATION_LEVEL = 0;
265 | GCC_PREPROCESSOR_DEFINITIONS = (
266 | "DEBUG=1",
267 | "$(inherited)",
268 | );
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
271 | GCC_WARN_UNDECLARED_SELECTOR = YES;
272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273 | GCC_WARN_UNUSED_FUNCTION = YES;
274 | GCC_WARN_UNUSED_VARIABLE = YES;
275 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
276 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
277 | MTL_FAST_MATH = YES;
278 | ONLY_ACTIVE_ARCH = YES;
279 | SDKROOT = iphoneos;
280 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
281 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
282 | };
283 | name = Debug;
284 | };
285 | 47ABE8352438A16500C870FD /* Release */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | ALWAYS_SEARCH_USER_PATHS = NO;
289 | CLANG_ANALYZER_NONNULL = YES;
290 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
292 | CLANG_CXX_LIBRARY = "libc++";
293 | CLANG_ENABLE_MODULES = YES;
294 | CLANG_ENABLE_OBJC_ARC = YES;
295 | CLANG_ENABLE_OBJC_WEAK = YES;
296 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
297 | CLANG_WARN_BOOL_CONVERSION = YES;
298 | CLANG_WARN_COMMA = YES;
299 | CLANG_WARN_CONSTANT_CONVERSION = YES;
300 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
301 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
302 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
303 | CLANG_WARN_EMPTY_BODY = YES;
304 | CLANG_WARN_ENUM_CONVERSION = YES;
305 | CLANG_WARN_INFINITE_RECURSION = YES;
306 | CLANG_WARN_INT_CONVERSION = YES;
307 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
308 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
309 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
311 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
312 | CLANG_WARN_STRICT_PROTOTYPES = YES;
313 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
314 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
315 | CLANG_WARN_UNREACHABLE_CODE = YES;
316 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
317 | COPY_PHASE_STRIP = NO;
318 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
319 | ENABLE_NS_ASSERTIONS = NO;
320 | ENABLE_STRICT_OBJC_MSGSEND = YES;
321 | GCC_C_LANGUAGE_STANDARD = gnu11;
322 | GCC_NO_COMMON_BLOCKS = YES;
323 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
324 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
325 | GCC_WARN_UNDECLARED_SELECTOR = YES;
326 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
327 | GCC_WARN_UNUSED_FUNCTION = YES;
328 | GCC_WARN_UNUSED_VARIABLE = YES;
329 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
330 | MTL_ENABLE_DEBUG_INFO = NO;
331 | MTL_FAST_MATH = YES;
332 | SDKROOT = iphoneos;
333 | SWIFT_COMPILATION_MODE = wholemodule;
334 | SWIFT_OPTIMIZATION_LEVEL = "-O";
335 | VALIDATE_PRODUCT = YES;
336 | };
337 | name = Release;
338 | };
339 | 47ABE8372438A16500C870FD /* Debug */ = {
340 | isa = XCBuildConfiguration;
341 | buildSettings = {
342 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
343 | CODE_SIGN_STYLE = Automatic;
344 | DEVELOPMENT_TEAM = XRT2TCPYP7;
345 | ENABLE_PREVIEWS = YES;
346 | INFOPLIST_FILE = GrowingTextView/SupportingFiles/Info.plist;
347 | LD_RUNPATH_SEARCH_PATHS = (
348 | "$(inherited)",
349 | "@executable_path/Frameworks",
350 | );
351 | PRODUCT_BUNDLE_IDENTIFIER = com.mg.GrowingTextView;
352 | PRODUCT_NAME = "$(TARGET_NAME)";
353 | SWIFT_VERSION = 5.0;
354 | TARGETED_DEVICE_FAMILY = "1,2";
355 | };
356 | name = Debug;
357 | };
358 | 47ABE8382438A16500C870FD /* Release */ = {
359 | isa = XCBuildConfiguration;
360 | buildSettings = {
361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
362 | CODE_SIGN_STYLE = Automatic;
363 | DEVELOPMENT_TEAM = XRT2TCPYP7;
364 | ENABLE_PREVIEWS = YES;
365 | INFOPLIST_FILE = GrowingTextView/SupportingFiles/Info.plist;
366 | LD_RUNPATH_SEARCH_PATHS = (
367 | "$(inherited)",
368 | "@executable_path/Frameworks",
369 | );
370 | PRODUCT_BUNDLE_IDENTIFIER = com.mg.GrowingTextView;
371 | PRODUCT_NAME = "$(TARGET_NAME)";
372 | SWIFT_VERSION = 5.0;
373 | TARGETED_DEVICE_FAMILY = "1,2";
374 | };
375 | name = Release;
376 | };
377 | /* End XCBuildConfiguration section */
378 |
379 | /* Begin XCConfigurationList section */
380 | 47ABE8122438A16100C870FD /* Build configuration list for PBXProject "GrowingTextView" */ = {
381 | isa = XCConfigurationList;
382 | buildConfigurations = (
383 | 47ABE8342438A16500C870FD /* Debug */,
384 | 47ABE8352438A16500C870FD /* Release */,
385 | );
386 | defaultConfigurationIsVisible = 0;
387 | defaultConfigurationName = Release;
388 | };
389 | 47ABE8362438A16500C870FD /* Build configuration list for PBXNativeTarget "GrowingTextView" */ = {
390 | isa = XCConfigurationList;
391 | buildConfigurations = (
392 | 47ABE8372438A16500C870FD /* Debug */,
393 | 47ABE8382438A16500C870FD /* Release */,
394 | );
395 | defaultConfigurationIsVisible = 0;
396 | defaultConfigurationName = Release;
397 | };
398 | /* End XCConfigurationList section */
399 | };
400 | rootObject = 47ABE80F2438A16100C870FD /* Project object */;
401 | }
402 |
--------------------------------------------------------------------------------