Menu Docs

Página inicial do DocsDesenvolver aplicaçõesAtlas Device SDKs

CRUD — Leia — Swift SDK

Nesta página

  • Ler de um Realm
  • Leia as características
  • Limitando resultados da consulta
  • Paginação
  • Ler objetos de domínio
  • Sobre os exemplos nesta página
  • Encontrar um objeto específico por chave primária
  • Consultar todos os objetos de dado específico
  • Filtrar consultas com base nas propriedades do objeto
  • Filtro sobre Propriedades de ID de objeto
  • Fazer query em um relacionamento
  • Consultar um Relacionamento Inverso
  • Consultar uma Coleção sobre Propriedades de Objetos Embarcados
  • Consultar uma Propriedade de Mapa
  • Fazer query em uma propriedade MutableSet
  • Ler e Consultar Propriedade AnyRealmValue
  • Executar query de dados geoespaciais
  • Fazer query em uma propriedade persistente personalizada
  • Ler um Objeto de Forma Assíncrona
  • Classificar Resultados da Consulta
  • Resultados da Consulta da Seção
  • Dados agregados
  • Consultas em cadeia
  • Projeções de Classes de Consulta

Uma leitura de um reino geralmente consiste nas seguintes etapas:

  • Obtenha todos os objetos de um determinado tipo do realm.

  • Opcionalmente, filtre os resultados.

  • Opcionalmente, classifique os resultados.

  • Como alternativa, obtenha todos os objetos de um determinado tipo, divididos em seções. Tal como acontece com os resultados regulares, você pode filtrar e classificar os resultados seccionados.

As operações de consulta, filtro e classificação retornam uma coleção SectionedResults ou SectionedResults. Essas coleções estão ativas, o que significa que elas sempre contêm os resultados mais recentes da consulta associada.

Quando você projeta os padrões de acesso a dados da sua aplicação em torno das três principais características de leituras a seguir no Realm, você pode ter certeza de que está lendo dados da forma mais eficiente possível.

Os resultados de uma consulta não são cópias de seus dados: a modificação dos resultados de uma consulta modificará diretamente os dados no disco. Esse mapeamento de memória também significa que os resultados são ativos: ou seja, eles sempre refletem o estado atual no disco.

Veja também: As coleções são ao vivo.

O Realm só executa uma consulta quando você realmente solicita os resultados dessa consulta. Essa avaliação preguiçosa permite que você escreva código elegante e de alto desempenho para lidar com grandes conjuntos de dados e consultas complexas. Você pode encadear várias operações de filtro e classificação sem exigir trabalho extra para processar o estado intermediário.

Uma vantagem do modelo de objeto de Realm é que ele retém automaticamente todos os relacionamentos de um objeto como referências diretas, portanto você pode percorrer o grafo de relacionamentos diretamente por meio dos resultados de uma consulta.

Uma referência direta, ou ponteiro, permite que você acesse diretamente as propriedades de um objeto relacionado por meio da referência.

Outros bancos de dados geralmente copiam objetos do armazenamento do banco de dados para a memória do aplicativo quando você precisa trabalhar com eles diretamente. Como os objetos do aplicativo contêm referências diretas, você tem uma opção: copiar o objeto referido por cada referência direta para fora do banco de dados, caso seja necessário, ou apenas copiar a chave estrangeira de cada objeto e consultar o objeto com essa chave, se ele for acessado. Se você optar por copiar os objetos referenciados para a memória do aplicativo, poderá usar muitos recursos para objetos que nunca são acessados, mas se optar por copiar apenas a chave estrangeira, as pesquisas de objetos referenciados poderão causar lentidão no aplicativo.

O Realm contorna tudo isso com objetos ativos de cópia zero. Os acessadores de objeto de realm apontam diretamente para o armazenamento de banco de dados usando o mapeamento de memória, portanto não há distinção entre os objetos no Realm e os resultados da consulta na memória do aplicativo. Por isso você pode percorrer referências diretas em um domínio inteiro a partir de qualquer resultado de consulta.

Como resultado da avaliação preguiçosa, você não precisa de nenhum mecanismo especial para limitar os resultados da consulta com o Realm. Por exemplo, se a sua consulta corresponder a milhares de objetos, mas você quiser carregar somente os dez primeiros, basta acessar somente os dez primeiros elementos da collection de resultados.

Graças à avaliação preguiçosa, a tarefa comum da paginação se torna bastante simples. Por exemplo, suponha que você tenha uma coleção de resultados associada a uma consulta que corresponda a milhares de objetos em seu domínio. Você exibe cem objetos por página. Para avançar para qualquer página, basta acessar os elementos da coleta de resultados começando pelo índice que corresponde à página de destino.

