Me gustaría almacenar una serie de referencias débiles en Swift. La matriz en sí no debería ser una referencia débil, sus elementos deberían serlo. Creo que Cocoa NSPointerArrayofrece una versión no segura de esto.
179
Me gustaría almacenar una serie de referencias débiles en Swift. La matriz en sí no debería ser una referencia débil, sus elementos deberían serlo. Creo que Cocoa NSPointerArrayofrece una versión no segura de esto.
Respuestas:
Cree un contenedor genérico como:
Agregue instancias de esta clase a su matriz.
Al definir
Weakpuede usar cualquierastructoclass.Además, para ayudar a cosechar el contenido de la matriz, puede hacer algo en la línea de:
El uso de lo
AnyObjectanterior debería reemplazarse conT, pero no creo que el lenguaje Swift actual permita una extensión definida como tal.fuente
Stuffpor un protocolo; vea esta pregunta relacionadaPuede usar NSHashTable con weakObjectsHashTable.
NSHashTable<ObjectType>.weakObjectsHashTable()Para Swift 3:
NSHashTable<ObjectType>.weakObjects()Referencia de clase NSHashTable
fuente
Any, pero noAnyObject, como los protocolos.MyProtocol: classyNSHashTable<MyProtocol>.weakObjects(). "'NSHashTable' requiere que 'MyProtocol' sea un tipo de clase.Es un poco tarde para la fiesta, pero prueba el mío. Implementé como un conjunto, no una matriz.
WeakObjectSet
Uso
Tenga en cuenta que WeakObjectSet no tomará el tipo String sino NSString. Porque, el tipo de cadena no es un AnyType. Mi versión rápida es
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29).El código puede ser tomado de Gist. https://gist.github.com/codelynx/30d3c42a833321f17d39
** AGREGADO EN NOV.2017
Actualicé el código a Swift 4
Como mencionó Gokeji, descubrí que NSString no se desasignará en función del código en uso. Me rasqué la cabeza y escribí la clase MyString de la siguiente manera.
Luego reemplace
NSStringconMyStringesto. Entonces extraño decir que funciona.Luego descubrí que una página extraña puede estar relacionada con este problema.
https://bugs.swift.org/browse/SR-5511
Dice que el problema es,
RESOLVEDpero me pregunto si esto todavía está relacionado con este problema. De todos modos, las diferencias de comportamiento entre MyString o NSString están más allá de este contexto, pero agradecería si alguien resolviera este problema.fuente
nilvalores de lo internoSet. Así que agregué unareap()función mencionada en la respuesta superior y me aseguré de llamarreap()cada vez queWeakObjectSetse accede a ella.nilmásNSStringque no.UnsafeMutablePointer<T>(&object)puede cambiar aleatoriamente (lo mismo conwithUnsafePointer). Ahora uso una versión respaldada porNSHashTable: gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d .Esta no es mi solución. Lo encontré en los foros de desarrolladores de Apple .
@GoZoner tiene una buena respuesta, pero bloquea el compilador Swift.
Aquí hay una versión de un contenedor de objetos débiles que no bloquea el compilador actual.
Luego puede crear una matriz de estos contenedores:
fuente
EXC_BAD_ACCESSpor mi. Con la clase funciona bienPuede hacer esto creando un objeto contenedor para mantener un puntero débil.
Y luego usarlos en la matriz
fuente
classpara usarweakprotocol Protocol : class { ... }¿Qué tal un envoltorio de estilo funcional?
Simplemente llame al cierre devuelto para verificar que el objetivo aún esté vivo.
Y puede almacenar estos cierres en una matriz.
Y puede recuperar los valores débilmente capturados mediante el mapeo llamando a los cierres.
En realidad, no necesita una función para hacer un cierre. Simplemente captura un objeto directamente.
fuente
var array: [(x: Int, y: () -> T?)]. Exactamente lo que estaba buscando.let values = Array(array1.map({ $0() })) part. Como ya no se trata de una matriz de cierres con referencias débiles, los valores se conservarán hasta que esta matriz se desasigne. Si estoy en lo correcto, entonces es importante tener en cuenta que nunca debe conservar esta matriz,self.items = Array(array1.map({ $0() }))ya que esto supera el propósito.Tuve la misma idea de crear un contenedor débil con genéricos.
Como resultado, creé un contenedor para
NSHashTable:Uso:
No es la mejor solución, ya que
WeakSetse puede inicializar con cualquier tipo, y si este tipo no se ajusta alAnyObjectprotocolo, la aplicación se bloqueará con un motivo detallado. Pero no veo ninguna solución mejor en este momento.La solución original era definir
WeakSetde esta manera:Pero en este caso
WeakSetno se puede inicializar con el protocolo:Actualmente, el código anterior no se puede compilar (Swift 2.1, Xcode 7.1).
Es por eso que dejé de conformarme
AnyObjecty agregué guardias adicionales confatalError()afirmaciones.fuente
Detalles
Solución
Opción 1
Opción 1 uso
opcion 2
Opción 2 uso
Muestra completa
fuente
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. Entonces, tendrá una cantidad de controladores de vista que desearían usar esta funcionalidad. Esperarías llamarMyManager.delegates.append(self). Pero siMyManagerestá bloqueado en algún tipo genérico, entonces esto no es muy útil.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())El ejemplo existente de WeakContainer es útil, pero en realidad no ayuda a usar referencias débiles en contenedores rápidos existentes como Listas y Diccionarios.
Si desea utilizar métodos de Lista, como contiene, entonces WeakContainer deberá implementar Equatable. Así que agregué el código para permitir que WeakContainer sea equiparable.
En caso de que quisieras usar el WeakContainer en los diccionarios, también lo hice utilizable para que pueda usarse como teclas de diccionario.
También lo renombré a WeakObject para enfatizar que esto es solo para tipos de clase y para diferenciarlo de los ejemplos de WeakContainer:
Esto le permite hacer algunas cosas interesantes como usar un Diccionario de referencias débiles:
fuente
Aquí está cómo hacer @ gran respuesta de GoZoner conforme con
Hashable, por lo que puede ser indexado en los objetos contenedores como:Set,Dictionary,Array, etc.fuente
Como
NSPointerArrayya maneja la mayor parte de esto automáticamente, resolví el problema haciendo un envoltorio de tipo seguro para ello, lo que evita muchas de las repeticiones en otras respuestas:Ejemplo de uso:
Es más trabajo por adelantado, pero el uso en el resto de su código es mucho más limpio IMO. Si desea hacerlo más parecido a una matriz, incluso puede implementar suscripciones, hacer que sea un
SequenceTypeetc. (pero mi proyecto solo necesitaappendy,forEachpor lo tanto, no tengo el código exacto disponible).fuente
Otra solución más para el mismo problema ... el enfoque de este está en almacenar una referencia débil a un objeto, pero también le permite almacenar una estructura.
[No estoy seguro de lo útil que es, pero tardó un tiempo en obtener la sintaxis correcta]
fuente
Podrías crear una envoltura alrededor
Array. O utilice esta biblioteca https://github.com/NickRybalko/WeakPointerArray.let array = WeakPointerArray<AnyObject>()Es de tipo seguro.fuente
Otras respuestas han cubierto el ángulo de los genéricos. Pensé que compartiría un código simple que cubra el
nilángulo.Quería una matriz estática (leer ocasionalmente) de todos los
Labelcorreos electrónicos que existen actualmente en la aplicación, pero no quería vernildónde solían estar los viejos.Nada de lujos, este es mi código ...
fuente
flatMaplugar defilter&map?Basé esto en el trabajo de @Eonil, ya que me encantó la estrategia de cierre de enlace débil, pero no quería usar un operador de función para una variable, ya que me pareció extremadamente intuitivo
Lo que hice, en cambio, es lo siguiente:
De esta manera puedes hacer algo como:
fuente
Esta es mi solución:
-
fuente
Esta es una colección segura de tipo que contiene contenedores de objetos débiles. También elimina automáticamente los contenedores / envoltorios cuando se accede.
Ejemplo:
La colección personalizada https://gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc
fuente
¿Qué pasa con un enfoque funcional ?
Esta es la idea principal, luego agregue cualquier lógica de conveniencia para realizar un seguimiento de lo que hay en la matriz. Por ejemplo, uno podría considerar el mismo enfoque con un Diccionario usando la clave como una forma de encontrar lo que hay allí.
fuente