스위프트에서 관련 객체를 설정하는 방법이 있습니까?
Objective-C에서 기능 호출 가능objc_setAssociatedObject
참조를 유지하기 위해 두 개체 사이에서 참조를 유지할 수 있습니다. 참조가 제거될 때까지 개체가 삭제되지 않도록 하려면 실행 중에 편리할 수 있습니다.스위프트도 이것과 비슷한 것이 있습니까?
여기 jckarter의 답변에서 도출된 간단하지만 완전한 예가 있습니다.
기존 클래스에 새 속성을 추가하는 방법을 보여줍니다.확장 블록에 계산된 속성을 정의하여 이 작업을 수행합니다.계산된 속성은 연관된 개체로 저장됩니다.
import ObjectiveC
// Declare a global var to produce a unique address as the assoc object handle
private var AssociatedObjectHandle: UInt8 = 0
extension MyClass {
var stringProperty:String {
get {
return objc_getAssociatedObject(self, &AssociatedObjectHandle) as! String
}
set {
objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
편집:
초기화되지 않은 속성의 값을 가져오는 것을 지원하고 오류가 발생하지 않도록 해야 하는 경우unexpectedly found nil while unwrapping an Optional value
, 게터는 다음과 같이 수정할 수 있습니다.
get {
return objc_getAssociatedObject(self, &AssociatedObjectHandle) as? String ?? ""
}
이 솔루션은 String, Int, Double 등과 같이 자동으로 브리지되는 값 유형뿐만 아니라 모든 값 유형도 지원합니다.
포장지
import ObjectiveC
final class Lifted<T> {
let value: T
init(_ x: T) {
value = x
}
}
private func lift<T>(x: T) -> Lifted<T> {
return Lifted(x)
}
func setAssociatedObject<T>(object: AnyObject, value: T, associativeKey: UnsafePointer<Void>, policy: objc_AssociationPolicy) {
if let v: AnyObject = value as? AnyObject {
objc_setAssociatedObject(object, associativeKey, v, policy)
}
else {
objc_setAssociatedObject(object, associativeKey, lift(value), policy)
}
}
func getAssociatedObject<T>(object: AnyObject, associativeKey: UnsafePointer<Void>) -> T? {
if let v = objc_getAssociatedObject(object, associativeKey) as? T {
return v
}
else if let v = objc_getAssociatedObject(object, associativeKey) as? Lifted<T> {
return v.value
}
else {
return nil
}
}
클래스 확장 가능성(사용 예)
extension UIView {
private struct AssociatedKey {
static var viewExtension = "viewExtension"
}
var referenceTransform: CGAffineTransform? {
get {
return getAssociatedObject(self, associativeKey: &AssociatedKey.viewExtension)
}
set {
if let value = newValue {
setAssociatedObject(self, value: value, associativeKey: &AssociatedKey.viewExtension, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
}
저는 https://github.com/b9swift/AssociatedObject 에서 이용 가능한 현대식 포장지를 작성했습니다.
스위프트 구조까지 무료로 지원한다는 사실에 놀라실 수도 있습니다.
분명히, 이것은 Objective-C 객체에서만 작동합니다.이 문제를 좀 해결한 후 Swift에서 전화를 거는 방법은 다음과 같습니다.
import ObjectiveC
// Define a variable whose address we'll use as key.
// "let" doesn't work here.
var kSomeKey = "s"
…
func someFunc() {
objc_setAssociatedObject(target, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))
let value : AnyObject! = objc_getAssociatedObject(target, &kSomeKey)
}
Swift 3.0 업데이트 예를 들어 UITextField입니다.
import Foundation
import UIKit
import ObjectiveC
// Declare a global var to produce a unique address as the assoc object handle
var AssociatedObjectHandle: UInt8 = 0
extension UITextField
{
var nextTextField:UITextField {
get {
return objc_getAssociatedObject(self, &AssociatedObjectHandle) as! UITextField
}
set {
objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
Swift 2.1에 대해서만 클라스가 대답합니다.
import ObjectiveC
let value = NSUUID().UUIDString
var associationKey: UInt8 = 0
objc_setAssociatedObject(parentObject, &associationKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
let fetchedValue = objc_getAssociatedObject(parentObject, &associationKey) as! String
2022년의 경우 매우 간단합니다.
// Utils-tags.swift
// Just a "dumb Swift trick" to add a string tag to a view controller.
// For example, with UIDocumentPickerViewController you need to know
// "which button was clicked to launch a picker"
import UIKit
private var _docPicAssociationKey: UInt8 = 0
extension UIDocumentPickerViewController {
public var tag: String {
get {
return objc_getAssociatedObject(self, &_docPicAssociationKey)
as? String ?? ""
}
set(newValue) {
objc_setAssociatedObject(self, &_docPicAssociationKey,
newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
}
추가하기만 하면 됩니다.#import <objc/runtime.h>
swift code로 objc_setAssociatedObject에 액세스하기 위해 헤더 파일을 가져오면 됩니다.
위 친구가 귀하의 질문에 답변해 주었으나, 폐쇄 속성과 관련이 있는 경우 다음 사항을 참고하시기 바랍니다.
```
import UIKit
public extension UICollectionView {
typealias XYRearrangeNewDataBlock = (_ newData: [Any]) -> Void
typealias XYRearrangeOriginaDataBlock = () -> [Any]
// MARK:- associat key
private struct xy_associatedKeys {
static var originalDataBlockKey = "xy_originalDataBlockKey"
static var newDataBlockKey = "xy_newDataBlockKey"
}
private class BlockContainer {
var rearrangeNewDataBlock: XYRearrangeNewDataBlock?
var rearrangeOriginaDataBlock: XYRearrangeOriginaDataBlock?
}
private var newDataBlock: BlockContainer? {
get {
if let newDataBlock = objc_getAssociatedObject(self, &xy_associatedKeys.newDataBlockKey) as? BlockContainer {
return newDataBlock
}
return nil
}
set(newValue) {
objc_setAssociatedObject(self, xy_associatedKeys.newDataBlockKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
convenience init(collectionVewFlowLayout : UICollectionViewFlowLayout, originalDataBlock: @escaping XYRearrangeOriginaDataBlock, newDataBlock: @escaping XYRearrangeNewDataBlock) {
self.init()
let blockContainer: BlockContainer = BlockContainer()
blockContainer.rearrangeNewDataBlock = newDataBlock
blockContainer.rearrangeOriginaDataBlock = originalDataBlock
self.newDataBlock = blockContainer
}
```
언급URL : https://stackoverflow.com/questions/24133058/is-there-a-way-to-set-associated-objects-in-swift
'sourcetip' 카테고리의 다른 글
Powershell: 폴더 및 하위 폴더의 모든 파일을 단일 폴더로 이동 (0) | 2023.10.20 |
---|---|
자신의 보필은 현실적인 문제인가요, 아니면 역사적인 문제인가요? (0) | 2023.10.20 |
로컬 호스트에서만 get/post 요청 수락 (0) | 2023.10.20 |
ENOENT: node_modules\jquery\dist\jquery.min.js'에 해당하는 파일 또는 디렉토리가 없습니다. (0) | 2023.10.20 |
인라인 CSS가 뭐가 그렇게 안 좋습니까? (0) | 2023.10.20 |