Os exemplos nesta página usam os seguintes modelos:

Um filtro seleciona um subconjunto de resultados com base no(s) valor(es) de uma ou mais propriedades do objeto. O Realm oferece um mecanismo de consulta completo que você pode usar para definir filtros.

Dica

Filtrar nas Propriedades de Objetos Relacionados e Embarcados

Para filtrar uma consulta com base na propriedade de um objeto incorporado ou de um objeto relacionado, use a notação de pontos como se estivesse em um objeto normal aninhado.

Os tipos no seu predicado devem corresponder aos tipos das propriedades. Evite comparar propriedades de ObjectID com cadeias de caracteres, pois o Realm não converte automaticamente cadeias de caracteres em ObjectIDs.

Você pode fazer consultas por meio de um relacionamento da mesma forma que acessaria um nó de um objeto regular do Swift ou Objective-C.

Você pode fazer consultas por meio de um relacionamento inverso da mesma forma que acessaria um nó de um objeto regular do Swift ou Objective-C.

Use a notação de ponto para filtrar ou classificar uma coleção de objetos com base em um valor de propriedade de objeto incorporado:

Observação

Não é possível consultar objetos incorporados diretamente. Em vez disso, acesse objetos incorporados por meio de uma consulta para o tipo de objeto pai.

Você pode iterar e verificar os valores de um mapa Realm como faria com um Dicionário:

let realm = try! Realm()
let dogs = realm.objects(Dog.self)
// Find dogs who have favorite parks
let dogsWithFavoriteParks = dogs.where {
$0.favoriteParksByCity.count >= 1
}
for dog in dogsWithFavoriteParks {
// Check if an entry exists
if dog.favoriteParksByCity.keys.contains("Chicago") {
print("\(dog.name) has a favorite park in Chicago")
}
// Iterate over entries
for element in dog.favoriteParksByCity {
print("\(dog.name)'s favorite park in \(element.key) is \(element.value)")
}
}

Você pode consultar um MutableSet para verificar se ele contém um elemento. Se você estiver trabalhando com vários conjuntos, poderá verificar a interseção de dois conjuntos ou verificar se um conjunto é um subconjunto do outro.

let realm = try! Realm()
// Find dogs who have visited New York
let newYorkDogs = realm.objects(Dog.self).where {
$0.citiesVisited.contains("New York")
}
// Get some information about the cities they have visited
for dog in newYorkDogs {
print("Cities \(dog.name) has visited: \(dog.citiesVisited)")
}
// Check whether two dogs have visited some of the same cities.
// Use "intersects" to find out whether the values of the two sets share common elements.
let isInBothCitiesVisited = (dog.citiesVisited.intersects(dog2.citiesVisited))
print("The two dogs have visited some of the same cities: \(isInBothCitiesVisited)")
// Prints "The two dogs have visited some of the same cities: true"
// Or you can check whether a set is a subset of another set. In this example,
// the first dog has visited "New York" and "Toronto", while dog2 has visited both of
// those but also "Toronto" and "Boston".
let isSubset = (dog.citiesVisited.isSubset(of: dog2.citiesVisited))
print("\(dog.name)'s set of cities visited is a subset of \(dog2.name)'s: \(isSubset)")
// Prints "Maui's set of cities visited is a subset of Lita's: true"

Ao ler uma propriedade AnyRealmValue, verifique o tipo do valor antes de fazer qualquer coisa com ele. O Realm Swift SDK fornece um enum AnyRealmValue que itera por todos os tipos que o AnyRealmValue pode armazenar.

let realm = try! Realm()
let dogs = realm.objects(Dog.self)
for dog in dogs {
// Verify the type of the ``AnyRealmProperty`` when attempting to get it. This
// returns an object whose property contains the matched type.
// If you only care about one type, check for that type.
if case let .string(companion) = dog.companion {
print("\(dog.name)'s companion is: \(companion)")
// Prints "Wolfie's companion is: Fluffy the Cat"
}
// Or if you want to do something with multiple types of data
// that could be in the value, switch on the type.
switch dog.companion {
case .string:
print("\(dog.name)'s companion is: \(dog.companion)")
// Prints "Wolfie's companion is: string("Fluffy the Cat")
case .object:
print("\(dog.name)'s companion is: \(dog.companion)")
// Prints "Fido's companion is: object(Dog { name = Spot })"
case .none:
print("\(dog.name) has no companion")
// Prints "Rex has no companion" and "Spot has no companion"
default:
print("\(dog.name)'s companion is another type.")
}
}

Você pode comparar esses tipos de valores mistos:

  • Numérico: int, bool, float, duplo, decimal

  • Baseado em bytes: string, binário

  • Baseado em tempo: carimbo de data/hora, objectId

