Skip to content

Commit

Permalink
[Fix] rename & optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
zhgchgli0718 committed Mar 5, 2023
1 parent cd232b6 commit 591faa7
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 108 deletions.
2 changes: 1 addition & 1 deletion Sources/UIExtensions/ZNSTextAttachmentLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ZNSTextAttachmentLabel: UILabel {
public override var attributedText: NSAttributedString? {
didSet {
attributedText?.enumerateAttribute(NSAttributedString.Key.attachment, in: NSMakeRange(0, attributedText?.string.utf16.count ?? 0), options: []) { (value, effectiveRange, nil) in
guard let attachment = value as? ZNSTextAttachmentPlaceholder else {
guard let attachment = value as? ZNSTextAttachment else {
return
}

Expand Down
12 changes: 12 additions & 0 deletions Sources/ZNSTextAttachment/ZNSTextAttachmentDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// ZNSTextAttachmentDataSource.swift
//
//
// Created by zhgchgli on 2023/3/5.
//

import Foundation

public protocol ZNSTextAttachmentDataSource: AnyObject {
func zNSTextAttachment(_ textAttachment: ZNSTextAttachment, loadImageURL imageURL: URL, completion: @escaping (Data) -> Void)
}
12 changes: 12 additions & 0 deletions Sources/ZNSTextAttachment/ZNSTextAttachmentDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// ZNSTextAttachmentDelegate.swift
//
//
// Created by zhgchgli on 2023/3/5.
//

import Foundation

public protocol ZNSTextAttachmentDelegate: AnyObject {
func zNSTextAttachment(didLoad textAttachment: ZNSTextAttachment)
}
10 changes: 10 additions & 0 deletions Sources/ZNSTextAttachment/ZNSTextAttachmentHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// ZNSTextAttachmentHandler.swift
//
//
// Created by zhgchgli on 2023/3/5.
//

import Foundation

public typealias ZNSTextAttachmentHandler = (ZNSTextAttachmentDataSource & ZNSTextAttachmentDelegate)
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,25 @@ import UIKit
import MobileCoreServices
import UniformTypeIdentifiers

public protocol ZNSTextAttachmentDataSource: AnyObject {
func zNSTextAttachment(_ textAttachment: ZNSTextAttachmentPlaceholder, loadImageURL imageURL: URL, completion: @escaping (Data) -> Void)
}

public protocol ZNSTextAttachmentDelegate: AnyObject {
func zNSTextAttachment(didLoad textAttachment: ZNSTextAttachmentPlaceholder)
}

public class ZNSTextAttachment: NSTextAttachment {

public let imageSize: CGSize?

@available(iOS 13.0, *)
public init(image: UIImage) {
imageSize = image.size
super.init(image: image)
}

public init(imageSize: CGSize?, data: Data, type: String) {
self.imageSize = imageSize

super.init(data: data, ofType: type)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func attachmentBounds(for textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {

guard let imageWidth = imageSize?.width,
let imageHeight = imageSize?.height else {
return .zero
}

let maxWidth = lineFrag.size.width - ((textContainer?.lineFragmentPadding ?? 0) * 2)
let factor = maxWidth / imageWidth

return CGRect(origin: CGPoint.zero, size:CGSize(width: Int(imageWidth * factor), height: Int(imageHeight * factor)))
}
}

public class ZNSTextAttachmentPlaceholder: NSTextAttachment {

public let imageURL: URL
public weak var delegate: ZNSTextAttachmentDelegate?
public weak var dataSource: ZNSTextAttachmentDataSource?

private let origin: CGPoint?
private let imageWidth: CGFloat?
private let imageHeight: CGFloat?

private var isLoading: Bool = false
private var textStorages: [WeakNSTextStorage] = []
private var labels: [WeakUILabel] = []

public init(imageURL: URL, placeholderImage: UIImage? = nil, placeholderImageOrigin: CGPoint? = nil) {
public init(imageURL: URL, imageWidth: CGFloat? = nil, imageHeight: CGFloat? = nil, placeholderImage: UIImage? = nil, placeholderImageOrigin: CGPoint? = nil) {
self.imageURL = imageURL
self.imageWidth = imageWidth
self.imageHeight = imageHeight
self.origin = placeholderImageOrigin

if let placeholderImageData = placeholderImage?.pngData() {
Expand Down Expand Up @@ -122,14 +85,14 @@ public class ZNSTextAttachmentPlaceholder: NSTextAttachment {
self.textStorages.forEach { value in
value.rangesForAttachment(attachment: self)?.forEach({ range in
value.textStorage?.deleteCharacters(in: range)
value.textStorage?.insert(NSAttributedString(attachment: ZNSTextAttachment(imageSize: image?.size, data: data, type: fileType)), at: range.location)
value.textStorage?.insert(NSAttributedString(attachment: ZResizableNSTextAttachment(imageSize: image?.size, fixedWidth: self.imageWidth, fixedHeight: self.imageHeight, data: data, type: fileType)), at: range.location)
})
}
self.labels.forEach { value in
value.rangesForAttachment(attachment: self)?.forEach({ range in
let attributedText = NSMutableAttributedString(attributedString: value.label?.attributedText ?? NSAttributedString())
attributedText.deleteCharacters(in: range)
attributedText.insert(NSAttributedString(attachment: ZNSTextAttachment(imageSize: image?.size, data: data, type: fileType)), at: range.location)
attributedText.insert(NSAttributedString(attachment: ZResizableNSTextAttachment(imageSize: image?.size, fixedWidth: self.imageWidth, fixedHeight: self.imageHeight, data: data, type: fileType)), at: range.location)
value.label?.attributedText = attributedText
})
}
Expand Down Expand Up @@ -157,7 +120,7 @@ public class ZNSTextAttachmentPlaceholder: NSTextAttachment {
}
}

private extension ZNSTextAttachmentPlaceholder {
private extension ZNSTextAttachment {
class WeakNSTextStorage {

weak var textStorage: NSTextStorage?
Expand All @@ -166,15 +129,15 @@ private extension ZNSTextAttachmentPlaceholder {
self.textStorage = textStorage
}

func rangesForAttachment(attachment: ZNSTextAttachmentPlaceholder) -> [NSRange]? {
func rangesForAttachment(attachment: ZNSTextAttachment) -> [NSRange]? {
guard let attributedString = textStorage else {
return nil
}
let range = NSRange(location: 0, length: attributedString.string.utf16.count)

var ranges = [NSRange]()
attributedString.enumerateAttribute(NSAttributedString.Key.attachment, in: range, options: []) { (value, effectiveRange, nil) in
guard (value as? ZNSTextAttachmentPlaceholder) == attachment else {
guard (value as? ZNSTextAttachment) == attachment else {
return
}
ranges.append(effectiveRange)
Expand All @@ -196,7 +159,7 @@ private extension ZNSTextAttachmentPlaceholder {
}
}

private extension ZNSTextAttachmentPlaceholder {
private extension ZNSTextAttachment {
class WeakUILabel {

weak var label: UILabel?
Expand All @@ -205,15 +168,15 @@ private extension ZNSTextAttachmentPlaceholder {
self.label = label
}

func rangesForAttachment(attachment: ZNSTextAttachmentPlaceholder) -> [NSRange]? {
func rangesForAttachment(attachment: ZNSTextAttachment) -> [NSRange]? {
guard let attributedString = label?.attributedText else {
return nil
}
let range = NSRange(location: 0, length: attributedString.string.utf16.count)

var ranges = [NSRange]()
attributedString.enumerateAttribute(NSAttributedString.Key.attachment, in: range, options: []) { (value, effectiveRange, nil) in
guard (value as? ZNSTextAttachmentPlaceholder) == attachment else {
guard (value as? ZNSTextAttachment) == attachment else {
return
}
ranges.append(effectiveRange)
Expand Down
57 changes: 57 additions & 0 deletions Sources/ZNSTextAttachment/iOS/ZResizableNSTextAttachment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// ZResizableNSTextAttachment.swift
//
//
// Created by zhgchgli on 2023/3/5.
//

import Foundation

#if canImport(UIKit)
import UIKit

public class ZResizableNSTextAttachment: NSTextAttachment {

public let imageSize: CGSize?
public let fixedWidth: CGFloat?
public let fixedHeight: CGFloat?

public init(imageSize: CGSize?, fixedWidth: CGFloat?, fixedHeight: CGFloat?, data: Data, type: String) {
self.imageSize = imageSize
self.fixedWidth = fixedWidth
self.fixedHeight = fixedHeight

super.init(data: data, ofType: type)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func attachmentBounds(for textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {

if let fixedWidth = self.fixedWidth,
let fixedHeight = self.fixedHeight {
return CGRect(origin: .zero, size: CGSize(width: fixedWidth, height: fixedHeight))
}

guard let imageWidth = imageSize?.width,
let imageHeight = imageSize?.height else {
return .zero
}

if let fixedWidth = self.fixedWidth {
let factor = fixedWidth / imageWidth
return CGRect(origin: .zero, size:CGSize(width: Int(fixedWidth), height: Int(imageHeight * factor)))
} else if let fixedHeight = self.fixedHeight {
let factor = fixedHeight / imageHeight
return CGRect(origin: .zero, size:CGSize(width: Int(imageWidth * factor), height: Int(fixedHeight)))
} else {
let maxWidth = lineFrag.size.width - ((textContainer?.lineFragmentPadding ?? 0) * 2)
let factor = maxWidth / imageWidth

return CGRect(origin: .zero, size:CGSize(width: Int(imageWidth * factor), height: Int(imageHeight * factor)))
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,64 +1,32 @@

//
// ZNSTextAttachmentLabel.swift
//
// ZNSTextAttachmentForMacOS.swift
//
//
// Created by zhgchgli on 2023/3/5.
// Created by https://zhgchg.li on 2023/3/5.
//

import Foundation
#if canImport(AppKit)
import AppKit
import UniformTypeIdentifiers

public protocol ZNSTextAttachmentDataSource: AnyObject {
func zNSTextAttachment(_ textAttachment: ZNSTextAttachmentPlaceholder, loadImageURL imageURL: URL, completion: @escaping (Data) -> Void)
}

public protocol ZNSTextAttachmentDelegate: AnyObject {
func zNSTextAttachment(didLoad textAttachment: ZNSTextAttachmentPlaceholder)
}

public class ZNSTextAttachment: NSTextAttachment {

public let imageSize: CGSize?

public init(imageSize: CGSize?, data: Data, type: String) {
self.imageSize = imageSize

super.init(data: data, ofType: type)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func attachmentBounds(for textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {

guard let imageWidth = imageSize?.width,
let imageHeight = imageSize?.height else {
return .zero
}

let maxWidth = lineFrag.size.width - ((textContainer?.lineFragmentPadding ?? 0) * 2)
let factor = maxWidth / imageWidth

return CGRect(origin: CGPoint.zero, size:CGSize(width: Int(imageWidth * factor), height: Int(imageHeight * factor)))
}
}

public class ZNSTextAttachmentPlaceholder: NSTextAttachment {

public let imageURL: URL
public weak var delegate: ZNSTextAttachmentDelegate?
public weak var dataSource: ZNSTextAttachmentDataSource?

private let origin: CGPoint?
private let imageWidth: CGFloat?
private let imageHeight: CGFloat?

private var isLoading: Bool = false
private var textStorages: [WeakNSTextStorage] = []

public init(imageURL: URL, placeholderImage: NSImage? = nil, placeholderImageOrigin: CGPoint? = nil) {
public init(imageURL: URL, imageWidth: CGFloat? = nil, imageHeight: CGFloat? = nil, placeholderImage: NSImage? = nil, placeholderImageOrigin: CGPoint? = nil) {
self.imageURL = imageURL
self.imageWidth = imageWidth
self.imageHeight = imageHeight
self.origin = placeholderImageOrigin

if let placeholderImageData = placeholderImage?.tiffRepresentation {
Expand Down Expand Up @@ -110,7 +78,7 @@ public class ZNSTextAttachmentPlaceholder: NSTextAttachment {
self.textStorages.forEach { value in
value.rangesForAttachment(attachment: self)?.forEach({ range in
value.textStorage?.deleteCharacters(in: range)
value.textStorage?.insert(NSAttributedString(attachment: ZNSTextAttachment(imageSize: image?.size, data: data, type: fileType)), at: range.location)
value.textStorage?.insert(NSAttributedString(attachment: ZResizableNSTextAttachment(imageSize: image?.size, fixedWidth: self.imageWidth, fixedHeight: self.imageHeight, data: data, type: fileType)), at: range.location)
})
}
self.delegate?.zNSTextAttachment(didLoad: self)
Expand All @@ -137,7 +105,7 @@ public class ZNSTextAttachmentPlaceholder: NSTextAttachment {
}
}

private extension ZNSTextAttachmentPlaceholder {
private extension ZNSTextAttachment {
class WeakNSTextStorage {

weak var textStorage: NSTextStorage?
Expand All @@ -146,15 +114,15 @@ private extension ZNSTextAttachmentPlaceholder {
self.textStorage = textStorage
}

func rangesForAttachment(attachment: ZNSTextAttachmentPlaceholder) -> [NSRange]? {
func rangesForAttachment(attachment: ZNSTextAttachment) -> [NSRange]? {
guard let attributedString = textStorage else {
return nil
}
let range = NSRange(location: 0, length: attributedString.string.utf16.count)

var ranges = [NSRange]()
attributedString.enumerateAttribute(NSAttributedString.Key.attachment, in: range, options: []) { (value, effectiveRange, nil) in
guard (value as? ZNSTextAttachmentPlaceholder) == attachment else {
guard (value as? ZNSTextAttachment) == attachment else {
return
}
ranges.append(effectiveRange)
Expand Down
Loading

0 comments on commit 591faa7

Please sign in to comment.