type the servicio raw not have enum does consumir cannot ios swift memory-management automatic-ref-counting

ios - the - swift 4 enum string



Swift Managing Memory (2)

Esta pregunta se limpió y la información importante se trasladó a la respuesta a continuación.

Tengo algunas preguntas sobre la gestión de la memoria.

Estoy construyendo una aplicación de edición de fotos. Por lo tanto, mantener el uso de memoria bajo es importante. Además, no voy a publicar código porque no tengo una gran pérdida de memoria cuando hago una cosa específica. Solo pierdo un par de KB / MB con todo lo que sucede. Y revisar decenas de miles de líneas de código para encontrar kilobytes no es divertido;)

mi aplicación utiliza datos básicos, muchas cosas cifilter, ubicación y lo básico.

Mi primera vista es solo una tabla que me cuesta unos 5 MB de memoria. Luego, toma algunas fotos, aplica algunos filtros, esto se guarda en los datos centrales y luego vuelves a la primera vista.

¿Es posible deshacerse de todo en la memoria, excepto por los datos necesarios para conducir esa primera vista? (eso muy guardar e impresionante 5mb)

¿O siempre habrá algo que quede atrás, incluso si configuras todo en cero?

Pregunta de bonificación: ¿hay alguna diferencia en el tamaño del archivo / carga de la CPU entre UIImageJPEGRepresentation y UIImagePNGRepresentation ? Sé que puede establecer una calidad de compresión con el método JPEG (más difícil en la CPU / GPU?).

Solo estoy tratando de reducir la presión de la memoria por todos los medios posibles.

Actualizar:

Se me indicó que la pregunta podría ser demasiado vaga.

Los problemas que estaba teniendo en algún momento u otro fueron los siguientes:

  • En algunos puntos, el uso máximo de la memoria es demasiado alto
  • Navegar a un segundo controlador de visualización y volver provoca una fuga
  • La edición de una imagen provoca una pérdida de memoria.
  • Al aplicar un filtro a más de 4 o 5 imágenes se produce un bloqueo debido a la poca memoria, no hubo más pérdidas de memoria en este punto. (verificado en instrumentos)

Ps esto fue todo probado en un iPhone 4s, no en el simulador.

Hubo un meme aquí para aligerar el estado de ánimo en este sitio un poco.


Esta pregunta ha estado abierta el tiempo suficiente y ahora me siento lo suficientemente seguro como para responderla.

Diferentes niveles de MM:

Memoria de hardware

En Swift con ARC no tenemos forma de limpiar el RAM de hardware real. Solo podemos permitir que el sistema operativo lo haga por nosotros. Una parte está usando el código correcto ( optionals y weak ), la otra parte está creando tiempo para que el SO haga su trabajo.

Imagine que tenemos una función que se ejecuta en todos los hilos indefinidamente. Hace una cosa, cargar una imagen, convertir a blanco / negro y guardar. Todas las imágenes tienen un máximo de un par de mb y la función no crea pérdidas de memoria del software. Debido a que las imágenes no tienen un tamaño establecido y pueden tener una compresión diferente, no tienen la misma huella. Esta función siempre bloqueará tu aplicación.

Esta fuga de memoria de "Hardware" es causada por la función que siempre ocupa la próxima ranura de memoria disponible.

El sistema operativo no interviene para "limpiar realmente la memoria" porque no hay tiempo de inactividad. Poner un retraso entre cada pase soluciona esto por completo.

Idioma específico MM

Fundición

Algunas operaciones no tienen un impacto en la memoria, otras lo hacen:

let myInt : Int = 1 Float(myInt) // this creates a new instance

Intenta lanzar en cambio:

(myInt as Float) // this will not create a new instance.

Tipos de referencia vs tipos de valores | Clases vs estructuras

Ambos tienen sus ventajas y sus peligros.

Las estructuras requieren mucha memoria porque son tipos de valores . Esto significa que copian sus valores cuando se asignan a otra instancia, lo que duplica el uso de la memoria . No hay una solución / solución para esto. Es lo que hace que Structs Structs.

Las clases no tienen este comportamiento porque son Tipos de referencia . No copian cuando están asignados. En su lugar, crean otra referencia al mismo objeto . El ARC o el conteo automático de referencias es lo que hace un seguimiento de estas referencias. Cada objeto tiene un contador de referencia. Cada vez que lo asigne, aumentará en uno. Cada vez que establece una referencia a nil, la función envolvente finaliza, o el Objeto envolvente se inicia, el contador baja.

Cuando el contador llega a 0, el objeto se desinicializa.

Hay una manera de evitar que una instancia se desinicialice y, por lo tanto, genere una fuga. Esto se llama un Ciclo de Referencia Fuerte .

Buena explicación de Débil

class MyClass { var otherClass : MyOtherClass? deinit { print("deinit") // never gets called } } class MyOtherClass { var myclass : MyClass? deinit { print("deinit") // never gets called } } var classA : MyClass? = MyClass() // sorry about the force unwrapping, don''t do it like this classA!.otherClass = MyOtherClass() classA!.otherClass!.myclass = classA // this looks silly but in some form this happens a lot classA = nil // neither the MyClass nor the MyOtherClass deinitialised and we no longer have a reference we can acces. Immortalitiy reached they have.

establecer una referencia a weak

class MyOtherClass { weak var myclass : MyClass? deinit { print("deinit") // gets called } }

En fuera

Las funciones capturan los valores que se les pasan. Pero también es posible marcar esos valores como inout. Esto le permite cambiar un Struct pasado a una función sin copiar el Struct. Esto podría ahorrar memoria, dependiendo de lo que pase y de lo que haga en la función.

También es una buena forma de tener múltiples valores de retorno sin usar tuplas.

var myInt : Int = 0 // return with inout func inoutTest(inout number: Int) { number += 5 } inoutTest(&myInt) print(myInt) // prints 5 // basic function with return creates a new instance which takes up it''s own memory space func addTest(number:Int) -> Int { return number + 5 }

Programación Funcional

El estado es valor a lo largo del tiempo

La programación funcional es la contraparte de la programación orientada a objetos. La programación funcional utiliza un estado inmutable.

Más sobre esto here

La programación orientada a objetos utiliza objetos que tienen estados cambiantes / mutantes. En lugar de crear un nuevo valor, los valores anteriores se actualizan.

La Programación Funcional puede usar más memoria.

ejemplo en FP

Opcionales

Los opcionales le permiten establecer cosas en cero. Esto reducirá el recuento de referencias de las clases o las estructuras de inicialización. Configurar cosas a cero es la forma más fácil de limpiar la memoria. Esto va de la mano con ARC. Una vez que haya establecido todas las referencias de una clase en cero, se desenmotará y liberará la memoria.

Si no crea una instancia como opcional, los datos permanecerán en la memoria hasta que finalice la función adjunta o se inicie la clase adjunta. Es posible que no sepas cuándo sucederá esto. Las opciones le dan control sobre lo que permanece vivo durante cuánto tiempo.

API MM

Muchas "filtraciones de memoria" son causadas por Frameworks que tienen una función de "limpieza" que es posible que no haya llamado. Un buen ejemplo es UIGraphicsEndImageContext() El Contexto permanecerá en la memoria hasta que se llame a esta función. No se limpia cuando termina la función que creó el contexto, o cuando la imagen involucrada se establece en nil.

Otro buen ejemplo es descartar ViewControllers. Puede tener sentido pasar a un VC y luego volver atrás, pero el segue realmente crea un VC. Una vuelta atrás no destruye un VC. Call dismissViewControllerAnimated() para eliminarlo de la memoria.

Lea las referencias de clase y compruebe que no haya funciones de "limpieza".

Si necesita instrumentos para encontrar una fuga, consulte la otra respuesta a esta pregunta.


haga clic en el nombre de su aplicación en la esquina superior derecha de Xcode.

haga clic en ''editar esquema'' en el menú que aparece.

asegúrese de seleccionar "EJECUTAR" en el lado izquierdo, luego haga clic en la pestaña de diagnóstico cerca de la parte superior de la ventana.

debajo del encabezado ''gestión de la memoria'', marque ''habilitar Guard Malloc''

Es posible que también desee probar la comprobación de ''objetos distribuidos'' y ''malloc stack'' en el encabezado ''logging''

más información sobre Malloc guardia, bordes de guardia y garabato se puede encontrar here .



¡espero que esto ayude!