Ao usar o tipo de dados misto AnyRealmValue, lembre-se do seguinte:

  • equals consultas fazem a correspondência de valor e tipo

  • not equals consultas fazem a correspondência de objetos com valores ou tipos diferentes

  • realm converte propriedades numéricas comparáveis sempre que possível. Por exemplo, em um campo de tipo misto, 1 corresponde a todos 1.0, 1 e verdadeiro.

  • As propriedades de string não correspondem a consultas numéricas. Por exemplo, em um campo de tipo misto, 1 não corresponde a "1". "1" não corresponde a 1, 1.0 ou verdadeiro.

Novidades na versão 10.47.0.

O Swift SDK fornece diversas formas para simplificar a query de dados geospaciais. Você pode usar as formas GeoCircle, GeoBox e GeoPolygon para definir os limites de suas queries de dados geoespaciais.

O SDK fornece dois tipos de dados especializados não persistentes para definir formas:

  • GeoPoint: uma estrutura que representa as coordenadas de uma ponta formada por um par de duplos contendo estes valores:

    • Latitude: varia entre -90 e 90 graus, inclusivo.

    • Longitude: varia entre -180 e 180 graus, inclusivo.

  • RLMDistance: uma estrutura auxiliar para representar e converter uma distância.

Você pode usar estas formas em uma query geoespacial. Você pode executar uma query de dados geoespaciais de três maneiras:

  • Usar o operador .geoWithin() com a API Realm Swift Query com segurança de tipo

  • Usar um .filter() com RQL

  • Usar um .filter() com uma query NSPredicate

Os exemplos abaixo mostram os resultados das queries usando estes dois objetos Company:

let company1 = Geospatial_Company()
company1.location = CustomGeoPoint(47.68, -122.35)
let company2 = Geospatial_Company(CustomGeoPoint(47.9, -121.85))
2 GeoPoints
clique para ampliar

Quando você usa a projeção de tipo para mapear tipos sem suporte para tipos com suporte, o acesso a essas propriedades geralmente é baseado no tipo persistente.

Ao trabalhar com tipos projetados, as consultas operam no tipo persistente. No entanto, você pode usar os tipos mapeados de forma intercambiável com os tipos persistentes em argumentos na maioria dos casos. A exceção são consultas em objetos incorporados.

Dica

Os tipos projetados suportam classificação e agregados onde o tipo persistente os suporta.

let akcClub = realm.objects(Club.self).where {
$0.name == "American Kennel Club"
}.first!
// You can use type-safe expressions to check for equality
XCTAssert(akcClub.url == URL(string: "https://akc.org")!)
let clubs = realm.objects(Club.self)
// You can use the persisted property type in NSPredicate query expressions
let akcByUrl = clubs.filter("url == 'https://akc.org'").first!
XCTAssert(akcByUrl.name == "American Kennel Club")

Você pode consultar tipos embarcados nos tipos de propriedade permitidos dentro do objeto utilizando a igualdade de todos os nós.

As propriedades do link de objeto suportam comparações de igualdade, mas não oferecem suporte a comparações entre nós. Você pode consultar objetos incorporados para obter igualdade de nós em todos os tipos primitivos. Você não pode realizar comparações entre nós em objetos e coleções.

Como o esquema não tem nenhum conceito de mapeamentos de tipos personalizados, a leitura de dados por meio de qualquer uma das APIs dinâmicas fornece o tipo persistente subjacente. O Realm oferece suporte à gravação de tipos mapeados por meio de uma API dinâmica e converte o tipo projetado em tipo persistente.

O uso mais comum das APIs dinâmicas é a migração. Você pode escrever tipos projetados durante a migração, e o Realm converte o tipo projetado no tipo persistente. No entanto, a leitura de dados durante uma migração fornece o tipo persistente subjacente.

Quando usar um realm isolado por atores, você pode usar as funcionalidades de simultaneidade do Swift para consultar objetos de forma assíncrona.

let actor = try await RealmActor()
// Read objects in functions isolated to the actor and pass primitive values to the caller
func getObjectId(in actor: isolated RealmActor, forTodoNamed name: String) async -> ObjectId {
let todo = actor.realm.objects(Todo.self).where {
$0.name == name
}.first!
return todo._id
}
let objectId = await getObjectId(in: actor, forTodoNamed: "Keep it safe")

Se você precisar avançar manualmente o estado de um realm observado na thread principal ou de um realm isolado por ator, chame await realm.asyncRefresh(). Isso atualiza o realm e os objetos pendentes gerenciados pelo Realm para apontar para os dados mais recentes e fornecer quaisquer notificações aplicáveis.

