Wednesday, 29 November 2017

Core data transformable vs binary options


Com um atributo binário, você lê e escreve instâncias de NSData diretamente. Com um atributo transformável, você lê e grava instâncias de qualquer classe que pode ser convertida para e de NSData. O armazenamento de dados real é o mesmo que com um atributo binário, mas Core dados usa um NSValueTransformer para converter para / de NSData quando necessário. Por exemplo, digamos que o objeto gerenciado tem um atributo de imagem onde seria conveniente ler e escrever UIImage diretamente. Exceto, UIImage não pode ser salvo em Core Data. Mas UIImage pode ser convertido para e de NSData. Então, se você usou um atributo transformável, você pode ler e escrever UIImage enquanto ainda mantém NSData no armazenamento de dados. Os dados transformáveis ​​manterão o mesmo comportamento NSData em relação ao armazenamento externo (mesmo que o armazenamento externo não esteja explicitamente na interface do usuário ou os blobs começarão a aparecer no Core Data Store). A documentação Não indica com precisão que o atributo transformável será salvo em um registro externo ou as regras que serão aplicadas. Você pode partilhar a sua experiência ndash Tommie C. Sep 13 15 at 2:19 Exatamente tenho a mesma pergunta. Não existe tal opção no tipo de atributo Transformable a ser armazenado em quotExternal Storagequot. É por padrão ativado ou o que ndash Marcin Kapusta 26 de fevereiro às 16: 02Eu estou prestes a empreender o projeto assustador de converter o meu aplicativo ao vivo (ou seja, já na App Store por um número de anos) de Transformable para Binary Data armazenar para imagens Em Core Data. Tenho muitos usuários com bancos de dados muito grandes que armazenam muitas imagens. Isso realmente retardou o processo de backup / restauração e, provavelmente, causou alguns outros bastidores também. Eu não conheço nenhum melhor quando eu configurá-lo desta forma há anos. Como posso me submeter a este processo para não perder nem mesmo uma das imagens dos meus clientes Se fosse apenas eu e meus próprios dados, Im certeza de que eu poderia começar as coisas funcionando. Mas eu quero ter certeza de fazer isso corretamente, passo a passo, e eu sabia que essa comunidade poderia ser uma grande ajuda nessa área. Eu realmente não sei por onde começar para as imagens existentes. Basicamente, estou procurando 1) passos a tomar, para não perder uma batida. E 2) aconselhamento geral, avisos, etc. neste processo. Eu realmente preciso de uma migração limpa quando esta versão for lançada. Agradecemos antecipadamente a quem puder ajudar. Perguntou Mar 13 14 at 18:38 A partir da resposta de Z S acima, parece que eu vou precisar para mover para gerenciar todos os arquivos eu mesmo desde que eu estou tentando implementar o Core iCloud sincronização de dados também. Ugh. Que tipo de worms isso vai abrir? É mesmo possível obter as imagens quotoriginalquot de volta dos dados existentes e, em caso afirmativo, isso levará ainda mais tempo do que a pesada migração que você descreveu acima ndash SAHM Mar 14 14 às 3:13 Migração pesada é o pior. Fazer uma exportação / importação será mais rápido (não tão rápido quanto a migração leve) e permitirá que você preserve todas as imagens existentes, porque você estará exportando para o disco como parte da migração. Ndash Marcus S. Zarra Mar 14 14 às 3:39 That39s engraçado você deve dizer que, eu estou começando a implementar Core Data iCloud sincronização hoje também. O artigo foi muito eye abertura. Não deve inspirar muita confiança, especialmente a última parte. Então, parece que eu não tenho escolha, mas para salvar o URL, certo Ou talvez ainda não é tempo quothe para tentar implementar a sincronização ainda Estou olhando para ensaios Drew McCormacks, se você tem alguma idéia sobre isso. Ndash SAHM Mar 14 14 at 3:08 Minha opinião pessoal (depois de ter enviado iCloud Core dados sincronização no meu aplicativo) é que ele é muito sólido se você limitar-se a iOS7 / 10.9 apenas. Nenhuma pergunta que você shouldn39t suporta qualquer coisa antes disso. Mesmo assim, ele requer algum trabalho para dar suporte, como esse artigo menciona (opções para mudar iCloud on / off, transições de conta etc) a situação mais comum para executar em é que a sincronização pára de funcionar depois de um tempo para alguns usuários e você tem que Fornecer uma maneira de redefinir o contêiner. Eu faria mais pesquisa. Ndash Z S 14 de março de 14 às 22:22 Eu não procurei bastante em Ensembles para comentar sobre suas habilidades, mas eu seria cuidadoso de confiar na implementação de outro indivíduo contra Apple39s. A versão de Apple teve problemas desde o envio, mas eles melhoraram substancialmente em cada atualização, e eles têm uma equipe de pessoas que apóiam isso em frente. É importante saber quem você está construindo dependências contra. Mas você deve fazer sua própria pesquisa, obviamente. Ndash Z S Mar 14 14 at 22:25 Alguém pode atualizar este It39s sido mais de um ano desde que estes comentários foram feitos. I39ve ler o artigo também, mas it39s iOS 9 na esquina e eu suspeito 39Allow External Storage39 seria (ler: deve) trabalho Se não, we39d ter ouvido falar de mais gritos e reclamações. Estou prestes a criar um novo projeto e preciso tomar as decisões certas. Obrigado ndash strangetimes Jul 7 15 at 4: 24Transformável atributos em Core Data Boring: strings e inteiros diversão e misterioso: transformable Além dos tipos usuais string, float, boolean, data você pode definir entidades de dados principais com um atributo do tipo Transformable. O que é esse tipo de magia, eo que ele transforma em Adicionar uma propriedade Transformable, gerar uma subclasse NSManagedObject, e isso é o que você vê: Um ID antigo simples. Então, em teoria, você poderia definir qualquer objeto lá. Em 10.9, eu posso definir meu próprio objeto de subclasse NSObject personalizado para a propriedade transformável, mas quando eu salvar o contexto eu recebo uma exceção para o unrecognized encodeWithCoder: mensagem. Therersquos a pista que o objeto precisa para se conformar a NSCoding. Então NSArray. NSDictionary. NSData. E outros são suportados fora da caixa. Assim você pode usar sua própria classe como-é contanto que você implementar os métodos de protocolo necessários initWithCoder: e encodeWithCoder. Então, você e Core Data podem obter um quarto e seus dados serão felizes persistiu e percebeu com suas classes intactas. A desvantagem padrão é que os atributos transformáveis ​​são armazenados no backend SQLite como plists binários dentro de BLOBs, assim você canrsquot consulta esses campos diretamente de um NSPredicate. Copy Copyright 20092017 Greg Heo Feito em San Francisco deinitUsing Transformable ampamp Propriedades de dados binários em Core Data: Como você sabe Core Data atributos podem ter propriedades como Undefined, Integer16, Integer32, Integer64, Float, Decimal, Data, Boolean, String, Double, Binary Os dados do objectivo C têm para oferecer. De todas essas propriedades, os dados binários devem ser considerados. Com o apoio de todas essas propriedades Swift linguagem também está fornecendo-lhe propriedade Transformable que é muito interessante Importante. Devido a essa propriedade, você pode colocar qualquer tipo de dados nos dados do núcleo sem sobrecarga extra. Neste tutorial vou mostrar-lhe como usar ambas as propriedades. (Propriedade de transformada de ampamp dos dados binários). 1. Como de costume crie um único nome do ampamp do aplicativo do molde do nome ele ImportantDataTypeInCoreData ampamp escolhem o idioma como rápido Deixando a caixa de verificação dos dados do núcleo Unchecked nós introduziremos nosso modelo do núcleo dados mais tarde. Como mostrado na imagem abaixo: 2. Adicione uma música cuja URL estaremos armazenando no atributo urlOfSong que estaremos criando no modelo em breve. 3. Agora que temos um projeto para completar ampamp vamos usar as propriedades Core Data para agora criar uma classe Cocoa Touch com nome Persistência, que é subclasse de ampot NSObject, em seguida, para incluir o modelo clique na pasta ImportantDataTypeInCoreData ampamp clique em Novo Arquivo - gt Core Data (campo iOS) - gtData Model amamp nomeia as propriedades, em seguida, continuar até que ele será criado como mostrado na Imagem: 4. Agora abra o modelo que você acabou de criar ampamp adicionar uma entidade chamada UseOfDataTypes com dois atributos urlOfSong ampamp nome do tipo Amplamp transformável Dados Binários respectivamente, mostrados na Imagem abaixo: 5. Mantenha a entidade UseOfDataTypes selecionada vamos criar uma Classe NSObject. Clique no ampamp do editor e, em seguida, clique na opção Create NSmanagedObject Subclass ampamp siga as instruções até que a classe com o mesmo nome como entidade será criada. NSObject subclasse é criada com o nome mesmo uma entidade UseOfDataTypes abri-lo ampamp você verá algo como o que é mostrado no abaixo apresentado Image: Como mostrado nesta imagem urlOfSong atributo é do tipo AnyObject porque é de tipo transformável ampamp isso tem que ser transformado In para o que precisamos armazenar em Core Data nome ampamp é do tipo NSData porque nós configurá-lo para dados binários no modelo. Vá em frente ampamp transformar sua classe em um pouco mostrado na imagem abaixo: var managedObjectContext. NSManagedObjectContext. Deixe modelURL NSBundle. MainBundle (). URLForResource (properties. withExtension: momd) allow managedObjectModel NSManagedObjectModel (contentsOfURL: modelURL) deixa storeURL Persistence. applicationDocumentDirectory. URLByAppendingPathComponent (properties. sqlite) deixa persistentStoreCoordinator erro NSPersistentStoreCoordinator (managedObjectModel: managedObjectModel). NSError. Nil if (persistentStoreCoordinator) addPersistentStoreWithType (NSSQLiteStoreType. configuração: nil. URL: storeURL, opções: nil. Error: amperror) nil). GerenciadoObjectContext NSManagedObjectContext () managedObjectContext. PersistentStoreCoordinator persistentStoreCoordinator Aqui no código exibido acima tudo o que estamos fazendo é apenas ficando o caminho onde nós armazenamos o modelo que criamos chamado properties. xcdatamodeld ampamp, em seguida, criando o gerenciador de armazenamento de persistência ampamp ManagedObjectModel ampamp Contexto. ------ gtgtgtgtgtgt Agora temos tudo configuração adicionar o seguinte código para Persistence. Swift arquivo para armazenar objetos para Core Data: deixe qualquerObject NSEntityDescription. insertNewObjectForEntityForName (UseOfDataTypes. InManagedObjectContext: managedObjectContext) as. UseOfDataTypes deixe o caminho NSURL (fileURLWithPath: NSBundle. MainBundle (). PathForResource (pooja. OfType: mp3)) anyObject. urlOfSong caminho como NSURL var archievedName NSKeyedArchiver. ArchivedDataWithRootObject (Name) // arquivando os dados para armazenar em dados centrais para dados binários dataCaching de imagem de dados de dados Publicado em 16 de março de 2017 por Hawk iMedia É um padrão comum para um aplicativo fazer algo com dados que não são locais. Manter o desempenho decente do aplicativo ao buscar os dados é um desafio (e não o foco deste artigo). Manter os dados, e o suficiente, para uso posterior e para evitar ter que obtê-lo novamente, é outro desafio. Existem soluções óbvias, algumas fáceis e outras não, e todas com suas próprias vantagens e desvantagens. O que é Caching Caching é, muito simplesmente, manter algo em volta para uso posterior que foi 8220hard8221 para chegar em primeiro lugar. Isso pode ser dados externos, um valor calculado, ou qualquer coisa que você não tem que adquirir mais de uma vez se você pode evitá-lo. Caching não deve ser considerado um processo ilimitado, no entanto. Por isso quero dizer que você pode apenas armazenar em cache tudo para sempre Você tem que ter uma maneira de limpar o cache periodicamente com base em algum algoritmo que faz sentido para o seu aplicativo. Um algoritmo comum (e simples) é menos usado recentemente, ou LRU. Com este algoritmo, a teoria é que os itens em seu cache que foram usados ​​pelo menos são candidatos a serem purgados forma o cache com base em algum limiar de não-uso. Você pode imaginar que em um dispositivo móvel purgar o cache é importante devido às limitações de espaço inerentes. Você também pode optar por armazenar em cache uma quantidade limitada de dados (mas you8217d ainda precisa saber o que a queda se o cache ficou muito grande.) Objetivos do cache As razões para o cache são bastante simples: Mas como isso é conseguido Depende parcialmente do que Uma definição razoável de 8220performance8221 é para o seu aplicativo. Desempenho como ele se relaciona com o cache será evidente em vários lugares diferentes: Inicial cache de carga Cache de acesso Cache purge Cache salvar Tão distintamente como I8217ve fez esta lista, verifica-se que cada uma dessas coisas estão relacionados uns aos outros em algum grau. Por exemplo, a purga do cache é algo que você pode executar durante a carga do cache. A freqüência de cache salvar deve estar relacionada a algo como como 8220dirty8221 o cache é (quantas coisas mudaram desde o último salvar) ou quanto tempo decorrido desde o último salvar. Opções de Implementação Existem várias opções para implementar um cache. Sua escolha depende muito do tipo de dados que você está armazenando em cache, da quantidade de dados que você precisa armazenar em cache, de como gerenciará seu cache (ou seja, purga) e, provavelmente, muitas outras coisas específicas para seu aplicativo. As escolhas óbvias incluem: banco de dados de arquivos de dicionário ou alguma combinação destes Let8217s olhar para cada um. Dicionário Usando um dicionário parece ser uma escolha óbvia. Eles são fáceis de usar e fáceis de entender. Para conjuntos de dados muito pequenos, esta pode ser uma boa escolha. Mas uma vez que seu conjunto de dados obtém 8220large8221, você começará a notar problemas de desempenho especialmente quando você precisar carregá-lo, limpá-lo ou salvá-lo. Usando um dicionário é certamente fácil e rápido. Assim também, ler e escrever um dicionário é fácil, mas à medida que seu conjunto de dados cresce, essas ações se tornarão lentas porque você está lendo e escrevendo todo o dicionário. Prós: Rápido e fácil, especialmente para pequenos conjuntos de dados Contras: Não escalável, ou seja, o desempenho diminui à medida que o conjunto de dados cresce. Arquivos Arquivos individuais podem ser uma melhoria. Se você estiver caching dizer, imagens em miniatura, você poderia criar um esquema para escrever cada arquivo para o sistema de arquivos de uma maneira que mais tarde lhe permite encontrá-lo novamente. Isto tem a vantagem de que você só está lendo e escrevendo um único arquivo de cada vez. Ele tem as desvantagens que você poderia estar colocando uma carga pesada sobre o sistema de arquivos e é difícil, sem metadados adicionais armazenados em outro lugar, para gerenciar o cache em termos de purga de dados antigos ou limitar o tamanho de it8217s. Esta abordagem é um pouco mais complicada do que usar um dicionário, mas ainda é simples o suficiente para entender e lidar com ele. Pros: Ainda é simples, e deve ser relativamente rápido para armazenar e recuperar dados, exceto em casos raros Contras: difícil de gerenciar cache purga Database Você provavelmente se perguntou quando I8217d chegar ao CoreData Um banco de dados oferece uma boa abstração para os seus dados, Para os dados ea delegação de certas tarefas 8220hard8221 para a base de dados subjacente. CoreData realmente é útil para cache, eu aprendi, por causa dos benefícios de banco de dados como operações. (A menos que eu seja lembrado dele nos comentários: CoreData não é um banco de dados.) Em mais de uma ocasião agora eu usei um cache baseado em CoreData para armazenar dados de imagem localmente. Os benefícios de desempenho sozinho valeram a pena. Mas não comecei com o CoreData. Eu realmente comecei com um dicionário. Em um aplicativo, armazenamos cerca de 3MB ou mais de dados de imagem, com um vencimento de 30 dias em entradas individuais. Aconteceu que tentar ler ou escrever tanto dados como um dicionário era lento E pior, o dicionário inteiro tinha que ser percorrido para encontrar entradas para expirar, o que piorou as coisas. Um exemplo A título de exemplo, gostaria de salientar apenas algumas coisas sobre o meu cache de imagens CoreData, agora em uso em alguns aplicativos. O modelo começou muito simplesmente: eu era um noobie CoreData quando eu primeiro desenvolveu isso, então eu defini o atributo de dados de imagem como dados binários. Isso funcionou, mas exigiu que eu fizesse o trabalho em meu código para transformar os dados em uma UIImage. Acontece que o CoreData pode fazer esse tipo de transformação para você usando o tipo de atributo Transformable. Mais sobre isso mais tarde. O atributo imageUrl é na verdade a chave para cada registro. E o lastUsedTimestamp é a chave (por assim dizer) para o gerenciamento de purga de cache. Quando o meu aplicativo é iniciado, eo modelo e os componentes associados são inicializados, a primeira coisa que é feito é limpar o cache de qualquer coisa que tenha expirado. Isso é feito usando uma solicitação de busca predefinida: E o seguinte código: Há muitas coisas para gostar sobre este código (eu acho). Por um lado, é compacto. Não há necessidade de iterar em todo o cache para encontrar as entradas nas quais o we8217re interessado. Na verdade, deixamos o CoreData lidar com isso. E, na verdade, temos de tocar um número muito pequeno de objetos (se houver) para excluí-los. No final, o CoreData gerencia quais objetos estão sujos, ou excluídos, e faz a coisa certa. Para o que vale a pena, o código para buscar entradas com base em seu URL é similarmente compacto. Usamos um pedido de busca predefinido diferente para isso. Como uma otimização, eu queria parar de armazenar dados binários (e convertê-lo em meu código para UIImage) e usar um Transformable. Parecia bastante direto o suficiente: Crie uma nova versão do modelo, mude o tipo de dados Dados binários para Transformable e deixe a Lightweight Migration cuidar do resto. Infelizmente, isso não funcionou. Aqui está o modelo que eu acabei inventando: assim como o modelo de mapeamento para a migração: Isso permitiu que a migração leve funcionasse, mas eu tinha que fazer um pouco de trabalho extra no meu código para mover os dados de dados para a nova imagem de atributo de Type Transformable: A entrada de variável é um objeto gerenciado recém-obtido do CoreData. Para o caso em que há dados velhos pendurados ao redor, precisamos definir o atributo imagem para um UIImage criado usando esses dados. CoreData vai cuidar de converter de volta para dados binários, e armazená-lo dessa forma. E no futuro, o atributo imagem será apenas uma imagem que podemos manipular. Esta talvez não seja a maneira mais eficiente de fazer isso, mas pareceu funcionar e eu não consegui encontrar outra solução. Também definimos entry. data como nil para que não tenhamos duas cópias dos dados binários no CoreData e por isso não fazemos 8220upgrade8221 sempre para cada imagem. It8217s vale nada, pelo menos, que esta migração de dados pouco é feito apenas como imagens são chamados pela UI. Portanto, a dor disto é espalhar-se como o aplicativo é usado. E há sempre uma chance de que as entradas de cache serão envelhecidas antes de serem convertidas com esse código. Eu tomo consolo nisso. Conclusões Rochas do CoreData Depois de ultrapassar o padrão, mas necessário código boilerplate, você deve escrever para usar o CoreData em seu aplicativo, é bastante agradável de usar e realmente o libera de se preocupar demais com como gerenciar os dados e permite que você se concentre em como você Precisa usar os dados em seu aplicativo. Para fins de cache, eu acho que é uma alternativa muito legal e parece estar funcionando bem para mim até agora. Quais são seus pensamentos sobre o cache com o CoreData? Deixe-me saber nos comentários. Compartilhe isso: Tom Wilson diz: Não seria melhor armazenar os dados de imagem no disco e apenas usar os objetos de dados principais para acompanhar os meta-dados (url, último carimbo de data / hora usado) e, em seguida, substituir o método prepareForDeletion para Limpar os arquivos Armazenar os arquivos para que você possa encontrá-los facilmente e tê-los únicos é fácil fazer apenas um hash fora do url ou o ID de dados do núcleo (certifique-se de sua permanente e não temporária: P) Que Maneira que você pode buscar e fazer um loop e fazer o que quer que seja com os registros de cache, sem fazer dados de núcleo buscar os dados de imagem em ram constantemente. Deve ser um impulso de desempenho razoável, sem muito esforço8230 Olá Tom - Obrigado por essa sugestão it8217s uma ótima otimização. Um detalhe que deixei de fora do meu artigo é que uma vez que eu buscar um objeto gerenciado do CoreData, eu mantê-lo em um dicionário na memória. Assim, uma vez que os dados da imagem (como parte do objeto gerenciado) são lidos, ele está na memória. Assim, na próxima vez que for necessária, essa E / S não é necessária. Dito isto, sua sugestão ainda é válida e se move no sentido de combinar técnicas de cache disponíveis em soluções híbridas interessantes. Obrigado Karl Puder diz: Você manteve o campo 8220data8221 porque já existia, para compatibilidade com versões anteriores, ou por algum outro motivo, eu acho que eu gostaria de buscar o conteúdo de um URL e torná-lo em uma imagem de imediato, uma vez que o Presumivelmente está acontecendo porque precisamos mostrar aquela coisa na tela agora. Foi um movimento de desespero. Minha esperança era que a migração leve migraria automagicamente o modelo original (url, data, timestamp) para o novo modelo (url, imagem, timestamp) usando um modelo de mapeamento que mapeasse dados - imagem. Mas isso não deu certo. Então eu fiz o novo modelo incluir todos os atributos de model8217s antigo mais um novo atributo, imagem. O modelo de mapeamento mapeia os atributos antigos diretamente para seus equivalentes no novo modelo e define o novo atributo de imagem como 0 (ou nil, efetivamente). Em seguida, no código, verifico um valor de imagem nulo no objeto gerenciado e transformo em código do atributo de dados para o atributo de imagem e defino o atributo de dados como nulo. Esta talvez não seja a maneira de ter feito isso, mas funcionou. Isso é mais fácil se você usar relacionamentos para grandes objetos de dados (BLOBs). Como com todos os problemas de desempenho eu aconselho usando o método mais simples até que seu problema de desempenho. Fiquei muito mais feliz quando eu comecei a trabalhar primeiro e, em seguida, usar otimização de perfil orientado. Além disso, após 20 anos de programação, também é incrível como otimizações rápidas com bibliotecas ou OS8217s obsoletas otimização de nível de aplicativo. Oi Todd - Obrigado pelo seu comentário. Quanto à utilização dos métodos mais simples primeiro, concordo. No entanto, neste caso particular, onde eu comecei a usar um NSDictionary, descobri que ler e escrever tornou-se um verdadeiro gargalo, razão pela qual eu comecei a olhar para o CoreData. Dylan Neild diz: Eu acho que a única coisa a ter em mente aqui é o iCloud Backup, especificamente se você estiver usando o Core Data no iOS. Especificamente, se você estiver armazenando seu arquivo sqlite do Core Data no diretório Documents, o iCloud irá automaticamente fazer o backup quando o usuário conectar seu telefone ao poder (se eles tiverem configurado). O problema com o armazenamento de dados de blob nesse arquivo sqlite é que esse único arquivo está crescendo em tamanho com cada blob adicionado e I8217d acho que iCloud, em seguida, re-backup do arquivo inteiro, por sua vez, não Isso pode ficar proibitivamente lenta / Uma imagem de 5KB para um banco de dados de 500MB significa um novo backup de 500MB5K. A menos que a Apple tenha algum tipo de 8220row-level8221 backups estratégia ao lidar com arquivos Core sqlite de dados Eles fazem sincronização de nível de linha para sincronização iCloud para 8282 possível 8211 mas eu can8217t encontrar qualquer referência a este em qualquer lugar. Dylan - Você está absolutamente correto. Nas implementações deste esquema de cache do CoreData explicitamente não coloquei o arquivo de cache no diretório / Documents para exatamente os motivos que você destacar. Afinal, é um cache. Portanto, o local certo para colocar o arquivo está em / Library / Caches, para que o iOS possa recuperar esse espaço se for necessário. Há um recurso adicionado no iOS 5.0.1 que permite que um aplicativo definir um 8220no backup8221 bit em qualquer arquivo. Essa é outra maneira de dizer ao sistema para não fazer backup de algo. Basicamente, a regra de ouro é que se o usuário criou os dados, ele deve ir em / Documents. Se eles não puderam ser facilmente recriados ou refetched, ele deve entrar em

No comments:

Post a Comment