Reputation: 11
I am trying to set a NSTextAttachment
image from a url, I tried to follow Cocoanetics guide for Asynchronous NSTextAttachments
but looks like it is not working. My url works fine because I already downloaded things from it and teamLogo
is not nil
when I do the debug
let teamLogo = Team.get()
let teamImage = team?.teamLogo
guard let image = teamImage else {return nil}
let teamImageAttachment = AsyncTextAttachment()
teamImageAttachment.imageURL = URL(string: image)
let stringWithTeamImage = NSAttributedString(attachment: teamImageAttachment)
let finalAttributedString = NSMutableAttributedString(string: "")
finalAttributedString.append(stringWithTeamImage)
Upvotes: 1
Views: 2563
Reputation: 2719
teamImageAttachment.imageURL = URL(string: image)
after the image
is downloaded,
you shall refresh the label
,
which label.attributedText
by
label.setNeedsDisplay()
Upvotes: 0
Reputation: 4047
since you use swift
,
you can use the following KingFisher
extension:
import Foundation
import UIKit
// MARK: - Associated Object
private var taskIdentifierK: Void?
private var placeholderK: Void?
private var imageTas_K: Void?
extension KingfisherWrapper where Base: NSTextAttachment {
// MARK: Properties
public private(set) var taskId: Source.Identifier.Value? {
get {
let box: Box<Source.Identifier.Value>? = getAssociatedObject(base, &taskIdentifierK)
return box?.value
}
set {
let box = newValue.map { Box($0) }
setRetainedAssociatedObject(base, &taskIdentifierK, box)
}
}
private var imageTask: DownloadTask? {
get { return getAssociatedObject(base, &imageTas_K) }
set { setRetainedAssociatedObject(base, &imageTas_K, newValue)}
}
/// Represents the `Placeholder` used for this image view. A `Placeholder` will be shown in the view while
/// it is downloading an image.
public private(set) var placeholder: UIImage? {
get { return getAssociatedObject(base, &placeholderK) }
set {
if let previousPlaceholder = placeholder {
base.image = nil
}
if let newPlaceholder = newValue {
base.image = newPlaceholder
} else {
base.image = nil
}
setRetainedAssociatedObject(base, &placeholderK, newValue)
}
}
}
extension KingfisherWrapper where Base: NSTextAttachment {
@discardableResult
public func setImage(
with resource: Resource?,
placeholder: String,
options: KingfisherOptionsInfo? = nil,
progressBlock: DownloadProgressBlock? = nil,
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
{
return setImage(
with: resource?.convertToSource(),
placeholder: UIImage(named: placeholder),
options: options,
progressBlock: progressBlock,
completionHandler: completionHandler)
}
@discardableResult
public func setImage(
with source: Source?,
placeholder: UIImage? = nil,
options: KingfisherOptionsInfo? = nil,
progressBlock: DownloadProgressBlock? = nil,
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
{
let options = KingfisherParsedOptionsInfo(KingfisherManager.shared.defaultOptions + (options ?? []))
return setImage(
with: source,
placeholder: placeholder,
parsedOptions: options,
progressBlock: progressBlock,
completionHandler: completionHandler
)
}
func setImage(
with source: Source?,
placeholder: UIImage? = nil,
parsedOptions: KingfisherParsedOptionsInfo,
progressBlock: DownloadProgressBlock? = nil,
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
{
var mutatingSelf = self
guard let source = source else {
/**
* In iOS SDK 14.0-14.4 the image param was non-`nil`. The SDK changed in 14.5
* to allow `nil`. The compiler version 5.4 was introduced in this same SDK,
* which allows >=14.5 SDK to set a `nil` image. This compile check allows
* newer SDK users to set the image to `nil`, while still allowing older SDK
* users to compile the framework.
*/
#if compiler(>=5.4)
self.base.image = placeholder
#else
if let placeholder = placeholder {
self.base.image = placeholder
}
#endif
mutatingSelf.taskId = nil
completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptySource)))
return nil
}
var options = parsedOptions
if !options.keepCurrentImageWhileLoading {
/**
* In iOS SDK 14.0-14.4 the image param was non-`nil`. The SDK changed in 14.5
* to allow `nil`. The compiler version 5.4 was introduced in this same SDK,
* which allows >=14.5 SDK to set a `nil` image. This compile check allows
* newer SDK users to set the image to `nil`, while still allowing older SDK
* users to compile the framework.
*/
#if compiler(>=5.4)
self.base.image = placeholder
#else // Let older SDK users deal with the older behavior.
if let placeholder = placeholder {
self.base.image = placeholder
}
#endif
}
let issuedIdentifier = Source.Identifier.next()
mutatingSelf.taskId = issuedIdentifier
if let block = progressBlock {
options.onDataReceived = (options.onDataReceived ?? []) + [ImageLoadingProgressSideEffect(block)]
}
if let provider = ImageProgressiveProvider(options, refresh: { image in
self.base.image = image
}) {
options.onDataReceived = (options.onDataReceived ?? []) + [provider]
}
options.onDataReceived?.forEach {
$0.onShouldApply = { issuedIdentifier == self.taskId }
}
let task = KingfisherManager.shared.retrieveImage(
with: source,
options: options,
downloadTaskUpdated: { mutatingSelf.imageTask = $0 },
completionHandler: { result in
CallbackQueue.mainCurrentOrAsync.execute {
guard issuedIdentifier == self.taskId else {
let reason: KingfisherError.ImageSettingErrorReason
do {
let value = try result.get()
reason = .notCurrentSourceTask(result: value, error: nil, source: source)
} catch {
reason = .notCurrentSourceTask(result: nil, error: error, source: source)
}
let error = KingfisherError.imageSettingError(reason: reason)
completionHandler?(.failure(error))
return
}
mutatingSelf.imageTask = nil
mutatingSelf.taskId = nil
switch result {
case .success(let value):
self.base.image = value.image
completionHandler?(result)
case .failure:
if let image = options.onFailureImage {
/**
* In iOS SDK 14.0-14.4 the image param was non-`nil`. The SDK changed in 14.5
* to allow `nil`. The compiler version 5.4 was introduced in this same SDK,
* which allows >=14.5 SDK to set a `nil` image. This compile check allows
* newer SDK users to set the image to `nil`, while still allowing older SDK
* users to compile the framework.
*/
#if compiler(>=5.4)
self.base.image = image
#else // Let older SDK users deal with the older behavior.
if let unwrapped = image {
self.base.image = unwrapped
}
#endif
} else {
#if compiler(>=5.4)
self.base.image = nil
#endif
}
completionHandler?(result)
}
}
}
)
mutatingSelf.imageTask = task
return task
}
}
call like this,
let attriString = NSMutableAttributedString()
let attachment = NSTextAttachment()
let edge: CGFloat = 30
let y = (txtFont.capHeight - edge) * 0.5
attachment.bounds = CGRect(x: 0, y: y, width: edge, height: edge)
attachment.kf.setImage(with: URL(string: ddd.gift.avatar), placeholder: "hl_gift_display_default", completionHandler:{ result in
switch result{
case .success:
self.label.setNeedsDisplay()
case .failure: ()
}
})
let attachmentString = NSAttributedString(attachment: attachment)
attriString?.append(attachmentString)
label.attributedText = attriString
Upvotes: 0