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 NSPointerArray
ofrece 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 NSPointerArray
ofrece una versión no segura de esto.
Respuestas:
Cree un contenedor genérico como:
Agregue instancias de esta clase a su matriz.
Al definir
Weak
puede usar cualquierastruct
oclass
.Además, para ayudar a cosechar el contenido de la matriz, puede hacer algo en la línea de:
El uso de lo
AnyObject
anterior debería reemplazarse conT
, pero no creo que el lenguaje Swift actual permita una extensión definida como tal.fuente
Stuff
por 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: class
yNSHashTable<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
NSString
conMyString
esto. 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,
RESOLVED
pero 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
nil
valores de lo internoSet
. Así que agregué unareap()
función mencionada en la respuesta superior y me aseguré de llamarreap()
cada vez queWeakObjectSet
se accede a ella.nil
másNSString
que 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_ACCESS
por 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
class
para usarweak
protocol 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
WeakSet
se puede inicializar con cualquier tipo, y si este tipo no se ajusta alAnyObject
protocolo, 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
WeakSet
de esta manera:Pero en este caso
WeakSet
no 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
AnyObject
y 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 siMyManager
está 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
NSPointerArray
ya 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
SequenceType
etc. (pero mi proyecto solo necesitaappend
y,forEach
por 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
Label
correos electrónicos que existen actualmente en la aplicación, pero no quería vernil
dónde solían estar los viejos.Nada de lujos, este es mi código ...
fuente
flatMap
lugar 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