Soy un nuevo desarrollador y mi aplicación tiene una vista de colección (desplazamiento horizontal) con 32 imágenes. He creado matrices para las imágenes, etiquetas y texto. Cuando llego al final de la lista, la aplicación falla. Independientemente del tamaño de mis imágenes, recibo "Mensaje del depurador: Terminado debido a un problema de memoria". Utilicé la herramienta Instrumentos, que parece indicar que las imágenes no se están publicando.
Intenté cambiar el tamaño de las imágenes pero sin éxito. También intenté usar autoreleasepool, que puede que haya usado incorrectamente.
Mi matriz de imágenes está configurada así con las imágenes 1-32.
let imageArray = [UIImage (named: "1"), UIImage (named: "2"), etc.]Aquí está mi vista de colección:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.imageArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCollectionViewCell", for: indexPath) as! MainCollectionViewCell cell.imgImage.image = imageArray [indexPath.row] cell.lblImageName.text = nameArray [indexPath.row] return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil) let desVC = mainStoryboard.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController desVC.image = imageArray[indexPath.row]! desVC.name = nameArray[indexPath.row] desVC.text = textArray[indexPath.row] self.navigationController?.pushViewController(desVC, animated: true) }Algunas observaciones:
No cargue imágenes por adelantado. Cárguelos a medida que los necesite.
Entonces, en lugar de imageArray que es una matriz de UIImage , guarde una matriz de nombres de imágenes, por ejemplo
let imageNames = ["1", "2", ...] Luego, en cellForItemAt , ahí es donde puede crear una instancia de UIImage para esa celda en particular, por ejemplo
cell.imgImage.image = UIImage(named: imageNames[indexPath.row])Recuerde que las imágenes usan mucha memoria. Independientemente del tamaño del JPG o PNG, cuando se usan en la interfaz de usuario, generalmente usan 4 bytes por píxel. Así que considere una imagen de 2000 × 2000 px, cuyo JPG solo puede ser de 100 kb: ¡Incluso cuando se usa en una vista de imagen pequeña de 100 × 100, la imagen completa está sin comprimir y, en este caso, usará 16 MB! Así que asegúrese de que sus imágenes tengan dimensiones apropiadas para su interfaz de usuario. Por ejemplo, si la vista de su imagen es 100 × 100, entonces podría tener tres representaciones de la imagen, una de 100 × 100, para dispositivos sin retina, una de 200 × 200 para dispositivos con retina @2x y otra de 300 ×300 para dispositivos @3x.
Con respecto a la memoria que no se libera, tres puntos:
Elimine el uso de la matriz de UIImage y eso evitará obligar a la aplicación a mantener todas las imágenes en la memoria, aunque es posible que no todas sean necesarias en un momento dado (consulte el punto 1, arriba).
Asegúrate de no tener un ciclo de referencia fuerte. Así que descarte el controlador de vista en cuestión y luego use "Depurar gráfico de memoria" y asegúrese de que el controlador de vista haya sido realmente descartado.
Cuando usa UIImage(named:) , las imágenes se almacenarán en caché y la memoria no se liberará hasta que haya presión de memoria (por ejemplo, una advertencia de memoria). Por lo general, el comportamiento de almacenamiento en caché de UIImage(named:) funcionará (cuando solucione los problemas anteriores), pero si no es así, use UIImage(contentsOfFile:) en su lugar. Como nos advierte la documentación de UIImage(named:) :
Este método busca en las memorias caché del sistema un objeto de imagen con el nombre especificado y devuelve la variante de esa imagen que mejor se adapta a la pantalla principal. Si un objeto de imagen coincidente aún no está en la memoria caché, este método ubica y carga los datos de imagen desde el disco o desde un catálogo de activos disponible y luego devuelve el objeto resultante.
El sistema puede purgar los datos de imágenes almacenados en caché en cualquier momento para liberar memoria. La purga ocurre solo para las imágenes que están en el caché pero que no se están utilizando actualmente...
Si tiene un archivo de imagen que solo se mostrará una vez y desea asegurarse de que no se agregue al caché del sistema, debe crear su imagen usando
imageWithContentsOfFile:. Esto mantendrá su imagen de un solo uso fuera del caché de imágenes del sistema, lo que podría mejorar las características de uso de memoria de su aplicación.
Mantenga los nombres de las imágenes en una matriz y en el origen de datos obtenga el nombre de la imagen de la matriz y construya la imagen.
let imageArray = ["1", "2"] func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCollectionViewCell", for: indexPath) as! MainCollectionViewCell cell.imgImage.image = UIImage (named: imageArray [indexPath.row]) cell.lblImageName.text = nameArray [indexPath.row] return cell }Nota: Si aún enfrenta problemas de memoria, es posible que esté cargando imágenes de alta resolución, mejor cambie su tamaño en el subproceso de fondo y asígnelas a imageView en el subproceso principal.