Created
April 14, 2016 03:45
-
-
Save wh1pch81n/585451344947db8c645fce0cee62c37d to your computer and use it in GitHub Desktop.
UITextView supports clinking a link and going directly to the website, but sometimes you want that "link" to act like a button so you can do something else when you click it. In this example we have ""no-opclickno-op"" where "click" is a link that will print "hello world"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import XCPlayground | |
class ClickableLinkTextView: UITextView { | |
override init(frame: CGRect, textContainer: NSTextContainer?) { | |
super.init(frame: frame, textContainer: textContainer) | |
setUp() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
setUp() | |
} | |
func setUp() { | |
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ClickableLinkTextView.tappedView(_:)))) | |
} | |
func tappedView(gesture: UITapGestureRecognizer) { | |
var location: CGPoint = gesture.locationInView(self) | |
location.x -= textContainerInset.left | |
location.y -= textContainerInset.top | |
let characterIndex: Int = Int(layoutManager.characterIndexForPoint(location, inTextContainer:textContainer, fractionOfDistanceBetweenInsertionPoints: nil)) | |
if case 0..<textStorage.length = characterIndex { | |
let value: AnyObject? = attributedText.attribute(LinkStringHelper.linkAttributeName, atIndex:characterIndex, effectiveRange:nil) | |
if let v = value as? LinkStringAction { | |
v.action() | |
} | |
} | |
} | |
} | |
class LinkStringAction: NSObject { | |
let text: String | |
let action: () -> () | |
init(text: String, action: () -> ()) { | |
self.text = text | |
self.action = action | |
} | |
} | |
struct LinkStringHelper: StringInterpolationConvertible { | |
static let linkAttributeName: String = "\(String(LinkStringHelper)).linkAttributedName" | |
private var plainString: String? | |
private var linkAction: LinkStringAction? | |
private var linkObjects: [LinkStringHelper] = [] | |
/// every segment created by init<T>(stringInterpolationSegment expr: T) will come here as an array of Segments. | |
init(stringInterpolation strings: LinkStringHelper...) { | |
linkObjects = strings // Keep as disparate segments | |
} | |
/// the string literal is broken up into intervals of all string and \(..) which are called segments | |
init<T>(stringInterpolationSegment expr: T) { | |
if let lk = expr as? LinkStringAction { | |
linkAction = lk | |
} else { | |
plainString = String(expr) | |
} | |
} | |
/// Combines all segments and applys attributes to it. | |
func attributedStringWithAttributes(attributes: [String : AnyObject]) -> NSAttributedString { | |
let mut = NSMutableAttributedString() | |
for i in linkObjects { | |
let t = (i.plainString, i.linkAction) | |
if case (nil, let x?) = t { | |
var newAttributes = attributes | |
newAttributes[NSLinkAttributeName] = NSURL(string: "http://www.google.com")!// For link color | |
newAttributes[LinkStringHelper.linkAttributeName] = x | |
mut.appendAttributedString(NSAttributedString(string: x.text, attributes: newAttributes)) | |
} else if case (let y?, nil) = t { | |
mut.appendAttributedString(NSAttributedString(string: y, attributes: attributes)) | |
} | |
} | |
mut.appendAttributedString(NSAttributedString(string: "\0")) // To prevent taps from registering if after clickable text. | |
return mut | |
} | |
} | |
//Example | |
var textview: ClickableLinkTextView = ClickableLinkTextView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 100, height: 100)), textContainer: nil) | |
let action = LinkStringAction(text: "click", action: { print("hello world") }) | |
let cs: LinkStringHelper = "no-op\(action)no-op" | |
textview.attributedText = cs.attributedStringWithAttributes([:]) | |
XCPlaygroundPage.currentPage.liveView = textview |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment