您需要使用 UITextView 委托功能:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {...}
在该函数中,您不能用您的属性覆盖插入“”(空格)字符。
About string attributes
Swift 3 中的完整示例
ViewController.swift
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.textView.delegate = self
}
@IBAction func webLink(_ sender: AnyObject) {
let alertController = UIAlertController(title: "Insert Link", message: "", preferredStyle: .alert)
alertController.addTextField { (textField) in
textField.placeholder = "URL"
textField.keyboardType = .URL
}
alertController.addTextField { (textField) in
textField.placeholder = "Link name"
textField.keyboardType = .default
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
self.dismiss(animated: true, completion: nil)
}
let insertAction = UIAlertAction(title: "Insert", style: .default) { (action) in
if let urlName = alertController.textFields![1].text {
let systemFont = self.textView.font!
let linkAttributes = [
NSFontAttributeName : systemFont,
NSLinkAttributeName: NSURL(string: alertController.textFields![0].text!)!] as [String : Any]
let myAttributes2 = [ NSForegroundColorAttributeName: UIColor.green]
let attributedString = NSMutableAttributedString(string: urlName)
// Set the 'click here' substring to be the link
attributedString.setAttributes(linkAttributes, range: NSMakeRange(0, urlName.characters.count))
self.textView.linkTextAttributes = myAttributes2
self.textView.textStorage.insert(attributedString, at: self.textView.selectedRange.location)
let cursor = NSRange(location: self.textView.selectedRange.location + urlName.characters.count, length: 0)
self.textView.selectedRange = cursor
self.textView.font = systemFont
}
}
alertController.addAction(cancelAction)
alertController.addAction(insertAction)
self.present(alertController, animated: true) {}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == " " {
let attributes = [NSForegroundColorAttributeName: UIColor.black, NSFontAttributeName: self.textView.font!] as [String : Any]
let attributedString = NSMutableAttributedString(string: text, attributes: attributes)
self.textView.textStorage.insert(attributedString, at: range.location)
let cursor = NSRange(location: self.textView.selectedRange.location+1, length: 0)
textView.selectedRange = cursor
return false
}
return true
}
}
Main.storyboard
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="stackoverflow_40611248" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MAb-bM-rda">
<state key="normal" title="Button"/>
<connections>
<action selector="webLink:" destination="BYZ-38-t0r" eventType="touchUpInside" id="lEW-xK-QqL"/>
</connections>
</button>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="NfR-7H-lIY">
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="oZX-gx-ivA"/>
</constraints>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="MAb-bM-rda" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="EUe-Ac-j39"/>
<constraint firstItem="NfR-7H-lIY" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="162" id="LtY-X7-xvc"/>
<constraint firstItem="MAb-bM-rda" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="XWA-IA-8Bd"/>
<constraint firstItem="MAb-bM-rda" firstAttribute="top" secondItem="NfR-7H-lIY" secondAttribute="bottom" constant="8" symbolic="YES" id="cUB-uR-AvM"/>
<constraint firstItem="NfR-7H-lIY" firstAttribute="centerX" secondItem="MAb-bM-rda" secondAttribute="centerX" id="pyb-a7-lJG"/>
</constraints>
</view>
<connections>
<outlet property="textView" destination="NfR-7H-lIY" id="vYj-cp-6P8"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>