iOS Swift - Add target(selector) to string - ios

Is there a way to add a target to a specified word from an UITextView? For example.
I want to add a target to a hash-tagged word from a UITextView.
I'm using a function to get an array with the hash-tagged words from the textview, but I don't know how to add them a target, or a tap-gesture.

You can use an attributed string to set the text in the text view. That attributed string uses link attributes (NSLinkAttributeName with a URL value of your choice) in the range of your target hash-tagged words. You need to search the text for your hash-tagged words and add the appropriate link attributes. You probably want to create the link URLs to have a custom scheme and include information about the hash-tagged word. When one of the links is tapped you get a delegate callback from the text view.

I had the same question recently and I found a solution that fit my needs. It's not perfect but maybe it will help:
I decided to go for a whole text button with specific style around my target element. In a user experience way, user may be inclined to touch the styled word.
#IBOutlet weak var stringBtn: UIButton!
override func viewWillAppear(animated: Bool) {
let string = "string with #tag" as NSString
var attributedString = NSMutableAttributedString(string: string as String)
let firstAttributes = [NSUnderlineStyleAttributeName: 1, NSForegroundColorAttributeName: UIColor.whiteColor()]
attributedString.addAttributes(firstAttributes, range: string.rangeOfString("#tag"))
stringBtn.setAttributedTitle(attributedString, forState: .Normal)
//Add target to your button
}

Related

Instantly format a UITextView using AttributedString

I'm developing a macOS rich-text editor that applies pre-defined style for each line of the text view.
To format the lines, I'm using NSAttributedString, then, I'm inserting that string into my UITextView. To make things easier, I'm using a tool called SwiftRichString.
My code looks like below. It's straight-forward and works fine.
import Cocoa
import SwiftRichString
import AppKit
class ViewController: NSViewController {
#IBOutlet var textView: NSTextView!
override func viewDidLoad() {
super.viewDidLoad()
// Format the string
let style = Style {
$0.font = NSFont(name: "Arial", size: 20)
$0.color = NSColor.black
$0.alignment = .center
}
let attributedText = "Hello World!".set(style: style)
// Add formatted string to the text view
textView.textStorage?.append(attributedText)
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
Current situation:
User is typing a formatted line. Then when user hits Return and types something, format of the new line returns back to the default style of the UITextView.
What I want:
User is typing a certain formatted line, then he hits Return. The next line should be formatted to another pre-defined style on-the-go.
Example:
User is typing the Title line. Current style is (Arial, bold, 20pt).
He hits Return.
Next line should be styled as Normal Text using a pre-defined style (Arial, 12pt).
Important Note:
In my above code, I was able to format the line easily because it's hard-coded. My real issue is, how can I instantly format the next line, because the next line will be entered by the user. The style should be applied to the next line before user begins writing it.
Okay, I just figured out how to use typingAttributtes to solve this question (thanks to #Larme for the hint).
// Define next attributes
let attributes: [NSAttributedString.Key: Any] = [
.foregroundColor: NSColor.red,
.font: NSFont(name: "Arial", size: 12)!,
]
// Assign attributes to the text view typing attributes
textView.typingAttributes = attributes
Very easy!
Pardon off topic. If you're making a text editor, you may consider using a table view, where each text line is a cell - this is extra work for you as a programmer but it'll boost the performance significantly. That's how Xcode editor is built.
Maybe you might use optional func textViewDidChange(_ textView: UITextView)
https://developer.apple.com/documentation/uikit/uitextviewdelegate/1618599-textviewdidchange
and after the change, just parse the text, find new lines, split them and apply all styling you want

Xcode How read numbers on a Text View (or label?)

this is my first post.
I'm new in the Xcode Word.
At the moment I'm working to a simple application and I need to read a number from a box and after a lot of calculations write the result in an other text view or label.
I need how to read a numbers or a string from a box after writing (text view, label or other).
Thank you very much for your answers
if you are sure that your textfield will accept only numbers, one of the possible ways could be:
yourTextField.keyboardType = UIKeyboardType.decimalPad
in this way, when the user will tap on the textField, you may use the numeric keypad.
At this point your viewController must implement UItextFieldDelegate
yourTextField.delegate = self
and then use the method, called when textfield loses focus:
func textFieldDidEndEditing(_ textField: UITextField) {
var valueInserted : Float = NSString(string: textField.text!).floatValue
}
Drag a UITextView inside the scene (in the storyboard)
Create an outlet between the UITextView and ViewController.swift
in ViewController.swift you will have something like this:
#IBOutlet weak var myTextView:UITextView!
You must also get a reference for your label
#IBOutlet weak var myLabel:UILabel!
you can now access to the content(input) of your textView by checking the text property:
var input = myTextView.text
This will be a string, that you can try to convert to an Int. Once you have a result to display, set the label text:
myLabel.text = result

Structuring UIViewControllers with images inside of text

I have to create an application that has 5 UIViewControllers, each with big text and images inside the text. What I have done so far was to add a UITextView in the UIViewController and load with an rtf file the whole text (every text is big).
Now I have to add images inside the text in some places. What do you propose that could be the best way to construct it? I tried to add the image inside the the rtf file but it is not working properly. Since the text is too big I did not want to add the text manually by typing it. Also, I have a top bar menu that slides the view to each content, that is why I had to have only one UITextView. I am looking for a best solution.
What about adding your texts with images on UIWebView with loading these texts by wrapping them into html?
You can also add javascript callbacks which you will be able to handle in swift or obj-c by adding JavascriptCore.framework to your build phases:
Add button in your code:
<button text="Close" onclick="javascript:callSwiftCode()">Call swift code</button>
And in your UIWebViewDelegate class:
func webViewDidFinishLoad(webView: UIWebView) {
let context: JSContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
let codeClosure: #convention(block) ()->() = { ()->() in
print ("This is callback from javascript you can add your code in this closure")
}
let casted: AnyObject = unsafeBitCast(codeClosure, AnyObject.self) as AnyObject
context.setObject(casted, forKeyedSubscript: "callSwiftCode")
}
You can achieve this using NSAttributedString and NSTextAttachment. Attributed strings are strings with formatting attached(bold, italics, colors, etc), but you can also attach the images inside attributed strings, and they just get drawn right along with the text. Below example might help you understand:
//Create a mutable attributed string so that we could append everything to it.
let bigText = NSMutableAttributedString(string: "Your text starts here")
//Create a NSTextAttachment
let image1Attachment = NSTextAttachment()
image1Attachment.image = UIImage(named: "image1.png")
// wrap the attachment in its own attributed string so we can append it
let image1String = NSAttributedString(attachment: image1Attachment)
// add the NSTextAttachment wrapper to our full string, then add some more text.
bigText.appendAttributedString(image1String)
bigText.appendAttributedString(NSAttributedString(string: "End of text"))
// Then set this bigText to your label's attributedText property.
yourLabel.attributedText = bigText

How to stop typing characters in textfield when text is the same size as textfield?

I want to find a way where when the characters completely fill up a textfield, to let the user type but it doesn't add any new characters to the textfield (like Snapchat). I've only see this done in Objective-C and I wasn't able to translate it into Swift. Can someone please help? Thanks!
You could do like this:
#IBAction func textField_EditingChanged(sender: AnyObject) {
//Set your font and add attributes if needed.
let stringSize: CGSize = textField!.text!.sizeWithAttributes([NSFontAttributeName: textField.font!])
if (stringSize.width > textField.bounds.width - 20){
textField.deleteBackward()
}
}
I added - 20 since I wanted to be sure that no small chars is added like "i", "1" etc.

Clickable username and hashtag in UILabel (Not UIWebView!)

The idea is for example there is a UILabel (like in Instagram)
"User1 started following User2"
I want that when we click either on chunk of text 'User1' or 'User2' it does some action(Not opening like usual link in UIWebView)
Tried TTTAttributedLabel , didn't find anything which will fit me exactly.
in case you haven't found something yet, you could also try ActiveLabel.swift which is an UILabel drop-in replacement supporting Hashtags (#), Mentions (#) and URLs (http://) written in Swift.
Here is a simple example:
import ActiveLabel
let label = ActiveLabel()
label.text = "This is a post with #hashtags and a #userhandle."
label.hashtagColor = .blueColor()
label.handleHashtagTap { print("Success. You just tapped the \($0) hashtag") }
Disclaimer: I'm the author of the library.
Using a method will force you to make two of them (User 1 and User 2) and align it every time you draw it. I think it's better to make a category ( or Swift extension) of UILabel that gets it's frame and add a gesture recognizer with that frame bounds
Just make a new button. It can do everything a label can do, and also have actions. You can easily update the text of a button by using:
exampleButton.setTitle("example", forState: .Normal)
And you can add an action like this:
#IBAction func myExample(sender: UIButton) {
//do action
}
Hope this helped.

Resources