Giter Site home page Giter Site logo

lixiang1994 / attributedstring Goto Github PK

View Code? Open in Web Editor NEW
797.0 15.0 75.0 10.18 MB

基于Swift插值方式优雅的构建富文本, 支持点击长按事件, 支持不同类型过滤, 支持自定义视图等.

License: MIT License

Ruby 0.62% Objective-C 0.22% Swift 99.16%
attributes attributedstring nsattributedstring string ios app apple swift swift5 paragraph

attributedstring's Introduction

Hi there 👋

  • 🇨🇳 I’m an iOS developer in Beijing
  • 💻 Focusing on Swift & iOS
  • 🔨 Creator of a few widely used applications and frameworks
  • :trollface: Github is amazing, I hope to create more useful things here

attributedstring's People

Contributors

dependabot[bot] avatar lixiang1994 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

attributedstring's Issues

点击事件识别不灵敏

        let d: AttributedString = .init("《隐私协议》", .font(.font12), .foreground(.red_F84417), .action(.click, {[weak self] in
            
        }))

响应不及时,按一秒以上才能响应

iOS 15 ,Xcode 13

'AttributedString' is ambiguous for type lookup in this context

Invalid line spacing for last line with button

Attached example:

Code for init:

let text = AttributedString(NSAttributedString(string: text), .font(textFont), .color(descriptionLabel.textColor))
        let button = AttributedString(NSAttributedString(string: button), .font(buttonFont), .color(buttonColor), .action([.color(buttonColor.withAlphaComponent(0.5))], action))
        descriptionLabel.attributed.text = text + " " + button

Code for layout

titleLabel.frame.origin = .zero
titleLabel.frame.set(width: frame.width)
titleLabel.sizeToFit()
        
descriptionLabel.frame = CGRect.init(x: 0, y: titleLabel.frame.bottomY + 4, width: frame.width, height: 0)
descriptionLabel.sizeToFit()

Number of lines set to zero.

富文本编辑插值问题

如果我想用来做富文本编辑器,插入图片的时候具体该怎么定位插入图片的位置呢?

XCode14打包在iOS12设备上崩溃问题

XCode14打的Release包,在触发UILabel的点击事件方法时会造成崩溃.

Thread 0 Crashed:
0   libswiftCore.dylib                  0x000000020ae4ab00 specialized _fatalErrorMessage(_:_:file:line:flags:) + [ : 296] 
1   libswiftCore.dylib                  0x000000020ae4ab00 specialized _fatalErrorMessage(_:_:file:line:flags:) + [ : 296] 
2   libswiftCore.dylib                  0x000000020acc1750 $ss17__CocoaDictionaryV8IteratorC4nextyXl3key_yXl5valuetSgyF + [ : 156] 
3   libswiftFoundation.dylib            0x000000020b063a80 $ss30_dictionaryDownCastConditionalySDyq0_q1_GSgSDyxq_GSHRzSHR0_r2_lFSDySo8NSObjectCyXlGAcFRszyXlRs_SHR0_r2_lIetgo_Tp5 + [ : 916] 
4   libswiftFoundation.dylib            0x000000020b0636ac static Dictionary._conditionallyBridgeFromObjectiveC(_:result:) + [ : 376] 
5   libswiftCore.dylib                  0x000000020aecb480 _dynamicCastClassToValueViaObjCBridgeable(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*, (anonymous namespace)::_ObjectiveCBridgeableWitnessTable const*, swift::DynamicCastFlags) + [ : 456] 
6   libswiftCore.dylib                  0x000000020aecb6ac _dynamicCastFromExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*, swift::DynamicCastFlags) + [ : 312] 
7   AttributedString                    0x0000000103b981c8 specialized AssociatedWrapper<A>.get(_:) + [ : 136] 
8   AttributedString                    0x0000000103b99288 ASAttributedStringWrapper<A>.setupGestureRecognizers() + [UILabelExtension.swift : 215] 
9   AttributedString                    0x0000000103b9894c ASAttributedStringWrapper<A>.setter.setter + [<compiler-generated> : 0] 

图片不展示

let img = UIImage.init(named: "icon_apple")! textLabel.attributed.text = """ \(.image(img)) """
开发工具为AppCode

AttributedString.swift文件中别名的问题

在AttributedString.swift中第14行至第24行代码中
#if os(macOS)
import AppKit
public typealias Image = NSImage
public typealias Color = NSColor
public typealias Font = NSFont
#else
import UIKit
public typealias Image = UIImage
public typealias Color = UIColor
public typealias Font = UIFont
#endif
上述代码中别名Image会与SwiftUI中的Image(uiImage:(UIImage(systemName: ""))!)起冲突,可以测试一下,如有此问题,可以修改别名,或者添加前缀如public typealias LXImage = NSImage

TextView 图片偏移显示不全

给 textView 设置 contentInset 后,比如 UIEdgeInsets(top: 16, left: 20, bottom: 16, right: 20) ,图片会比预期的更靠右,如果是一个带圆角的图片就能很明显的看得出来,右边的圆角没有显示完全。

iOS11以下崩溃

在iOS11以下的系统,kvo的监听会崩溃,An instance 0x7f9395d49750 of class SXLabel was deallocated while key value observers were still registered with it. Current observation info:
使用了textView的attachment
attributed.text = .init("\(.view(customLabel, .original(.center))) \(string)", .paragraph(.lineSpacing(7)))

多语言怎么支持呢

目前本文有点击事件,因为内容是拼接的,导致多语言识别起来困难。

对于textview的点击相应的说明

在textview相应对应的点击 长按的事件的时候,必须设置textView.isEditable = false
textView.isSelectable = false,才能相应对应的点击事件,可以在readme事件中标注一下

自定义视图控件后,无法设置段落样式吗?

textView.attributed.text = .init(
"""
(.view(customLabel, .original(.center)))(" 两市涨跌不一,医疗器械集体走强两市涨跌不一,医疗器械集体走强", .font(.systemFont(ofSize: 17, weight: .medium)), .paragraph(.lineSpacing(5)))
("美国三大股指涨跌不一,道指下1.39%,纳指上涨0.53%,标普500下跌0.56%...", .paragraph(.lineSpacing(5)))
""",
.font(.systemFont(ofSize: 15))
)
设置自定义视图控件之后,段落样式无法生效,如果不添加自定义视图控件则能正常显示

$100美刀 有偿征集解决方案 TextKit与UILabel内容同步问题


完美解决此问题, 以$100美刀作为酬谢, 支持 微信支付, 支付宝支付, PayPal支付.

  • 解决上述问题, 确保自测无误.
  • 提交PR或直接联系本人交付相关代码.
  • 本人验证通过测试.
  • 2小时内根据以上支付方式支付酬谢金.
  • Release记录 以示感谢🙏

描述:

本库对于 UILabel 的点击事件实现方案是使用 TextKit 构建一个与 UILabel 显示一致的内容, 通过TextKit计算出所点击的字符.

问题:

由于UILabel的特殊性, 导致TextKit无法构建出一个完全匹配的内容, 在某些情况下总会存在误差.

比如 富文本中 存在中英文不同字体混合的情况, 最终显示会不一致.

目前进展:

UILabel 真实的NSAttributedString对象的获取已解决, 可以肯定的是目前得到的NSAttributedString对象是准确无误的. 无需再考虑这方面的问题.

通过各种实践已知 TextKitUILabel的行高计算策略不同, 导致相同的NSAttributedString对象实际渲染后显示的不一样.

已经尝试使用Neat的方案解决, Neat本身存在很多问题, 比如富文本中包含NSTextAttachment Neat 就会出现问题, 幸运的是 这个问题我已经解决了.
其他问题目前还没有解决, 比如 numberOfLines会导致计算出错.
Neat的方案是否真正可靠还是个未知数, 但最起码它是目前最接近成功的一种方案, 你可以考虑继续使用Neat的方案走下去, 也可以另辟蹊径.

如何进行测试:

目前该分支内已经包含了调试代码.
CheckingViewController.swift文件中, 点击label后 会创建一个DebugView添加到UILabel上, DebugView上显示的内容由TextKit绘制, 如果所显示的内容完全重合 则表示通过, 如果出现不一致的情况 则表示不通过.

例子:

debug

通过:

success

不通过:

failure

分支地址

调试页面:
image

相关类:
image

Error

Xcode 13
let attr : ASAttributedString = "("lee", .action(clicked))"

error:

Cannot infer contextual base in reference to member 'action'
Generic parameter 'T' could not be inferred

检查样式add这个方法没有

var string: AttributedString = """
我的名字叫李响,我的手机号码是18611401994,我的电子邮件地址是[email protected],现在是2020/06/28 20:30。我的GitHub主页是https://github.com/lixiang1994。欢迎来Star! ("点击联系我", .action(clicked))
"""
string.add(attributes: [.foreground(#colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1)), .font(.systemFont(ofSize: 20, weight: .medium))], checkings: [.phoneNumber])
string.add(attributes: [.foreground(#colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)), .font(.systemFont(ofSize: 20, weight: .medium))], checkings: [.link])
string.add(attributes: [.foreground(#colorLiteral(red: 0.1764705926, green: 0.01176470611, blue: 0.5607843399, alpha: 1)), .font(.systemFont(ofSize: 20, weight: .medium))], checkings: [.date])
string.add(attributes: [.font(.systemFont(ofSize: 20, weight: .medium))], checkings: [.action])
container.label.attributed.text = string

UILabel.touchesBegan 会发生崩溃:'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'

open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard
            isActionEnabled,
            let string = attributed.text,
            let touch = touches.first,
            let (range, action) = matching(touch.location(in: self)) else {
            super.touchesBegan(touches, with: event)
            return
        }
        // 设置触摸范围内容
        touched = (string, range, action)
        // 设置高亮样式
        var temp: [NSAttributedString.Key: Any] = [:]
        action.highlights.forEach { temp.merge($0.attributes, uniquingKeysWith: { $1 }) }
        attributedText = string.value.reset(range: range) { (attributes) in
            attributes.merge(temp, uniquingKeysWith: { $1 })
        }
    }

其中这里会发生崩溃:'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'

        attributedText = string.value.reset(range: range) { (attributes) in
            attributes.merge(temp, uniquingKeysWith: { $1 })
        }

image

image

SPM Warning

I think it happen because plist file inside source folder.
Screenshot 2021-12-16 at 11 38 57

自定义构造 Attribute

我的需求是希望能自定义构造字符串差值过程中使用自定义的 attributes

// 构造自定义的 Attribute
extension ASAttributedString.Attribute {
    
    public static func fontStyle(_ value:  UIFont.TextStyle) -> Self {
        let font = UIFont.preferredFont(forTextStyle: value)
        
        let style = NSMutableParagraphStyle()
        style.minimumLineHeight = 20
        style.maximumLineHeight = 20
        
        let baselineOffset = (20 - font.lineHeight) * 0.5

        return .init(attributes: [
            .font: font,
            .paragraphStyle: style,
            .baselineOffset: baselineOffset
        ])
    }
}
// 用法如下:
 """
        \("fontStyle: .sbuheadline", .fontStyle(.subheadline), .background(UIColor.systemBackground), .foreground(UIColor.label))
"""

但是目前由于 Attribute 的 attributes 是 internal 的,导致无法构造自定义的 attributes.

点击事件崩溃

adjustsFontSizeToFitWidth = true 的时候 一行展示不下的时候 文字里面有点击部分点击会崩溃

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.