Para obter mais informações sobre como trabalhar com o domínio usando os recursos de simultaneidade do Swift, consulte Use Realm with Actors - Swift SDK.

Uma operação de classificação permite que você configure a ordem em que o Realm Database retorna os objetos consultados. Você pode classificar com base em uma ou mais propriedades dos objetos na coleção de resultados. O Realm só garante uma ordem consistente de resultados se você classificá-los explicitamente.

Dica

Classificar nas Propriedades de Objetos Relacionados e Embarcados

Para classificar uma consulta com base em uma propriedade de um objeto incorporado ou de um objeto relacionado, use não anotação como se estivesse em um objeto aninhado regular.

Observação

Somente é permitido classificar strings e consultas sem diferenciação de maiúsculas e minúsculas para conjuntos de caracteres em 'Latin Basic', 'Latin Supplement', 'Latin Extended A' e 'Latin Extended B' (UTF-8 faixa 0-591).

Você pode dividir os resultados em seções individuais. Cada seção corresponde a uma chave gerada a partir de uma propriedade no objeto que representa.

Por exemplo, você pode adicionar uma variável computada ao seu objeto para ter a primeira letra da propriedade name:

// Computed variable that is not persisted, but only
// used to section query results.
var firstLetter: String {
return name.first.map(String.init(_:)) ?? ""
}

Em seguida, você pode criar uma coleção segura de tipo SectionedResults para esse objeto e usá-la para recuperar objetos seccionados por essa variável computada:

var dogsByFirstLetter: SectionedResults<String, Dog>
dogsByFirstLetter = realm.objects(Dog.self).sectioned(by: \.firstLetter, ascending: true)

Você pode obter uma contagem das seções, obter uma lista de chaves ou acessar uma resultSection individual por índice:

let realm = try! Realm()
var dogsByFirstLetter: SectionedResults<String, Dog>
dogsByFirstLetter = realm.objects(Dog.self).sectioned(by: \.firstLetter, ascending: true)
// You can get a count of the sections in the SectionedResults
let sectionCount = dogsByFirstLetter.count
// Get an array containing all section keys for objects that match the query.
let sectionKeys = dogsByFirstLetter.allKeys
// This example realm contains 4 dogs, "Rex", "Wolfie", "Fido", "Spot".
// Prints ["F", "R", "S", "W"]
print(sectionKeys)
// Get a specific key by index position
let sectionKey = dogsByFirstLetter[0].key
// Prints "Key for index 0: F"
print("Key for index 0: \(sectionKey)")
// You can access Results Sections by the index of the key you want in SectionedResults.
// "F" is the key at index position 0. When we access this Results Section, we get dogs whose name begins with "F".
let dogsByF = dogsByFirstLetter[0]
// Prints "Fido"
print(dogsByF.first?.name)

Você também pode seccionar usando um retorno de chamada de resposta. Isso permite seccionar uma coleção de primitivos ou ter mais controle sobre como a chave de seção é gerada.

let realm = try! Realm()
let results = realm.objects(Dog.self)
let sectionedResults = results.sectioned(by: { String($0.name.first!) },
sortDescriptors: [SortDescriptor.init(keyPath: "name", ascending: true)])
let sectionKeys = sectionedResults.allKeys

Você pode observar instâncias do e ambos estão em ResultsSection com SectionedResults .

Você pode usar os operadores de agregação do Realm para consultas sofisticadas em relação às propriedades da lista.

Como os resultados são avaliados preguiçosamente, você pode agrupar várias consultas. Ao contrário dos bancos de dados tradicionais, isso não requer uma viagem separada ao banco de dados para cada query sucessiva.

Exemplo

Para obter um conjunto de resultados para cães amarelos e cães amarelos cujos nomes começam com 'B', encadeie duas consultas dessa forma:

Para consultar as projeções de classe em um realm, passe a instância do meta-tipo YourProjectionName.self para Realm.objects(_:). Isso retorna um objeto Results que representa todos os objetos de projeção de classe no realm.

// Retrieve all class projections of the given type `PersonProjection`
let people = realm.objects(PersonProjection.self)
// Use projection data in your view
print(people.first?.firstName)
print(people.first?.homeCity)
print(people.first?.firstFriendsName)

Dica

Não faça consultas derivadas sobre os resultados da projeção da classe. Em vez disso, execute uma consulta com o objeto Realm diretamente e, em seguida, projete o resultado. Se você tentar fazer uma consulta derivada no topo dos resultados de projeção da classe, consultar um campo com o mesmo nome e tipo que o objeto original funciona, mas consultar um campo com um nome ou tipo que não está no objeto original falha.

← CRUD - Criar - Swift SDK