ios - que - ¿Cómo borrar el caché de fuentes lleno de caracteres emoji?
si borro la memoria cache se borran mis fotos (4)
Estoy desarrollando extensiones de teclado para iPhone. Hay una pantalla de emoji similar al teclado emoji propio de Apple que muestra unos 800 caracteres emoji en UICollectionView
.
Cuando se desplaza este emoji UIScrollView
el uso de memoria aumenta y no se despliega. Estoy reutilizando las celdas correctamente y cuando las pruebas con un solo carácter emoji se muestran 800 veces, la memoria no aumenta durante el desplazamiento.
Usando instrumentos encontré que no hay pérdida de memoria en mi código, pero parece que los glifos emoji están almacenados en la memoria caché y pueden tomar alrededor de 10-30MB de memoria dependiendo del tamaño de la fuente (la búsqueda muestra que en realidad son PNG). Las extensiones de teclado pueden usar poca memoria antes de que se eliminen. ¿Hay alguna manera de borrar ese caché de fuentes?
Editar
Agregar un ejemplo de código para reproducir el problema:
let data = Array("😄😊☺️😉😍😘😚😗😙😜😝😛😳😁😔😌😒😞😣😢😂😭😪😥😰😅😓😩😫😨😱😠😡😤😖😆😋😷😎😴😵😲😟😦😧😈👿😮😬😐😕😯😶😇😏😑👲👳👮👷💂👶👦👧👨👩👴👵👱👼👸😺😸😻😽😼🙀😿😹😾👹👺🙈🙉🙊💀👽💩🔥✨🌟💫💥💢💦💧💤💨👂👀👃👅👄👍👎👌👊✊✌️👋✋👐👆👇👉👈🙌🙏☝️👏💪🚶🏃💃👫👪👬👭💏💑👯🙆🙅💁🙋💆💇💅👰🙎🙍🙇🐶🐺🐱🐭🐹🐰🐸🐯🐨🐻🐷🐽🐮🐗🐵🐒🐴🐑🐘🐼🐧🐦🐤🐥🐣🐔🐍🐢🐛🐝🐜🐞🐌🐙🐚🐠🐟🐬🐳🐋🐄🐏🐀🐃🐅🐇🐉🐎🐐🐓🐕🐖🐁🐂🐲🐡🐊🐫🐪🐆🐈🐩🐾💐🌸🌷🍀🌹🌻🌺🍁🍃🍂🌿🌾🍄🌵🌴🌲🌳🌰🌱🌼🌐🌞🌝🌚🌑🌒🌓🌔🌕🌖🌗🌘🌜🌛🌙🌍🌎🌏🌋🌌🌠⭐️☀️⛅️☁️⚡️☔️❄️⛄️🌀🌁🌈🌊☕️🍵🍶🍼🍺🍻🍸🍹🍷🍴🍕🍔🍟🍗🍖🍝🍛🍤🍱🍣🍥🍙🍘🍚🍜🍲🍢🍡🍳🍞🍩🍮🍦🍨🍧🎂🍰🍪🍫🍬🍭🍯🍎🍏🍊🍋🍒🍇🍉🍓🍑🍈🍌🍐🍍🍠🍆🍅🌽🎍💝🎎🎒🎓🎏🎆🎇🎐🎑🎃👻🎅🎄🎁🎋🎉🎊🎈🎌🔮💛💙💜💚❤️💔💗💓💕💖💞💘💌💋💍💎👑👒👟👞👡👠👢👕👔👚👗🎽👖👘👙💼👜👝👛👓🎀🌂💄📚📖🔬🔭📰🎨🎬🎩🎪🎭🎤🎧🎼🎵🎶🎹🎻🎺🎷🎸👾🎮🃏🎴🀄️🎲🎯🏈🏀⚽️⚾️🎾🎱🏉🎳⛳️🚵🚴🏁🏇🏆🎿🏂🏊🏄🎣").map {String($0)}
class CollectionViewTestController: UICollectionViewController {
override func viewDidLoad() {
collectionView?.registerClass(Cell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! Cell
if cell.label.superview == nil {
cell.label.frame = cell.contentView.bounds
cell.contentView.addSubview(cell.label)
cell.label.font = UIFont.systemFontOfSize(34)
}
cell.label.text = data[indexPath.item]
return cell
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
}
class Cell: UICollectionViewCell {
private let label = UILabel()
}
Después de ejecutar y desplazar el UICollectionView
obtengo un gráfico de uso de memoria como este:
Supongo que estás cargando las imágenes usando [UIImage imageNamed:]
, o algo que se deriva de ello. Eso almacenará en caché las imágenes en la memoria caché del sistema.
Necesitará cargarlos usando [UIImage imageWithContentsOfFile:]
lugar. Eso omitirá el caché.
(Y si ese no es el problema, entonces deberá incluir algún código en su pregunta para que podamos ver lo que está sucediendo).
Me encontré con el mismo problema y lo solucioné al descargar el archivo .png de / System / Library / Fonts / Apple Color Emoji.ttf y usar UIImage (contentsOfFile: String) en lugar de un String.
Usé https://github.com/github/gemoji para extraer los archivos .png, renombré los archivos con @ 3x sufijo.
func emojiToHex(emoji: String) -> String {
let data = emoji.dataUsingEncoding(NSUTF32LittleEndianStringEncoding)
var unicode: UInt32 = 0
data!.getBytes(&unicode, length:sizeof(UInt32))
return NSString(format: "%x", unicode) as! String
}
let path = NSBundle.mainBundle().pathForResource(emojiToHex(char) + "@3x", ofType: "png")
UIImage(contentsOfFile: path!)
UIImage (contentsOfFile: path!) Se ha liberado correctamente para que la memoria permanezca en un nivel bajo. Hasta ahora, mi extensión de teclado no se ha bloqueado todavía.
Si el UIScrollView contiene muchos emoji, considere usar UICollectionView que conserva solo 3 o 4 páginas en el caché y libera las otras páginas que no se han visto.
Tuve el mismo problema e intenté muchas cosas para liberar la memoria, pero no tuve suerte. Acabo de cambiar el código según la sugerencia de Matthew. Funciona, ya no tengo problemas de memoria, incluido iPhone 6 Plus.
El cambio de código es mínimo. Encuentre el cambio en la subclase UILabel a continuación. Si me preguntas, el desafío es obtener las imágenes emoji. No pude entender cómo funciona gemoji ( https://github.com/github/gemoji ).
//self.text = title //what it used to be
let hex = emojiToHex(title) // this is not the one Matthew provides. That one return strange values starting with "/" for some emojis.
let bundlePath = NSBundle.mainBundle().pathForResource(hex, ofType: "png")
// if you don''t happened to have the image
if bundlePath == nil
{
self.text = title
return
}
// if you do have the image
else
{
var image = UIImage(contentsOfFile: bundlePath!)
//(In my case source images 64 x 64 px) showing it with scale 2 is pretty much same as showing the emoji with font size 32.
var cgImage = image!.CGImage
image = UIImage( CGImage : cgImage, scale : 2, orientation: UIImageOrientation.Up )!
let imageV = UIImageView(image : image)
//center
let x = (self.bounds.width - imageV.bounds.width) / 2
let y = (self.bounds.height - imageV.bounds.height) / 2
imageV.frame = CGRectMake( x, y, imageV.bounds.width, imageV.bounds.height)
self.addSubview(imageV)
}
El método de emojiToHex () Matthew proporciona valores extraños que comienzan con "/" para algunos emojis. La solución en el enlace dado funciona sin problemas hasta el momento. Convierte emoji a un valor hexadecimal usando Swift
func emojiToHex(emoji: String) -> String
{
let uni = emoji.unicodeScalars // Unicode scalar values of the string
let unicode = uni[uni.startIndex].value // First element as an UInt32
return String(unicode, radix: 16, uppercase: true)
}
---------- DESPUÉS DE ALGÚN TIEMPO----
Resultó que este método emojiToHex no funciona para todos los emoji. Así que termino descargando todos los emojis por Gemoji y mapeo todos y cada uno de los archivos de imagen emoji (los nombres de los archivos son como 1.png, 2.png, etc.) con el emoji mismo en un objeto de diccionario. Usando el siguiente método en su lugar ahora.
func getImageFileNo(s: String) -> Int
{
if Array(emo.keys).contains(s)
{
return emo[s]!
}
return -1
}
Muchos emojis están representados por secuencias que contienen más de un escalar unicode. La respuesta de Matthew funciona bien con los emojis básicos, pero solo muestra el primer escalar de las secuencias de emojis como banderas de países.
El siguiente código obtendrá secuencias completas y creará una cadena que coincida con los nombres de archivo exportados por gemoji .
Algunos emojis sonrientes simples también tienen el selector fe0f
. Pero gemoji no agrega este selector a los nombres de archivo en la exportación, por lo que debe eliminarse.
func emojiToHex(_ emoji: String) -> String
{
var name = ""
for item in emoji.unicodeScalars {
name += String(item.value, radix: 16, uppercase: false)
if item != emoji.unicodeScalars.last {
name += "-"
}
}
name = name.replacingOccurrences(of: "-fe0f", with: "")
return name
}