Swift - 使用AttributedString将URL添加到UITextView

时间:2016-11-15 13:37:29

标签: ios swift uitextview

当我按下按钮时,我正在尝试添加指向我的uitextview的链接。

到目前为止,我已设法做到这一点,但如果我开始编辑我的UITextView中的文本,它将继续作为链接。

我有很多设法通过为属性文本添加一个范围进行排序,但是然后如果我返回并删除例如URL(attributedString),那么文本现在又是一个属性字符串(链接) ...

以下是我的一些代码:

  @IBAction func webLink(_ sender: Any) {
        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


            let systemFont = self.Text.font!
            let linkAttributes = [
                NSFontAttributeName : systemFont,
                NSLinkAttributeName: NSURL(string: alertController.textFields![0].text!)!] as [String : Any]

            let myAttributes2 = [ NSForegroundColorAttributeName: customGreen ]
            let attributedString = NSMutableAttributedString(string: "\(alertController.textFields![1].text!)   ")

            // Set the 'click here' substring to be the link
            attributedString.setAttributes(linkAttributes, range: NSMakeRange(0, 3))

            self.Text.linkTextAttributes = myAttributes2
            self.Text.textStorage.insert(attributedString, at: self.Text.selectedRange.location)

            let cursor = NSRange(location: self.Text.selectedRange.location + "\(alertController.textFields![1].text!)   ".characters.count, length: 0)
            self.Text.selectedRange = cursor
            self.Text.font = systemFont

        }

        alertController.addAction(cancelAction)
        alertController.addAction(insertAction)


        self.present(alertController, animated: true) {
        }


     }

1 个答案:

答案 0 :(得分:1)

您需要使用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>