当基本字符串包含双引号时,仅针对 Swift 中 UILabel 的特定范围的点击手势不起作用
Posted
技术标签:
【中文标题】当基本字符串包含双引号时,仅针对 Swift 中 UILabel 的特定范围的点击手势不起作用【英文标题】:Tap gesture only for specific ranges of a UILabel in Swift not working when the base string contains double quotation 【发布时间】:2020-03-11 11:30:09 【问题描述】:我在我的 ios 应用程序中在 this 中进行了实现。但是当给出的基本文本时,guard let text = self.lblTermsAndConditions.text else return
包含双引号 func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool
返回 false。
例如,当 lblTermsAndConditions 给出的文本是,点击“注册”,即表示我同意条款和条件以及隐私政策 和 privacyPolicyRange = 条款和条件和隐私政策 didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool
返回 false。
我的代码
@IBOutlet weak var privacyPolicyLabel: HuqLabel!
didSet
privacyPolicyLabel.text = "By clicking \"Signup\",I agree to the Terms and Conditions & Privacy Policy"
override func viewDidLoad()
super.viewDidLoad()
self.privacyPolicyLabel.isUserInteractionEnabled = true
let tapgesture = UITapGestureRecognizer(target: self, action: #selector(tappedOnLabel(_ :)))
tapgesture.numberOfTapsRequired = 1
tapgesture.numberOfTouchesRequired = 1
self.privacyPolicyLabel.addGestureRecognizer(tapgesture)
self.privacyPolicyLabel.isUserInteractionEnabled = true
视图控制器底部的扩展
extension UITapGestureRecognizer
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
let textStorage = NSTextStorage(attributedString: label.attributedText!)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.maximumNumberOfLines = label.numberOfLines
let labelSize = label.bounds.size
textContainer.size = labelSize
// Find the tapped character location and compare it to the specified range
let locationOfTouchInLabel = self.location(in: label)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x,
y: locationOfTouchInLabel.y - textContainerOffset.y);
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
return NSLocationInRange(indexOfCharacter, targetRange)
我就是这样用的
guard let text = self.privacyPolicyLabel.text else return
let privacyPolicyRange = (text as NSString).range(of: "Terms and Conditions & Privacy Policy")
if gesture.didTapAttributedTextInLabel(label: self.privacyPolicyLabel, inRange: privacyPolicyRange)
print("clicked on terms and conditions")
else
print("false")
这打印错误。 我该如何解决这个问题?
编辑:
我的自定义标签
import UIKit
class HuqLabel: UILabel
private var attributes = HuqStringAttributes.attributes(for: .bigTitle)
private var typograpyStyle: HuqTypographyStyle!
override init(frame: CGRect)
super.init(frame: frame)
configure()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
configure()
private func configure()
adjustsFontForContentSizeCategory = true
numberOfLines = 0
// Must be called after setting the attributed text
func setNumberOfLines(_ numOfLines: Int, breakMode: NSLineBreakMode = .byTruncatingTail)
numberOfLines = numOfLines
lineBreakMode = breakMode
func setText(_ text: String)
self.text = text
setLetterSpacing()
func set(_ text: String = "", typographyStyle: HuqTypographyStyle, alignment: NSTextAlignment = .left)
typograpyStyle = typographyStyle
self.text = text
accessibilityLabel = text
self.attributes = HuqStringAttributes.attributes(for: typographyStyle, alignment: alignment)
setLetterSpacing()
func setAttributesForStrikeThrough(_ text: String, typographyStyle: HuqTypographyStyle, alignment: NSTextAlignment = .left)
self.text = text
accessibilityLabel = text
self.attributes = HuqStringAttributes.attributes(for: typographyStyle, alignment: alignment)
let attributedString = NSMutableAttributedString(string: text, attributes: self.attributes)
attributedString.addAttribute(NSAttributedString.Key.kern, value: letterSpacingForTypographyStyle(for: typographyStyle), range: NSRange(location: 0, length: text.count))
attributedString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: 1, range: NSMakeRange(0, attributedString.length))
attributedText = attributedString
func setLetterSpacing()
let attributedString = NSMutableAttributedString(string: self.text ?? "", attributes: self.attributes)
attributedString.addAttribute(NSAttributedString.Key.kern, value: letterSpacingForTypographyStyle(for: typograpyStyle), range: NSRange(location: 0, length: self.text?.count ?? 0))
attributedText = attributedString
private func letterSpacingForTypographyStyle(for typographyStyle: HuqTypographyStyle) -> CGFloat
switch typographyStyle
case .bigTitle, .title, .bodyLight, .bodyWhite, .caption, .bodyBoldWhite, .bodyBoldBlue, .bodyBalck, .bodySmall, .titleBlue, .captionBlack, .bigTitleOrange, .captionMediumBlue:
return 0
func setText(_ text: String,
withBoldTextSections boldSections: [String], font: UIFont = FontFamily.Ubuntu.bold.font(size: 16),color:UIColor = ColorName.brownGrey.color)
let attributes = HuqStringAttributes.attributes(for: .bodyLight, alignment: .center)
let attributedFullString = NSMutableAttributedString(string: text,
attributes: attributes)
boldSections.forEach section in
let rangeOfSection = attributedFullString.mutableString.range(of: section)
attributedFullString.addAttributes([
NSAttributedString.Key.foregroundColor: color,
NSAttributedString.Key.font:font], range: rangeOfSection)
attributedText = attributedFullString
-
import Foundation
enum HuqTypographyStyle
case bigTitle
case bigTitleOrange
case title
case titleBlue
case bodyLight
case bodyWhite
case bodyBalck
case caption
case captionBlack
case bodyBoldBlue
case bodyBoldWhite
case bodySmall
case captionMediumBlue
-
import Foundation
import UIKit
struct HuqFonts
static func font(for typographyStyle: HuqTypographyStyle) -> UIFont
switch typographyStyle
case .bigTitle, .bigTitleOrange:
return ubuntuMedium(size: 30)
case .title, .titleBlue:
return ubuntuMedium(size: 18)
case .bodyLight, .bodyBalck:
return ubuntuRegular(size: 16)
case .bodyWhite:
return ubuntuRegular(size: 14)
case .caption, .captionBlack:
return ubuntuRegular(size: 12)
case .bodyBoldBlue, .bodyBoldWhite:
return ubuntuBold(size: 16)
case .bodySmall:
return ubuntuRegular(size: 10)
case .captionMediumBlue:
return ubuntuMedium(size: 12)
private static func ubuntuMedium(size: CGFloat) -> UIFont
return FontFamily.Ubuntu.medium.font(size: size)
private static func ubuntuRegular(size: CGFloat) -> UIFont
return FontFamily.Ubuntu.regular.font(size: size)
private static func ubuntuBold(size: CGFloat) -> UIFont
return FontFamily.Ubuntu.bold.font(size: size)
import UIKit
struct HuqStringAttributes
static func attributes(for typographyStyle: HuqTypographyStyle,
alignment: NSTextAlignment = .left) -> [NSAttributedString.Key: Any]
var attributes: [NSAttributedString.Key: Any] = [:]
attributes[.font] = HuqFonts.font(for: typographyStyle).scaled
attributes[.foregroundColor] = colorsForTypographyStyles(for: typographyStyle).color
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = alignment
attributes[.paragraphStyle] = paragraphStyle
return attributes
private static func colorsForTypographyStyles(for typographyStyle: HuqTypographyStyle) -> ColorName
switch typographyStyle
case .bigTitle, .title, .bodyBalck, .captionBlack:
return ColorName.black
case .bodyLight ,.caption, .bodySmall:
return ColorName.brownGrey
case .bodyWhite, .bodyBoldWhite:
return ColorName.white
case .bodyBoldBlue, .titleBlue, .captionMediumBlue:
return ColorName.turquoiseBlue
case .bigTitleOrange:
return ColorName.bloodOrange
【问题讨论】:
不要仅仅链接到您的代码基于...编辑您的问题并包含您正在使用的实际代码。 @DonMag 现在检查。 您的文本是否包含多行? 没有字符串中的引号可以工作吗? 是的。它没有引号@DonMag 【参考方案1】:在viewDidLoad()
中添加这一行:
self.privacyPolicyLabel.lineBreakMode = .byWordWrapping
快速测试似乎可以解决问题。
编辑
试试这个。它使用标准的UILabel
- 全部通过代码,没有@IBOutlet
连接 - 所以只需将视图控制器的自定义类分配给LabelLinkViewController
。它还使用您在问题中发布的 UITapGestureRecognizer
扩展名。
class LabelLinkViewController: UIViewController
var privacyPolicyLabel: UILabel =
let v = UILabel()
v.numberOfLines = 0
return v
()
override func viewDidLoad()
super.viewDidLoad()
privacyPolicyLabel.translatesAutoresizingMaskIntoConstraints = false
privacyPolicyLabel.backgroundColor = .yellow
view.addSubview(privacyPolicyLabel)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
privacyPolicyLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
privacyPolicyLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
privacyPolicyLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
])
self.privacyPolicyLabel.lineBreakMode = .byWordWrapping
self.privacyPolicyLabel.isUserInteractionEnabled = true
let tapgesture = UITapGestureRecognizer(target: self, action: #selector(tappedOnLabel(_ :)))
tapgesture.numberOfTapsRequired = 1
tapgesture.numberOfTouchesRequired = 1
self.privacyPolicyLabel.addGestureRecognizer(tapgesture)
self.privacyPolicyLabel.isUserInteractionEnabled = true
self.privacyPolicyLabel.text = "By clicking \"Signup\", I agree to the Terms and Conditions & Privacy Policy"
//self.privacyPolicyLabel.text = "By clicking Signup, I agree to the Terms and Conditions & Privacy Policy"
//MARK:- tappedOnLabel
@objc func tappedOnLabel(_ gesture: UITapGestureRecognizer)
guard let text = self.privacyPolicyLabel.text else return
let privacyPolicyRange = (text as NSString).range(of: "Terms and Conditions & Privacy Policy")
if gesture.didTapAttributedTextInLabel(label: self.privacyPolicyLabel, inRange: privacyPolicyRange)
print("clicked on terms and conditions")
else
print("false")
如果这对您有用,但在您使用 HuqLabel
类时它确实不起作用,那么这就是问题所在。
【讨论】:
是的,这对我有用。不过,我使用了UILabel
,因为您没有发布任何有关您的HugLabel
课程的信息。也许这就是问题的一部分?
是的。我正在使用自定义 UILabel。我将其添加到问题中。
未解析的标识符HuqStringAttributes
和未声明的类型HuqTypographyStyle
@KrishanMadushanka - 在运行您的代码时仍然遇到问题(其他未声明的标识符等等)。在我编辑的答案中尝试示例。如果这可行,但仍然无法与您的 HuqLabel
一起使用,那么看看您是否可以编写一个完整的示例来运行,我们将看看我们是否可以找到并解决问题。以上是关于当基本字符串包含双引号时,仅针对 Swift 中 UILabel 的特定范围的点击手势不起作用的主要内容,如果未能解决你的问题,请参考以下文章
当字符串在双引号内有单引号时,如何在Javascript中将此字符串转换为JSON对象