programing

Swift에서 일련의 취약한 참조를 선언하려면 어떻게 해야 합니까?

lastmoon 2023. 4. 17. 22:14
반응형

Swift에서 일련의 취약한 참조를 선언하려면 어떻게 해야 합니까?

스위프트에 약한 레퍼런스를 저장해 두고 싶습니다.배열 자체는 약한 참조가 되어서는 안 됩니다.요소는 약한 참조여야 합니다.는 코코아가 좋다고 한다.NSPointerArray는 타입이 아닌 버전의 이 기능을 제공합니다.

다음과 같이 일반 래퍼 만들기:

class Weak<T: AnyObject> {
  weak var value : T?
  init (value: T) {
    self.value = value
  }
}

이 클래스의 인스턴스를 배열에 추가합니다.

class Stuff {}
var weakly : [Weak<Stuff>] = [Weak(value: Stuff()), Weak(value: Stuff())]

「」를 정의하는 Weak '어느쪽이든 쓸 수 요.struct ★★★★★★★★★★★★★★★★★」class.

또, 어레이 컨텐츠의 수집에 도움이 되도록, 다음과 같은 작업을 실시할 수 있습니다.

extension Array where Element:Weak<AnyObject> {
  mutating func reap () {
    self = self.filter { nil != $0.value }
  }
}

「 」의 AnyObject는 '아까보다'로 해야 합니다.T 할 수 같습니다 - Swift 언어에서는 그렇게 정의할 수 없습니다.

NSHashTable'weakObjectsHashTable'은 NSHashTable's weakObjectsHashTable's WeakObjectsHashTable's Weak ObjectsHashTable' NSHashTable<ObjectType>.weakObjectsHashTable()

3의 : Swift 3의 경우:NSHashTable<ObjectType>.weakObjects()

NSHashTable 클래스 참조

OS X v10.5 이후에 사용 가능.

iOS 6.0 이상에서 사용할 수 있습니다.

기능적 프로그래밍 접근법

추가 수업은 필요 없습니다.

하면 됩니다.() -> Foo? 인스턴스(foo instance) 약하다(weak)를 사용하여 foo)를 사용하여 (instance)를 사용합니다.[weak foo].

let foo = Foo()

var foos = [() -> Foo?]()
foos.append({ [weak foo] in return foo })

foos.forEach { $0()?.doSomething() }

파티에 늦었지만, 내 것을 먹어 봐.어레이가 아닌 세트로 구현했습니다.

Weak Object Set(Weak Object Set)

class WeakObject<T: AnyObject>: Equatable, Hashable {
    weak var object: T?
    init(object: T) {
        self.object = object
    }

    var hashValue: Int {
        if let object = self.object { return unsafeAddressOf(object).hashValue }
        else { return 0 }
    }
}

func == <T> (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
    return lhs.object === rhs.object
}


class WeakObjectSet<T: AnyObject> {
    var objects: Set<WeakObject<T>>

    init() {
        self.objects = Set<WeakObject<T>>([])
    }

    init(objects: [T]) {
        self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
    }

    var allObjects: [T] {
        return objects.flatMap { $0.object }
    }

    func contains(object: T) -> Bool {
        return self.objects.contains(WeakObject(object: object))
    }

    func addObject(object: T) {
        self.objects.unionInPlace([WeakObject(object: object)])
    }

    func addObjects(objects: [T]) {
        self.objects.unionInPlace(objects.map { WeakObject(object: $0) })
    }
}

사용.

var alice: NSString? = "Alice"
var bob: NSString? = "Bob"
var cathline: NSString? = "Cathline"

var persons = WeakObjectSet<NSString>()
persons.addObject(bob!)
print(persons.allObjects) // [Bob]

persons.addObject(bob!)
print(persons.allObjects) // [Bob]

persons.addObjects([alice!, cathline!])
print(persons.allObjects) // [Alice, Cathline, Bob]

alice = nil
print(persons.allObjects) // [Cathline, Bob]

bob = nil
print(persons.allObjects) // [Cathline]

Weak Object Set 문자열 NSString weak weak weak 。String type AnyType string string string 。의 빠른 은 ★★★★★★★★★★★★★★★★★★★★★★★.Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29).

코드는 Gist에서 가져올 수 있습니다.https://gist.github.com/codelynx/30d3c42a833321f17d39

** 2017년 11월 추가

나는 Swift 4로 코드를 업데이트 했다.

// Swift 4, Xcode Version 9.1 (9B55)

class WeakObject<T: AnyObject>: Equatable, Hashable {
    weak var object: T?
    init(object: T) {
        self.object = object
    }

    var hashValue: Int {
        if var object = object { return UnsafeMutablePointer<T>(&object).hashValue }
        return 0
    }

    static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
        return lhs.object === rhs.object
    }
}

class WeakObjectSet<T: AnyObject> {
    var objects: Set<WeakObject<T>>

    init() {
        self.objects = Set<WeakObject<T>>([])
    }

    init(objects: [T]) {
        self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
    }

    var allObjects: [T] {
        return objects.flatMap { $0.object }
    }

    func contains(_ object: T) -> Bool {
        return self.objects.contains(WeakObject(object: object))
    }

    func addObject(_ object: T) {
        self.objects.formUnion([WeakObject(object: object)])
    }

    func addObjects(_ objects: [T]) {
        self.objects.formUnion(objects.map { WeakObject(object: $0) })
    }
}

고케지가 말한 것처럼, 사용중의 코드에 근거해 NSString이 할당 해제되지 않는 것을 알았습니다.머리를 긁적이며 MyString 수업을 다음과 같이 썼습니다.

// typealias MyString = NSString
class MyString: CustomStringConvertible {
    var string: String
    init(string: String) {
        self.string = string
    }
    deinit {
        print("relasing: \(string)")
    }
    var description: String {
        return self.string
    }
}

'보다 낫다'로 .NSStringMyString그렇다면 효과가 있다니 이상한데요.

var alice: MyString? = MyString(string: "Alice")
var bob: MyString? = MyString(string: "Bob")
var cathline: MyString? = MyString(string: "Cathline")

var persons = WeakObjectSet<MyString>()

persons.addObject(bob!)
print(persons.allObjects) // [Bob]

persons.addObject(bob!)
print(persons.allObjects) // [Bob]

persons.addObjects([alice!, cathline!])
print(persons.allObjects) // [Alice, Cathline, Bob]

alice = nil
print(persons.allObjects) // [Cathline, Bob]

bob = nil
print(persons.allObjects) // [Cathline]

그리고 이 문제와 관련된 이상한 페이지를 발견했습니다.

취약한 참조는 할당 해제된 NSString을 유지합니다(XC9 + iOS Sim만 해당).

https://bugs.swift.org/browse/SR-5511

가 ★★★★★★★★★★★★★★★★★★★★★★」RESOLVED하지만 아직 이 문제와 관련이 있는지 궁금합니다.어쨌든 MyString과 NSString의 동작 차이는 이 문맥을 넘어섰습니다만, 누군가 이 문제를 해결해 주셨으면 합니다.

이건 내 해결책이 아니야Apple Developer Forums에서 찾았습니다.

@GoZoner는 좋은 답변을 가지고 있지만 Swift 컴파일러가 크래시 됩니다.

다음은 현재 출시된 컴파일러가 크래시하지 않는 Weak-Object 컨테이너 버전입니다.

struct WeakContainer<T where T: AnyObject> {
    weak var _value : T?

    init (value: T) {
        _value = value
    }

    func get() -> T? {
        return _value
    }
}

그런 다음 다음 컨테이너 배열을 생성할 수 있습니다.

let myArray: Array<WeakContainer<MyClass>> = [myObject1, myObject2]

기능성 포장지는 어떠세요?

class Class1 {}

func captureWeakly<T> (_ target:T) -> (() -> T?) where T: AnyObject {
    return { [weak target] in
        return target
    }
}

let obj1 = Class1()
let obj2 = Class1()
let obj3 = Class1()
let captured1 = captureWeakly(obj1)
let captured2 = captureWeakly(obj2)
let captured3 = captureWeakly(obj3)

목표물이 아직 살아있는지 확인하기 위해 반환된 폐쇄에 전화하세요.

let isAlive = captured1() != nil
let theValue = captured1()!

그리고 이 폐쇄를 배열에 저장할 수 있습니다.

let array1 = Array<() -> (Class1?)>([captured1, captured2, captured3])

또한 폐쇄를 호출하여 약하게 캡처된 값을 가져올 수 있습니다.

let values = Array(array1.map({ $0() }))

사실, 폐쇄를 위한 기능은 필요하지 않습니다.물체를 직접 캡처하기만 하면 됩니다.

let captured3 = { [weak obj3] in return obj3 }

취약한 포인터를 유지하는 래퍼 개체를 생성하여 이를 수행할 수 있습니다.

struct WeakThing<T: AnyObject> {
  weak var value: T?
  init (value: T) {
    self.value = value
  }
}

그리고 어레이에서 이것들을 사용합니다.

var weakThings = WeakThing<Foo>[]()

세부 사항

  • Swift 5.1, X코드 11.3.1

솔루션

struct WeakObject<Object: AnyObject> { weak var object: Object? }

옵션 1

@propertyWrapper
struct WeakElements<Collect, Element> where Collect: RangeReplaceableCollection, Collect.Element == Optional<Element>, Element: AnyObject {
    private var weakObjects = [WeakObject<Element>]()

    init(wrappedValue value: Collect) { save(collection: value) }

    private mutating func save(collection: Collect) {
        weakObjects = collection.map { WeakObject(object: $0) }
    }

    var wrappedValue: Collect {
        get { Collect(weakObjects.map { $0.object }) }
        set (newValues) { save(collection: newValues) }
    }
}

옵션 1의 사용방법

class Class1 { // or struct
    @WeakElements var weakObjectsArray = [UIView?]() // Use like regular array. With any objects

    func test() {
        weakObjectsArray.append(UIView())
        weakObjectsArray.forEach { print($0) }
    }
}

옵션 2

struct WeakObjectsArray<Object> where Object: AnyObject {
    private var weakObjects = [WeakObject<Object>]()
}

extension WeakObjectsArray {
    typealias SubSequence = WeakObjectsArray<Object>
    typealias Element = Optional<Object>
    typealias Index = Int
    var startIndex: Index { weakObjects.startIndex }
    var endIndex: Index { weakObjects.endIndex }
    func index(after i: Index) -> Index { weakObjects.index(after: i) }
    subscript(position: Index) -> Element {
        get { weakObjects[position].object }
        set (newValue) { weakObjects[position] = WeakObject(object: newValue) }
    }
    var count: Int { return weakObjects.count }
    var isEmpty: Bool { return weakObjects.isEmpty }
}

extension WeakObjectsArray: RangeReplaceableCollection {
    mutating func replaceSubrange<C : Collection>( _ subrange: Range<Index>, with newElements: C) where Element == C.Element {
        weakObjects.replaceSubrange(subrange, with: newElements.map { WeakObject(object: $0) })
    }
}

옵션 2의 사용방법

class Class2 { // or struct
    var weakObjectsArray = WeakObjectsArray<UIView>() // Use like regular array. With any objects

    func test() {
        weakObjectsArray.append(UIView())
        weakObjectsArray.forEach { print($0) }
    }
}

풀샘플

솔루션 코드를 붙이는 것을 잊지 마세요.

import UIKit

class ViewController: UIViewController {

    @WeakElements var weakObjectsArray = [UIView?]()
    //var weakObjectsArray = WeakObjectsArray<UIView>()

    override func viewDidLoad() {
        super.viewDidLoad()
        addSubviews()
    }

    private func printArray(title: String) {
        DispatchQueue.main.async {
            print("=============================\n\(title)\ncount: \(self.weakObjectsArray.count)")
            self.weakObjectsArray.enumerated().forEach { print("\($0) \(String(describing: $1))") }
        }
    }
}

extension ViewController {

    private func createRandomRectangleAndAdd(to parentView: UIView) -> UIView {
        let view = UIView(frame: CGRect(x: Int.random(in: 0...200),
                                        y: Int.random(in: 60...200),
                                        width: Int.random(in: 0...200),
                                        height: Int.random(in: 0...200)))
        let color = UIColor(red: CGFloat.random(in: 0...255)/255,
                            green: CGFloat.random(in: 0...255)/255,
                            blue: CGFloat.random(in: 0...255)/255,
                            alpha: 1)
        view.backgroundColor = color
        parentView.addSubview(view)
        return view
    }

    private func addSubviews() {
        (0...1).forEach { _ in addView() }
        addButtons()
    }

    private func createButton(title: String, frame: CGRect, action: Selector) -> UIButton {
        let button = UIButton(frame: frame)
        button.setTitle(title, for: .normal)
        button.addTarget(self, action: action, for: .touchUpInside)
        button.setTitleColor(.blue, for: .normal)
        return button
    }

    private func addButtons() {
        view.addSubview(createButton(title: "Add",
                                     frame: CGRect(x: 10, y: 20, width: 40, height: 40),
                                     action: #selector(addView)))

        view.addSubview(createButton(title: "Delete",
                                     frame: CGRect(x: 60, y: 20, width: 60, height: 40),
                                     action: #selector(deleteView)))

        view.addSubview(createButton(title: "Remove nils",
                                     frame: CGRect(x: 120, y: 20, width: 100, height: 40),
                                     action: #selector(removeNils)))
    }

    @objc func deleteView() {
        view.subviews.first { view -> Bool in return !(view is UIButton) }?
            .removeFromSuperview()

        printArray(title: "First view deleted")
    }

    @objc func addView() {
        weakObjectsArray.append(createRandomRectangleAndAdd(to: view))
        printArray(title: "View addded")
    }

    @objc func removeNils() {
        weakObjectsArray = weakObjectsArray.filter { $0 != nil }
        printArray(title: "Remove all nil elements in weakArray")
    }
}

제네릭스로 약한 용기를 만드는 것도 같은 생각이었어.
그 결과, 다음에 대한 래퍼를 작성했습니다.NSHashTable

class WeakSet<ObjectType>: SequenceType {

    var count: Int {
        return weakStorage.count
    }

    private let weakStorage = NSHashTable.weakObjectsHashTable()

    func addObject(object: ObjectType) {
        guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
        weakStorage.addObject(object as? AnyObject)
    }

    func removeObject(object: ObjectType) {
        guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
        weakStorage.removeObject(object as? AnyObject)
    }

    func removeAllObjects() {
        weakStorage.removeAllObjects()
    }

    func containsObject(object: ObjectType) -> Bool {
        guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
        return weakStorage.containsObject(object as? AnyObject)
    }

    func generate() -> AnyGenerator<ObjectType> {
        let enumerator = weakStorage.objectEnumerator()
        return anyGenerator {
            return enumerator.nextObject() as! ObjectType?
        }
    }
}

사용방법:

protocol MyDelegate : AnyObject {
    func doWork()
}

class MyClass: AnyObject, MyDelegate {
    fun doWork() {
        // Do delegated work.
    }
}

var delegates = WeakSet<MyDelegate>()
delegates.addObject(MyClass())

for delegate in delegates {
    delegate.doWork()
}

게게 it it it it it it it , it, it it,,WeakSet으로 초기화할 수 이하지 않은 에는 초기화할 수 있습니다.AnyObject그러면 자세한 이유와 함께 앱이 충돌합니다.하지만 지금으로선 더 나은 해결책이 보이지 않아요.

은 was래해 original original original를 이었다.WeakSet

class WeakSet<ObjectType: AnyObject>: SequenceType {}

, 이 에는 ''' '''입니다.WeakSet수 .

protocol MyDelegate : AnyObject {
    func doWork()
}

let weakSet = WeakSet<MyDelegate>()

Swift 2.1, Xcode 7.1).
그래서 내가 그 일에 순응해서 떨어트린 거야AnyObject했습니다.fatalError()★★★★★★ 。

★★NSPointerArray이미 이 대부분을 자동으로 처리하고 있기 때문에 다른 답변에서 많은 보일러 플레이트를 피할 수 있는 타입 세이프 래퍼를 만들어 문제를 해결했습니다.

class WeakArray<T: AnyObject> {
    private let pointers = NSPointerArray.weakObjects()
    
    init (_ elements: T...) {
        elements.forEach{self.pointers.addPointer(Unmanaged.passUnretained($0).toOpaque())}
    }
    
    func get (_ index: Int) -> T? {
        if index < self.pointers.count, let pointer = self.pointers.pointer(at: index) {
            return Unmanaged<T>.fromOpaque(pointer).takeUnretainedValue()
        } else {
            return nil
        }
    }
    func append (_ element: T) {
        self.pointers.addPointer(Unmanaged.passUnretained(element).toOpaque())
    }
    func forEach (_ callback: (T) -> ()) {
        for i in 0..<self.pointers.count {
            if let element = self.get(i) {
                callback(element)
            }
        }
    }
    // implement other functionality as needed
}

사용 예:

class Foo {}
var foo: Foo? = Foo()
let array = WeakArray(foo!)
print(array.get(0)) // Optional(Foo)
foo = nil
DispatchQueue.main.async{print(array.get(0))} // nil

같이 하여 IMO로 .어레이와 같이 하고 싶다면 서브스크립팅을 구현하거나SequenceType (단, 제 에는 (( (, ( ( ( ( ( ( 。append ★★★★★★★★★★★★★★★★★」forEach을 사용하다

Weak Container의 기존 예는 유용하지만 목록 및 사전과 같은 기존 swift 컨테이너에서 약한 참조를 사용하는 데는 그다지 도움이 되지 않습니다.

Contains 등의 List 메서드를 사용하려면 Weak Container에서 Equatable을 구현해야 합니다.그래서 Weak Container가 동등할 수 있도록 코드를 추가했습니다.

사전에서 Weak Container를 사용하고 싶은 경우를 위해 사전 키로 사용할 수 있도록 해시화했습니다.

또한 WeakObject로 이름을 변경하여 클래스 유형 전용임을 강조하고 WeakContainer의 예와 구별합니다.

struct WeakObject<TYPE where TYPE:AnyObject> : Equatable, Hashable
{
    weak var _value : TYPE?
    let _originalHashValue : Int

    init (value: TYPE)
    {
        _value = value

        // We keep around the original hash value so that we can return it to represent this
        // object even if the value became Nil out from under us because the object went away.
        _originalHashValue = ObjectIdentifier(value).hashValue
    }

    var value : TYPE?
    {
        return _value
    }

    var hashValue: Int
    {
        return _originalHashValue
    }
}

func ==<T>(lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool
{
    if lhs.value == nil  &&  rhs.value == nil {
        return true
    }
    else if lhs.value == nil  ||  rhs.value == nil {
        return false
    }

    // If the objects are the same, then we are good to go
    return lhs.value! === rhs.value!
}

이를 통해 약한 참조 사전을 사용하는 것과 같은 몇 가지 유용한 작업을 수행할 수 있습니다.

private var m_observerDict : Dictionary<WeakObject<AnyObject>,FLObservationBlock> = Dictionary()

func addObserver( observer:AnyObject, block:FLObservationBlock )
{
    let weakObserver = WeakObject(value:observer)
    m_observerDict[weakObserver] = block
}


func removeObserver( observer:AnyObject )
{
    let weakObserver = WeakObject(value:observer)
    m_observerDict.removeValueForKey(weakObserver)
}

다음은 @GoZoner의 훌륭한 답변을 적합하게 만드는 방법입니다.Hashable따라서 다음과 같은 컨테이너 개체에서 인덱스를 작성할 수 있습니다.Set,Dictionary,Array,기타.

private class Weak<T: AnyObject>: Hashable {
    weak var value : T!
    init (value: T) {
       self.value = value
    }

    var hashValue : Int {
       // ObjectIdentifier creates a unique hashvalue for objects.
       return ObjectIdentifier(self.value).hashValue
    }
}

// Need to override so we can conform to Equitable.
private func == <T>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

주변에 래퍼를 만들 수 있습니다.Array또는 이 라이브러리 https://github.com/NickRybalko/WeakPointerArray 를 사용해 주세요. let array = WeakPointerArray<AnyObject>() 입입세세 세다다다다다

약한 물체의 컨테이너를 보관하는 타입 세이프 컬렉션입니다.또한 접근 시 용기/포장을 0으로 자동으로 제거합니다.

예:

protocol SomeDelegate: class {
    func doSomething()
}

class SomeViewController: UIViewController {
    var delegates: WeakCollection<SomeDelegate> = []

    func someFunction(delegate: SomeDelegate) {
        delegates.append(delegate)
    }

    func runDelegates() {
        delegates.forEach { $0.doSomething() }
    }
}

커스텀 컬렉션 https://gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc

import Foundation

/**
 Creates an array of weak reference objects.
 - Important:
    Because this is an array of weak objects, the objects in the array can be removed at any time.
    The collection itself will handle removing nil objects (garbage collection) via the private function cleanUpNilContainers()
 */

class WeakCollection<T>: RangeReplaceableCollection, ExpressibleByArrayLiteral {
    typealias Index = Int
    typealias Element = T
    typealias Iterator = IndexingIterator<[Element]>

    private var weakContainers: [WeakReferenceContainer]

    required convenience init(arrayLiteral: Element...) {
        self.init()
        self.weakContainers = WeakCollection.createWeakContainers(from: arrayLiteral)
    }

    required init() {
        weakContainers = []
    }

    required init<S>(_ elements: S) where S: Sequence, WeakCollection.Element == S.Element {
        self.weakContainers = WeakCollection.createWeakContainers(from: elements)
    }

    static private func createWeakContainers<S>(from weakCollection: S) -> [WeakReferenceContainer] where S: Sequence,
        WeakCollection.Element == S.Element {
            return weakCollection.compactMap { WeakReferenceContainer(value: $0 as AnyObject) }
    }

    func append<S>(contentsOf newElements: S) where S: Sequence, WeakCollection.Element == S.Element {
        self.weakContainers.append(contentsOf: WeakCollection.createWeakContainers(from: newElements))
    }

    var startIndex: Index {
        return references.startIndex
    }

    var endIndex: Index {
        return references.endIndex
    }

    func replaceSubrange<C, R>(_ subrange: R, with newElements: C) where
        C: Collection, R: RangeExpression, WeakCollection.Element == C.Element, WeakCollection.Index == R.Bound {
            weakContainers.replaceSubrange(subrange, with: WeakCollection.createWeakContainers(from: newElements))
    }

    func index(after i: Int) -> Int {
        return references.index(after: i)
    }

    func makeIterator() -> IndexingIterator<[Element]> {
        return references.makeIterator()
    }

    subscript(index: Int) -> Element {
        get {
            return references[index]
        }
        set {
            weakContainers[index] = WeakReferenceContainer(value: newValue as AnyObject)
        }
    }
}

extension WeakCollection {
    private class WeakReferenceContainer {
        private(set) weak var value: AnyObject?

        init(value: AnyObject?) {
            self.value = value
        }
    }

    private func cleanUpNilContainers() {
        weakContainers = weakContainers.compactMap { $0.value == nil ? nil : $0 }
    }

    private var references: [Element] {
        cleanUpNilContainers()
        return weakContainers.compactMap { $0.value as? T }
    }
}

대부분의 경우 취소 가능한 상품을 반품하는 것이 더 깨끗합니다.이것에 의해, 콜 사이트에서는, 명시적으로(및 암묵적으로) 값을 파기하는 타이밍을 결정할 수 있습니다.


public protocol Cancellable {
    func cancel()
}

private struct MyValue: Identifiable {
    let id: String
    // ...
}

private class CancellationHandler: Cancellable {
    let handler: () -> ()
    init(handler: @escaping () -> ()) { self.handler = handler }
    func cancel() { handler() }
    deinit { handler() }
}

public class Container {
    private var array = [MyType]()

    public func add() -> Cancellable {
        let value = MyValue(...)
        array.append(value)
        return CancellationHandler {
            array.removeFirst(where: { $0.id == value.id })
        }
    }
}

let cancellable = container.add()

// Both cancellable.cancel() and the cancellable descoping 
// will call the `cancel` function, removing the value from array.

다른 답변에서는 제네릭스의 각도에 대해 설명했습니다.간단한 암호를 좀 알려드릴까 해서요nilanglediscloss(.

(가끔) .Label하지만 '보기'이 ' 싫음nil옛날 것들이 있던 곳이야

별 거 아니야, 이건 내 암호야...

public struct WeakLabel {
    public weak var label : Label?
    public init(_ label: Label?) {
        self.label = label
    }
}

public class Label : UILabel {
    static var _allLabels = [WeakLabel]()
    public static var allLabels:[WeakLabel] {
        get {
            _allLabels = _allLabels.filter{$0.label != nil}
            return _allLabels.filter{$0.label != nil}.map{$0.label!}
        }
    }
    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        Label._allLabels.append(WeakLabel(self))
    }
    public override init(frame: CGRect) {
        super.init(frame: frame)
        Label._allLabels.append(WeakLabel(self))
    }
}

하지만 같은 문제에 대한 또 다른 해결책은...이 문서의 초점은 객체에 대한 약한 참조를 저장하는 것이지만 구조체도 저장할 수 있습니다.

[얼마나 유용한지 모르겠지만구문을 맞히는데 시간이 좀 걸렸어요]

class WeakWrapper : Equatable {
    var valueAny : Any?
    weak var value : AnyObject?

    init(value: Any) {
        if let valueObj = value as? AnyObject {
            self.value = valueObj
        } else {
            self.valueAny = value
        }
    }

    func recall() -> Any? {
        if let value = value {
            return value
        } else if let value = valueAny {
            return value
        }
        return nil
    }
}


func ==(lhs: WeakWrapper, rhs: WeakWrapper) -> Bool {
    return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}



class Stuff {}
var weakArray : [WeakWrapper] = [WeakWrapper(value: Stuff()), WeakWrapper(value: CGRectZero)]

extension Array where Element : WeakWrapper  {

    mutating func removeObject(object: Element) {
        if let index = self.indexOf(object) {
            self.removeAtIndex(index)
        }
    }

    mutating func compress() {
        for obj in self {
            if obj.recall() == nil {
                self.removeObject(obj)
            }
        }
    }


}

weakArray[0].recall()
weakArray[1].recall() == nil
weakArray.compress()
weakArray.count

나는 이것을 @Eonil의 작업에 근거했다. 왜냐하면 나는 클로즈 약결합 전략을 좋아했기 때문이다. 그러나 나는 변수에 함수 연산자를 사용하고 싶지 않았다. 왜냐하면 그것은 매우 반감되는 직관적인 느낌이 들었기 때문이다.

대신 제가 한 일은 다음과 같습니다.

class Weak<T> where T: AnyObject {
    fileprivate var storedWeakReference: ()->T? = { return nil }

    var value: T? {
        get {
            return storedWeakReference()
        }
    }

    init(_ object: T) {
        self.storedWeakReference = storeWeakReference(object)
    }

    fileprivate func storeWeakReference<T> (_ target:T) -> ()->T? where T: AnyObject {
        return { [weak target] in
            return target
        }
    }
}

이렇게 하면 다음과 같은 작업을 수행할 수 있습니다.

var a: UIViewController? = UIViewController()
let b = Weak(a)
print(a) //prints Optional(<UIViewController: 0xSomeAddress>)
print(b.value) //prints Optional(<UIViewController: 0xSomeAddress>)
a = nil
print(a) //prints nil
print(b.value) //prints nil

언급URL : https://stackoverflow.com/questions/24127587/how-do-i-declare-an-array-of-weak-references-in-swift

반응형