Apologies
You must be signed in to watch this lesson.
Multi-line UITextView Input
Instagram Firebase
Implementing a multi-line input area that is anchored above the bottom home indicator view can be difficult. In today's video I'll show you how to use autoResizingMask to get this working.

Comments (51)
smiller193
6 years ago
my textview is not autowrapping it just goes off the screen. Any idea why?
Brian Voong
6 years ago
smiller193
6 years ago
This is my entire code // // CommentInputAccessoryView.swift // Eventful // // Created by Shawn Miller on 1/5/18. // Copyright © 2018 Make School. All rights reserved. // import UIKit protocol CommentInputAccessoryViewDelegate { func handleSubmit(for comment: String?) } class CommentInputAccessoryView: UIView, UITextViewDelegate { var delegate: CommentInputAccessoryViewDelegate? /* // Only override draw() if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func draw(_ rect: CGRect) { // Drawing code } */ fileprivate let submitButton: UIButton = { let submitButton = UIButton(type: .system) submitButton.setTitle("Submit", for: .normal) submitButton.setTitleColor(.black, for: .normal) submitButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14) submitButton.addTarget(self, action: #selector(handleSubmit), for: .touchUpInside) //submitButton.isEnabled = false return submitButton }() lazy var commentTextView: CommentInputTextView = { let textView = CommentInputTextView() // textView.placeholder = "Add a comment" textView.delegate = self textView.isScrollEnabled = false textView.backgroundColor = .red textView.font = UIFont.boldSystemFont(ofSize: 12) textView.textContainer.lineBreakMode = .byWordWrapping // textView.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) return textView }() override init(frame: CGRect) { super.init(frame: frame) // backgroundColor = .red //1 autoresizingMask = .flexibleHeight addSubview(submitButton) submitButton.anchor(top: topAnchor, left: nil, bottom: bottomAnchor, right:rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 12, width: 50, height: 0) addSubview(commentTextView) //3 if #available(iOS 11.0, *){ commentTextView.anchor(top: topAnchor, left: leftAnchor, bottom: safeAreaLayoutGuide.bottomAnchor, right: submitButton.leftAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 0, width: 0, height: 0) }else{ //fallback on earlier versions } setupLineSeparatorView() } //2 override var intrinsicContentSize: CGSize{ return .zero } fileprivate func setupLineSeparatorView(){ let lineSeparatorView = UIView() lineSeparatorView.backgroundColor = UIColor.rgb(red: 230, green: 230, blue: 230) addSubview(lineSeparatorView) lineSeparatorView.anchor(top:topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0.5) } @objc func handleSubmit(){ guard let commentText = commentTextView.text else{ return } delegate?.handleSubmit(for: commentText) } @objc func textFieldDidChange(_ textField: UITextView) { let isCommentValid = commentTextView.text?.count ?? 0 > 0 if isCommentValid { submitButton.isEnabled = true }else{ submitButton.isEnabled = false } } func clearCommentTextField(){ commentTextView.text = nil commentTextView.showPlaceholderLabel() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } You notice anything wrong
smiller193
6 years ago
I followed that simialr to how you did it in the video see my above code
Brian Voong
6 years ago
Brian Voong
6 years ago
smiller193
6 years ago
okay Ill try that now. Also I am running 11.1 and xCode 9.2
smiller193
6 years ago
I cant run in I keep getting these erorrs even when i change the googleplist diff: /Podfile.lock: No such file or directory diff: /Manifest.lock: No such file or directory error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
Brian Voong
6 years ago
smiller193
6 years ago
seems to work on yours. Now im all the way lost
smiller193
6 years ago
would it have anything to do with my contianer view lazy var containerView: CommentInputAccessoryView = { let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 50) let commentInputAccessoryView = CommentInputAccessoryView(frame:frame) commentInputAccessoryView.delegate = self return commentInputAccessoryView }() or my anchor's containerView.anchor(top: nil, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 40)
smiller193
6 years ago
Im also not overriding the input accessory view
Brian Voong
6 years ago
smiller193
6 years ago
https://github.com/Smiller193/EventfulApp1
smiller193
6 years ago
go to newCommentsViewController to view implementation
smiller193
6 years ago
lmk if you need login
smiller193
6 years ago
asfdf@mail.com Gohan114
Brian Voong
6 years ago
smiller193
6 years ago
thank you for taking the time out to help me. Maybe when im done you can bless me with an app review on your channel
Alpensol
6 years ago
Hey Brian, Happy New Year to You, I wish you and your family all the best! And I can't wait for see the future content from you. The way I handled the Placeholder appearance/disappearance was through conforming to the UITextViewDelegate and then using the textViewDidChange func. func textViewDidChange(_ textView: UITextView) { if textView.text.isEmpty { placeholderLabel.text = placeholderText } else { placeholderLabel.text = nil } } Works great, just wondering if there any drawback when compared to notifications/observers pattern
Brian Voong
6 years ago
stonypig1
6 years ago
MR.brian : what you mean by rerouted the delegate call ? why it won't fire if it work in this case ? thanks
stonypig1
6 years ago
MR.brian : what you mean by rerouted the delegate call ? why it won't fire if it work in this case ? thanks
stonypig1
6 years ago
sorry bad internet connection at Starbucks, don't mean to send twice
BellRinging
6 years ago
Thanks very much . That is what i am looking for .=]
mattphelps
6 years ago
Hey guys, Does anyone know which video Brian runs through the followers, following, posts adjustments in the user profile header? It’s an important part of the user experience that I can’t find. Cheers
Obrac
6 years ago
Hey Matt, So far the following/unfollowing logic was left off in the button implementation. As for the logic of actually modifying Firebase to update that info, It seems we are all still waiting on that.
Stephan Dowless
6 years ago
email me at dowless.stephan@gmail.com if you would like to see videos on how to do home feed pagination, hashtags/mentions, direct messaging, search feed with posts, and more.
Arvid Schneider
6 years ago
Subclassing UITextView to add custom placeholder label is gold! Thanks for sharing this.
Yunio
6 years ago
hey man great course learn a lot really appreciate you I know it kinda suck very one tell u you shroud do this next you shroud do this I bet ur like ooo shroud I lol but I was thinking theres no other guy to do it but you really and app that requires a regular user that consumes and another that requires the user thats making the service like lets say uber driver and the user using uber but u can make like a handy man app and the users that need the service and the user thats providing the service sorry to go ham but theres no other guy to do it than you and thanx man Brian the GOAT
Stephan Dowless
6 years ago
email me at dowless.stephan@gmail.com if you would like to see videos on how to do home feed pagination, hashtags/mentions, direct messaging, search feed with posts, and more.
tobitech
6 years ago
Hello Brian, there is a little problem with the textview. You disabled scrolling in the tutorial, which means the text view just keeps growing as long as possible and if the text inside of it is very long (i mean like a paragraph from a book), it just grows and fills the enter screen. There should be a way to enable scrolling when the text view grows to a certain height.
Brian Voong
6 years ago
juliolocoh
6 years ago
show us how to block users please that will help
Brian Voong
6 years ago
juliolocoh
6 years ago
both if that can be possible thanks
David Wu
6 years ago
Thanks for the awesome work Brian! This is so helpful as designing the input of a collectionViewController. I'm doing something that seems to be very similar to this video but I'm doing it from a view class rather than a ViewController class; thus I cannot enjoy the convenience of inputAccessoryView. Rather, I need to manually place the input container on the top of the keyboard and move it with the exact animation of the keyboard, which is not easy but possible. My question comes down to resizing the containerView. The only thing I can achieve so far is to grow its size from top to bottom (i.e. with its origin fixed) which is definitely not good at all (since we need to make it group upward).
Manoj Kumar
6 years ago
Thank you for guidance on this. Based on this I am implementing a postInputView. In one of my projects. I have view queries on this topic 1. How do I animate the input accessory height changes when one of the subviews height changes? 2. How to restrict the height of InputAccessoryView height till toolbar when keyboard is up?
Manoj Kumar
6 years ago
Hi, Hope you are not busy. It would be helpful if you can suggest tips on how to achieve them.
stonypig1
6 years ago
how can we limit the lines ? wechat has this similar feature, but only limit to 4 lines, after that it scrolls which make good sense because if user keep typing , we should not allow them auto scroll up 100 lines. anyone got any idea to do it ? thanks
marek.chojecki
6 years ago
Hi Brain I think your solution about safeArea with inputAccessoryView has a bug. If you'll try to scroll collection view down to dissmis a keyboard, and you make it slowly, then the app will crash after inputAccessoryView reach safe area. I tested it in mine and your app and it's crashing in both :/
sconrad8
6 years ago
I am having the same issue and would love a fix. Thank you!
marek.chojecki
6 years ago
If you are asking how I fixed it, I installed a pod called “device kit” which let you define what iphone user is using. You can find it easliy in google. Now I just check device and If it’s an iPhoneX I set collectionView.keyboardDissmis on .onDrag and if any different device to .interactive. It’s a half measure but works.
albert
6 years ago
Hope we can learn more about unit test and ui test in the real world swift!
jeremysua
6 years ago
Hi Brian my container view doesn't expand with the textView. The container view stays fixed to the frame height of 50 and the textview expands but is hidden :( I have no idea why this happening! Any suggestions?
caquillo07
6 years ago
Hi Brian, I noticed that the collection view holding the comments is not resizing properly behind the keyboard once it comes up. How do you make it stop at the top fo the keyboard so you can scroll to bottom of list? Thanks
marek.chojecki
6 years ago
Does anyone knows how to set a limit of lines where after for eg. 4 lines we can scrollntext - like in any other messenger app?
Brian Voong
6 years ago
Mohammed Aziz
6 years ago
Where to specify that.....Container view or text view. as the text ... Say i need to stop after a height of 150 and make the textview scrollable as most of the chat application do where should i do that
patrick.bellot
6 years ago
Brian, thank you for putting this course together. I've learned more in the past month and a half then I ever had before. Thank you.
Kirill Kudaev
6 years ago
Hey Brian! Thank you so much for your work! I'm interning as an iOS developer in SF next summer and a lot of my knowledge comes from your tutorials and youtube videos. The current app crashes if you drag the newsfeed down to refresh it 2 or 3 times. I'm not exactly sure how to fix that yet. Could you please address it in your next tutorial?
joeypozzyclinch
5 years ago
did you ever figure out why this is happening? I get a "Thread 1: Fatal error: Index out of range" and the app crashes whenever I drag down the newsfeed to refresh it
Hans Rietmann
6 years ago
Hey Brian ! I hope you're doing good.
Stephan Dowless
6 years ago
email me at dowless.stephan@gmail.com if you would like to see videos on how to do home feed pagination, hashtags/mentions, direct messaging, search feed with posts, and more.
aps17
6 years ago
Hi Brian, how do you scroll the collection view up so the comments dont hide under the keyboard? Thanks
Brian Voong
6 years ago
esong2288
5 years ago
I set up an observer using NotificationCenter to oberve when the keyboard pops up and the selector function would use collectionView.scrollToItem to scroll up to the latest comment. Not sure if that is what you wanted
Viswa Kodela
5 years ago
Comments are hiding under the keyboard, can't able to scroll the cells when the Keyboard is on the screen.
Anirudh Bandi
6 years ago
for removing the placeholder text I did this. I set the delegate to self in the init method of the CommentInputAccessoryView commentTextView.delegate = self then implemented the following protocol function func textViewDidChange(_ textView: UITextView) { guard let textView = textView as? CommentInputTextView else { return } if let text = textView.text, text.count > 0{ textView.removePlaceholderLabel() }else { textView.addPlaceholderLabel() } } I added two functions in the CustomInputTextView which add and remove the placeholder label Is this is a good approach ?
Anirudh Bandi
6 years ago
by remove and adding i meant hiding and unhiding the label just like you did
edison1
6 years ago
Please add how to block users. Blocking them, so they don't see your stuff and can't reach you. Has anyone figured this out? URGENT help.
jw76
6 years ago
can you add the story highlights feature
edison1
5 years ago
I can show the number of people who liked the post, but how would you show, who has liked it?
PreachOnBerto
5 years ago
Hey Brain, My app is crashing one I put the override var canBecomeFirstResponder: Bool { return true } property. When I comment it out I can see a red inputAccessoryView for test, when I uncomment it the app crashes with a Thread 1: signal SIGABRT error. I'm not sure why it is doing that. I'm pretty sure my InputTextView, InputAccessoryView, and InputAccessoryViewDelegate are set up correctly. The error message in the debug console also says: "Unable to register for remote notifications: remote notifications are not supported in the simulator" In need of some assistance.
edison1
5 years ago
How can an user update their profile picture once they're in the app?
Maximilian Osborne
5 years ago
Has anyone figured out how to do an equivalent of addTarget... submitButton.isEnabled = true/false for the UITextView? it is straight forward for UITextFields, however does not work with UITextView. I have tried to get around this by making two functions in CommentInputAccessoryView: func validSubmitButton() { submitButton.isEnabled = true } func inValidSubmitButton() { submitButton.isEnabled = false } and in delegate this in CommentInputTextView: @objc func handleTextChange() { placeholderLabel.isHidden = !self.text.isEmpty // need to update submit button here as this is the only spot that reacts to text changes perhaps a delegate needs to be added somewher if self.text.count > 0 { containerView.validSubmitButton() } else { containerView.inValidSubmitButton() } } the simulator can be compiled but the nothing happens
Maximilian Osborne
5 years ago
Re: container view in CommentInputTextView I have lazy var containerView: CommentInputAccessoryView = { let commentInputAccessoryView = CommentInputAccessoryView() return commentInputAccessoryView }()
Maximilian Osborne
5 years ago
solved it... I went about it the wrong way. so ignore the above. inside CommentInputAccessoryView: step 1: in override init(frame: CGRect) {... //add NotificationCenter.default.addObserver(self, selector: #selector(handleTextChange), name: .UITextViewTextDidChange, object: nil) } step 2: add the following functions in the class @objc func handleTextChange() { if commentTextView.text.count > 0 { validSubmitButton() } else { inValidSubmitButton() } } func validSubmitButton() { submitButton.isEnabled = true } func inValidSubmitButton() { submitButton.isEnabled = false }
esong2288
5 years ago
Has anyone found how to adjust the followers/following labels to match the correct numbers?
edison1
5 years ago
you have to create a new node
sharapov0140
5 years ago
what do you mean by node? node js?
edison1
5 years ago
just a new tree structure in database. nothing node
esong2288
5 years ago
I'm trying to fix the last comment being hidden by the text view by setting content insets for the collection view in viewDidLoad(), but it doesn't seem to be working. Am I missing something else?
esong2288
5 years ago
Nvm I moved it to viewDidAppear so I think it's all good now
edison1
5 years ago
so I'm trying to dismiss the keyboard when an user submits a comment, but if I do endEditing(True) doesn't work and resignfirstResponder does work, but it completely hides the inputaccessary view
TWei
5 years ago
@objc func handleSubmit() { guard let uid = Auth.auth().currentUser?.uid else { return } let postId = post?.id ?? "" let values = ["text": commentTextField.text ?? "", "creationData": Date().timeIntervalSince1970, "uid":uid ] as [String : Any] Database.database().reference().child("comments").child(postId).childByAutoId().updateChildValues(values) { (err, ref) in if let err = err { print("Failed to insert commnet:", err) return } print("Successfully inserted comment.") } commentTextField.resignFirstResponder() <<<<< commentTextField.text = "" <<<<< }
joeypozzyclinch
5 years ago
The app crashes when I try and refresh the home feed. This happened for the first time after I tried following someone new, but still persists when I unfollowed them. Am I the only one encountering this? Any idea why this might be happening? I can provide any source code you may need! Btw, this question is for Brian or anyone else who may have encountered this. Thanks for you help in advance!
Shahrukh Mohammad
5 years ago
What episode you're on? This problem normally occurs when indexPath is out of range when the app sets up the number of collectionView cells. This is my code that works for refreshing. Note Photos represent Posts in this case: override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! PhotoCell // Accounting for collectionView refresh if indexPath.item < photos.count { cell.photo = photos[indexPath.item] } self.photo = cell.photo cell.delegate = self return cell }
edison1
5 years ago
Hello, Brian, How will we move to Cloud FireStore, if we wanted to with this project? Would you recommend ?
Brian Voong
5 years ago
proogramer
5 years ago
Hello Mr. Voong! Can you help me, to set a limit of lines where after for eg. 4 lines we can scrollingText. I can't correctly understand where should I set maximumHeight ?
Anand Sharma
5 years ago
Hello, Have you got this solution, I am also trying this but I am not able to find any solution.
flashtrend
5 years ago
Hi Brian, I've followed all your videos and really enjoyed them. In the preview video of this course the followers and following count changes when you follow someone. I don't know if I missed that or if its not in the course. If so, can you please show us or explain to us how to do that?
edison1
5 years ago
Can you show us how to paginate the home feed ? you forgot about your best course Brian . :(
solimanjuanito@gmail.com
5 years ago
Hello, Can someone help me hide the CommentInputAccessoryView when tapping anywhere in the page.Thank you in advance
Alex Grinberg
5 years ago
Hi Brian (or anyone who can help me :) ) I want to create a table view that is expandable, I mean, if you have 2 cells, the table view side should be only the size of the 2 cells.... if it's 3, the same, etc... Any ideas?
Jovin Delfin
5 years ago
get the table view's content size then you can assign that content size to the table view's actual frame.
Brian Voong
5 years ago
Alex Grinberg
5 years ago
Thanks! Will try this soon
malrhex
5 years ago
Question: How do I deal with the InputAccessoryView on this new implementation when it get stuck at the bottom when somebody pulls out to write and hits the back button (homeFeed now), because the previous fix was Adding this line "commentTextField.resignFirstResponder()" in viewWillDisappear method in CommentsController.swift | but now I cannot access a viewWillDisappear on CommentInputAccesoryView class or CommentInputTextView class. So how can I access the InputAccessoryView to be removed from stucked homeFeed ?
cdarbs11
5 years ago
Is there a fully compiled Xcode Project with all of the features in one project?
lxirsh
4 years ago
Thanks for the great course, Brian!
Clint Larenz Nurse
4 years ago
So when I enter a caption for a photo, and choose not to type any text. The placeholder " Add a caption" is entered as the caption. How can I fix this?
Clint Larenz Nurse
4 years ago
I could try disabling the share button. But for good UX I would like for users to have the option to choose if they want to share their image or not.
Clint Larenz Nurse
4 years ago
I dont know if this is a bug, but in the comment section you can actually click on another users comment and edit their text. Assuming because we changed it to a textView. How can I fix this?
Clint Larenz Nurse
4 years ago
So disabling textViewUserInteraction fixes it . However will I have an issue if I want a user to click on the username or profile to take them to that clicked profile? Since interaction is set too false?
Cinquain
4 years ago
More fire
Cinquain
4 years ago
The Instagram course was dope! Definitely worth a rewatch.
KwokPing Lau
4 years ago
Hi Brian, I have a question on UITextView with Multiple lines. What is your approach if you want the UITextView to be scrollable after certain number of lines and also be able to truncate the sentences when it resignFirstResponder? Thank you.
Gündüz Gürel
4 years ago
Hello Brian. What must I change exactly so that only videos can be selected?
Brian Voong
4 years ago
Gündüz Gürel
4 years ago
That means I need to change PhotoSelectorController = VideoSelectorControllr, PhotoSelectorCell = VideoSelectorCell, PhotoSelectorHeader = VideoSelectorHeader SharePhotoController = ShareVideoController ???
Gündüz Gürel
4 years ago
it does not work. I would be very grateful for an aid :-( :-( :-( :-(
Gündüz Gürel
4 years ago
I apologize if I ask a lot but I'm not sure how to change the position of logo image. I want it a bit more downstairs
pvanides
4 years ago
Hi Brian, I just bought the course...It looks great. I have a quick question for you..Have you done, or will you consider doing a course on a view more/view less UITextView inside a tableview? For instance, a text view that you can shrink and expand inside a tableview cell? The one I am using in my project I got from here...https://github.com/ilyapuchka/ReadMoreTextView. It seems to work ok, but I am having a hard time understanding it and would prefer putting something in that I understand and can customize. Plus, I am getting some unwanted side affects from attempting to customize it. Anyway, hope you consider doing this in the future. Thank you for this tutorial series. Paul
HELP & SUPPORT