मैं स्विफ्ट में कमजोर संदर्भों की एक सरणी संग्रहीत करना चाहता हूं। सरणी अपने आप में एक कमजोर संदर्भ नहीं होनी चाहिए - इसके तत्व होने चाहिए। मुझे लगता है कि कोको NSPointerArray
इस का एक गैर-प्रकारीय संस्करण प्रदान करता है।
मैं स्विफ्ट में कमजोर संदर्भों की एक सरणी संग्रहीत करना चाहता हूं। सरणी अपने आप में एक कमजोर संदर्भ नहीं होनी चाहिए - इसके तत्व होने चाहिए। मुझे लगता है कि कोको 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
- लेकिन मुझे नहीं लगता कि वर्तमान स्विफ्ट भाषा इस तरह के रूप में परिभाषित विस्तार की अनुमति देती है।
Stuff
किसी प्रोटोकॉल द्वारा कक्षा को प्रतिस्थापित करते हैं तो वह विफल हो जाता है; इस संबंधित प्रश्न को
आप NSHashTable का उपयोग कमजोरObjectsHashTable के साथ कर सकते हैं। NSHashTable<ObjectType>.weakObjectsHashTable()
स्विफ्ट 3 के लिए: NSHashTable<ObjectType>.weakObjects()
OS X v10.5 और बाद में उपलब्ध है।
IOS 6.0 और बाद में उपलब्ध।
Any
लेकिन AnyObject
प्रोटोकॉल जैसे नहीं ।
MyProtocol: class
और NSHashTable<MyProtocol>.weakObjects()
। "" NSHashTable 'के लिए आवश्यक है कि' MyProtocol 'एक वर्ग का प्रकार हो।
यह पार्टी के लिए देर से है, लेकिन मेरा प्रयास करें। मैंने सेट के रूप में लागू किया न कि एरियर के रूप में।
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]
सावधान रहें कि WeakObjectSet स्ट्रिंग प्रकार नहीं लेगा, लेकिन NSString। क्योंकि, String type एक AnyType नहीं है। मेरा स्विफ्ट संस्करण है Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
।
कोड को जीस्ट से पकड़ा जा सकता है। https://gist.github.com/codelynx/30d3c42a833321f17d39
** NOV.2017 में जोड़ा गया
मैंने स्विफ्ट 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
}
}
तब की जगह NSString
के साथ MyString
इस तरह। फिर कहना अजीब है कि यह काम करता है।
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 सिम) को हटाता है
https://bugs.swift.org/browse/SR-5511
यह कहता है कि यह मुद्दा है, RESOLVED
लेकिन मैं सोच रहा हूं कि क्या यह अभी भी इस मुद्दे से संबंधित है। वैसे भी, MyString या NSString के बीच व्यवहार के अंतर इस संदर्भ से परे हैं, लेकिन मैं इस बात की सराहना करूंगा कि किसी ने इस मुद्दे का पता लगाया।
nil
आंतरिक से मूल्यों को हटाने के लिए प्रतीत नहीं होता है Set
। इसलिए मैंने reap()
शीर्ष उत्तर में उल्लिखित एक फ़ंक्शन जोड़ा है , और एक्सेस होने पर reap()
हर बार कॉल करना सुनिश्चित किया WeakObjectSet
है।
nil
NSString
ऐसा नहीं है।
UnsafeMutablePointer<T>(&object)
वह बेतरतीब ढंग से (उसी के साथ withUnsafePointer
) बदल सकता है । मैं अब एक समर्थित संस्करण का उपयोग करता हूं NSHashTable
: gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d ।
यह मेरा समाधान नहीं है। मैंने इसे Apple डेवलपर फ़ोरम पर पाया ।
@GoZoner के पास एक अच्छा जवाब है, लेकिन यह स्विफ्ट कंपाइलर को क्रैश कर देता है।
यहां एक कमजोर-वस्तु कंटेनर का एक संस्करण है जो जारी किए गए संकलक को क्रैश नहीं करता है।
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]
EXC_BAD_ACCESS
मेरे लिए कहते हैं । कक्षा के साथ ठीक काम करता है
कमजोर पॉइंटर को होल्ड करने के लिए रैपर ऑब्जेक्ट बनाकर आप ऐसा कर सकते हैं।
struct WeakThing<T: AnyObject> {
weak var value: T?
init (value: T) {
self.value = value
}
}
और फिर ऐरे में इनका उपयोग करना
var weakThings = WeakThing<Foo>[]()
class
का उपयोग करने के लिए एक होना चाहिएweak
protocol Protocol : class { ... }
कैसे कार्यात्मक शैली आवरण के बारे में?
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 }
var array: [(x: Int, y: () -> T?)]
। ठीक वही जो मेरे द्वारा खोजा जा रहा था।
let values = Array(array1.map({ $0() })) part
। चूंकि यह अब कमजोर संदर्भों के साथ बंद होने का एक सरणी नहीं है, इसलिए जब तक इस सरणी को हटा नहीं दिया जाता है तब तक मूल्यों को बनाए रखा जाएगा। अगर मैं सही हूं तो यह ध्यान रखना महत्वपूर्ण है कि आपको इस सरणी को कभी भी बनाए नहीं रखना चाहिए self.items = Array(array1.map({ $0() }))
क्योंकि यह उद्देश्य को पूरा करता है।
मेरे पास जेनेरिक के साथ कमजोर कंटेनर बनाने का एक ही विचार था।
परिणामस्वरूप मैंने इसके लिए रैपर बनाया 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()
}
यह सबसे अच्छा समाधान नहीं है, क्योंकि WeakSet
इसे किसी भी प्रकार से आरंभ किया जा सकता है, और यदि यह प्रकार AnyObject
प्रोटोकॉल के अनुरूप नहीं है, तो ऐप विस्तृत कारण के साथ क्रैश हो जाएगा। लेकिन मुझे अभी कोई बेहतर उपाय नहीं दिख रहा है।
मूल समाधान WeakSet
इस तरह से परिभाषित करना था :
class WeakSet<ObjectType: AnyObject>: SequenceType {}
लेकिन इस मामले में WeakSet
प्रोटोकॉल के साथ आरंभ नहीं किया जा सकता है:
protocol MyDelegate : AnyObject {
func doWork()
}
let weakSet = WeakSet<MyDelegate>()
वर्तमान में उपरोक्त कोड संकलित नहीं किया जा सकता (स्विफ्ट 2.1, एक्सकोड 7.1)।
इसलिए मैंने AnyObject
कयासों के साथ अतिरिक्त गार्ड को जोड़ा और छोड़ fatalError()
दिया।
struct WeakObject<Object: AnyObject> { weak var object: Object? }
@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) }
}
}
class Class1 { // or struct
@WeakElements var weakObjectsArray = [UIView?]() // Use like regular array. With any objects
func test() {
weakObjectsArray.append(UIView())
weakObjectsArray.forEach { print($0) }
}
}
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) })
}
}
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")
}
}
protocol TP: class { } class TC { var a = WeakArray<TP>() var b = WeakObjectsArray<TP>() }
protocol TP: class { } class TC<TYPE> where TYPE: TP { var a = WeakObjectsArray<TYPE>() // Use like regular array. With any objects var weakObjectsArray = [TYPE?]() }
delegates
। तब आपके पास कुछ दृश्य नियंत्रक होंगे जो इस कार्यक्षमता का उपयोग करना चाहते हैं। आपको कॉल करने की उम्मीद होगी MyManager.delegates.append(self)
। लेकिन अगर MyManager
कुछ सामान्य प्रकार के लिए बंद है तो यह बहुत उपयोगी नहीं है।
protocol TP: class { } class MyManager { typealias Delegate = AnyObject & TP static var delegates = [Delegate?]() } class A: TP { } class B: TP { } //MyManager.delegates.append(A()) //MyManager.delegates.append(B())
WeakContainer का मौजूदा उदाहरण सहायक है, लेकिन यह वास्तव में मौजूदा स्विफ्ट कंटेनर जैसे सूचियों और शब्दकोशों में कमजोर संदर्भों का उपयोग करने में मदद नहीं करता है।
यदि आप सूची विधियों का उपयोग करना चाहते हैं, जैसे कि सम्मिलित है, तो WeakContainer को Equatable को लागू करना होगा। इसलिए मैंने WeakContainer को न्यायसंगत बनाने की अनुमति देने के लिए कोड जोड़ा।
यदि आप शब्दकोशों में WeakContainer का उपयोग करना चाहते हैं, तो मैंने इसे भी हैशेबल बनाया ताकि इसे शब्दकोश कीज़ के रूप में उपयोग किया जा सके।
मैंने इसका नाम बदलकर 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
}
चूंकि यह 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: 0) {
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
इसलिए मेरे पास सटीक कोड नहीं है)।
फिर भी इसी समस्या का एक और समाधान ... इस एक का ध्यान किसी ऑब्जेक्ट के कमजोर संदर्भ को संचय करने पर है, लेकिन आपको एक संरचना को भी संग्रहीत करने की अनुमति देता है।
[मुझे यकीन नहीं है कि यह कितना उपयोगी है, लेकिन वाक्यविन्यास सही होने में थोड़ा समय लगा]
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
आप चारों ओर आवरण बना सकते हैं Array
। या इस लाइब्रेरी का उपयोग करें https://github.com/NickRybalko/WeakPointerArray
let array = WeakPointerArray<AnyObject>()
यह सुरक्षित है।
अन्य उत्तरों ने जेनरिक कोण को कवर किया है। सोचा था कि nil
कोण को कवर करने वाला कुछ सरल कोड साझा करूँगा ।
मैं उन सभी के स्थैतिक सरणी (कभी-कभार पढ़ना) चाहता था 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))
}
}
flatMap
बजाय filter
और map
?
मैं @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
यह मेरा समाधान है:
-
// MARK: - WeakObjectSet
public class WeakObject<T: AnyObject>: Equatable, Hashable {
// MARK: Public propreties
public weak var object: T?
public var hashValue: Int {
return self.identifier.hashValue
}
// MARK: Private propreties
private let identifier: ObjectIdentifier
// MARK: Initializer
public init(object: T) {
self.identifier = ObjectIdentifier(object)
self.object = object
}
public static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.identifier == rhs.identifier
}
}
// MARK: - WeakObjectSet
public class WeakObjectSet<T: AnyObject> {
// MARK: Public propreties
public var allObjects: [T] {
return allSetObjects.compactMap { $0.object }
}
// MARK: Private propreties
private var objects: Set<WeakObject<T>>
private var allSetObjects: Set<WeakObject<T>> {
get {
objects = self.objects.filter { $0.object != nil }
return objects
}
set {
objects.formUnion(newValue.filter { $0.object != nil })
}
}
// MARK: Initializer
public init() {
self.objects = Set<WeakObject<T>>([])
}
public init(objects: [T]) {
self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
}
// MARK: Public function
public func contains(_ object: T) -> Bool {
return self.allSetObjects.contains(WeakObject(object: object))
}
public func addObject(_ object: T) {
self.allSetObjects.insert(WeakObject(object: object))
}
public func addObjects(_ objects: [T]) {
objects.forEach { self.allSetObjects.insert(WeakObject(object: $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 }
}
}
एक कार्यात्मक दृष्टिकोण के बारे में क्या ?
let observers = [() -> Observer?]()
observers.append({ [weak anObserver] in return anObserver })
यह मुख्य विचार है, फिर किसी भी सुविधा तर्क को जोड़कर रखें कि ऐरे में क्या है। उदाहरण के लिए, एक शब्दकोश के साथ एक ही दृष्टिकोण पर विचार कर सकता है जो कुंजी का उपयोग कर सकता है जैसे कि वहां क्या है।