Skip to content

Instantly share code, notes, and snippets.

@brunopinheiro
Last active September 18, 2017 21:30
Show Gist options
  • Save brunopinheiro/d6560bbaf244cf8df5d0aeb1edf06317 to your computer and use it in GitHub Desktop.
Save brunopinheiro/d6560bbaf244cf8df5d0aeb1edf06317 to your computer and use it in GitHub Desktop.
Extended UITextView with Placeholder
//
// TextViewWithPlaceholder.swift
//
// Created by Bruno Pinheiro on 13/09/17.
// Copyright © 2017 Bruno Pinheiro. All rights reserved.
//
import UIKit
@IBDesignable
class TextViewWithPlaceholder: UITextView {
let placeholder: UITextView
@IBInspectable var placeholderTextColor: UIColor = UIColor.lightGray {
didSet {
placeholder.textColor = placeholderTextColor
}
}
@IBInspectable var placeholderText: String = "" {
didSet {
placeholder.text = placeholderText
}
}
required init?(coder aDecoder: NSCoder) {
self.placeholder = UITextView(frame: CGRect.zero)
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
self.placeholder = UITextView(frame: frame)
super.init(frame: frame, textContainer: nil)
setup()
}
private func setup() {
layoutMargins = UIEdgeInsets()
configurePlaceholder()
setNeedsUpdateConstraints()
}
private func configurePlaceholder() {
placeholder.isEditable = false
placeholder.isUserInteractionEnabled = false
placeholder.backgroundColor = UIColor.clear
placeholder.translatesAutoresizingMaskIntoConstraints = false
addSubview(placeholder)
}
override func becomeFirstResponder() -> Bool {
placeholder.isHidden = true
return super.becomeFirstResponder()
}
override func resignFirstResponder() -> Bool {
placeholder.isHidden = !text.isEmpty
return super.resignFirstResponder()
}
override func updateConstraints() {
super.updateConstraints()
guard !constraintsAlreadySet else {
return
}
constraintsAlreadySet = true
createPlaceholderConstraints()
}
private func createPlaceholderConstraints() {
placeholder.centerXAnchor.constraint(equalTo: layoutMarginsGuide.centerXAnchor).isActive = true
placeholder.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true
placeholder.widthAnchor.constraint(equalTo: layoutMarginsGuide.widthAnchor).isActive = true
placeholder.heightAnchor.constraint(equalTo: layoutMarginsGuide.heightAnchor).isActive = true
}
private var constraintsAlreadySet = false
}
//
// TextViewWithPlaceholderTests.swift
//
// Created by Bruno Pinheiro on 13/09/17.
// Copyright © 2017 Bruno Pinheiro. All rights reserved.
//
import XCTest
@testable import ExtendedTextView
class TextViewWithPlaceholderTests: XCTestCase {
override func setUp() {
super.setUp()
textView = TextViewWithPlaceholder(frame: CGRect.zero)
_ = textView.becomeFirstResponder()
}
func testWhenIsEmptyPlaceholderShouldNotBeHidden() {
textView.text = ""
_ = textView.resignFirstResponder()
XCTAssertFalse(textView.placeholder.isHidden)
}
func testWhenContainsTextPlaceholderShouldBeHidden() {
textView.text = "Hello World!"
_ = textView.resignFirstResponder()
XCTAssertTrue(textView.placeholder.isHidden)
}
func testPlaceholderColorShouldChangePlaceholderTextColor() {
textView.placeholderTextColor = UIColor.green
XCTAssertEqual(textView.placeholder.textColor, UIColor.green)
}
func testPlaceholderTextShouldChangePlaceholderText() {
textView.placeholderText = "Hello!"
XCTAssertEqual(textView.placeholder.text, "Hello!")
}
private var textView: TextViewWithPlaceholder!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment