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
Ler de um Realm
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, classifica 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.
Leia as características
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 não são cópias
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.
Os resultados são preguiçosos
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.
As referências são retidas
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.
Limitando resultados da 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.
Paginação
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.
Ler objetos de domínio
Sobre os exemplos nesta página
Os exemplos nesta página usam os seguintes modelos:
// DogToy.h @interface DogToy : RLMObject @property NSString *name; @end // Dog.h @interface Dog : RLMObject @property NSString *name; @property int age; @property NSString *color; // To-one relationship @property DogToy *favoriteToy; @end // Enable Dog for use in RLMArray RLM_COLLECTION_TYPE(Dog) // Person.h // A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs. @interface Person : RLMObject @property int _id; @property NSString *name; // To-many relationship - a person can have many dogs @property RLMArray<Dog *><Dog> *dogs; // Inverse relationship - a person can be a member of many clubs @property (readonly) RLMLinkingObjects *clubs; @end RLM_COLLECTION_TYPE(Person) // DogClub.h @interface DogClub : RLMObject @property NSString *name; @property RLMArray<Person *><Person> *members; @end // Dog.m @implementation Dog @end // DogToy.m @implementation DogToy @end // Person.m @implementation Person // Define the primary key for the class + (NSString *)primaryKey { return @"_id"; } // Define the inverse relationship to dog clubs + (NSDictionary *)linkingObjectsProperties { return @{ @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"], }; } @end // DogClub.m @implementation DogClub @end
class DogToy: Object { var id: ObjectId var name = "" } class Dog: Object { var name = "" var age = 0 var color = "" var currentCity = "" var citiesVisited: MutableSet<String> var companion: AnyRealmValue // To-one relationship var favoriteToy: DogToy? // Map of city name -> favorite park in that city var favoriteParksByCity: Map<String, String> // Computed variable that is not persisted, but only // used to section query results. var firstLetter: String { return name.first.map(String.init(_:)) ?? "" } } class Person: Object { true) var id = 0 (primaryKey: var name = "" // To-many relationship - a person can have many dogs var dogs: List<Dog> // Inverse relationship - a person can be a member of many clubs "members") var clubs: LinkingObjects<DogClub> (originProperty: // Embed a single object. // Embedded object properties must be marked optional. var address: Address? convenience init(name: String, address: Address) { self.init() self.name = name self.address = address } } class DogClub: Object { var name = "" var members: List<Person> // DogClub has an array of regional office addresses. // These are embedded objects. var regionalOfficeAddresses: List<Address> convenience init(name: String, addresses: [Address]) { self.init() self.name = name self.regionalOfficeAddresses.append(objectsIn: addresses) } } class Address: EmbeddedObject { var street: String? var city: String? var country: String? var postalCode: String? }
Encontrar um objeto específico por chave primária
Se você souber a chave primária de um determinado objeto, poderá procurá-la diretamente com +[RLMObject objectForPrimaryKey:].
// Get a specific person from the default realm Person *specificPerson = [Person objectForPrimaryKey:@12345];
Se você souber qual é a chave primária de um determinado objeto, poderá buscá-la diretamente com Realm.object(ofType:forPrimaryKey:).
let realm = try! Realm() let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345)
Consultar todos os objetos de dado específico
Para executar query de objetos de um determinado tipo em um Realm, passe a instância do Realm para +[ YourRealmObjectClass allObjectsInRealm:]. Substitua YourRealmObjectClass
pelo nome da classe de Objeto de Realm . Esse comando retorna um objeto RLMResults que representa todos os objetos de um determinado tipo no Realm.
RLMRealm *realm = [RLMRealm defaultRealm]; RLMResults *dogs = [Dog allObjectsInRealm:realm]; RLMResults *people = [Person allObjectsInRealm:realm];
Para buscar objetos de um determinado tipo em um domínio, passe a instância do metatipo YourClassName.self
para Realm.objects(_:). Esse comando retorna um objeto Results que representa todos os objetos de um determinado tipo no domínio.
let realm = try! Realm() // Access all dogs in the realm let dogs = realm.objects(Dog.self)
Filtrar consultas com base nas propriedades do objeto
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.
Novidades na versão 10,19,0.
Para usar a API de consulta do Realm Swift, chame .where com um fechamento que contenha uma expressão query como argumento.
let realm = try! Realm() // Access all dogs in the realm let dogs = realm.objects(Dog.self) // Query by age let puppies = dogs.where { $0.age < 2 } // Query by person let dogsWithoutFavoriteToy = dogs.where { $0.favoriteToy == nil } // Query by person's name let dogsWhoLikeTennisBalls = dogs.where { $0.favoriteToy.name == "Tennis ball" }
Para filtrar, chame Results.filter(_:) com um predicado de query.
let realm = try! Realm() // Access all dogs in the realm let dogs = realm.objects(Dog.self) // Filter by age let puppies = dogs.filter("age < 2") // Filter by person let dogsWithoutFavoriteToy = dogs.filter("favoriteToy == nil") // Filter by person's name let dogsWhoLikeTennisBalls = dogs.filter("favoriteToy.name == 'Tennis ball'")
Para filtrar, chame -[RLMResults objectswhere:] com um predicado de query.
RLMRealm *realm = [RLMRealm defaultRealm]; // Access all dogs in the realm RLMResults *dogs = [Dog allObjectsInRealm:realm]; // Filter by age RLMResults *puppies = [dogs objectsWhere:@"age < 2"]; // Filter by favorite toy RLMResults *dogsWithoutFavoriteToy = [dogs objectsWhere:@"favoriteToy == nil"]; // Filter by favorite toy's name RLMResults *dogsWhoLikeTennisBalls = [dogs objectsWhere:@"favoriteToy.name == %@", @"Tennis ball"];
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.
Filtro sobre Propriedades de ID de objeto
Os tipos no seu predicado devem corresponder aos tipos das propriedades. Evite comparar propriedades de ObjectID com strings, pois o Realm não converte automaticamente strings em ObjectIDs.
Novidades na versão 10,19,0.
A segurança do tipo integrado da Realm Swift Query API simplifica a escrita de uma consulta com um ObjectId:
let realm = try! Realm() let dogToys = realm.objects(DogToy.self) // Get specific user by ObjectId id let specificToy = dogToys.where { $0.id == ObjectId("11223344556677889900aabb") }
O exemplo a seguir mostra a maneira correta e incorreta de escrever uma query com um ObjectId dado o seguinte objeto Realm:
let realm = try! Realm() let dogToys = realm.objects(DogToy.self) // Get specific toy by ObjectId id let specificToy = dogToys.filter("id = %@", ObjectId("11223344556677889900aabb")).first // WRONG: Realm will not convert the string to an object id // users.filter("id = '11223344556677889900aabb'") // not ok // users.filter("id = %@", "11223344556677889900aabb") // not ok
Fazer query em um relacionamento
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.
RLMRealm *realm = [RLMRealm defaultRealm]; // Establish a relationship Dog *dog = [[Dog alloc] init]; dog.name = @"Rex"; dog.age = 10; Person *person = [[Person alloc] init]; person._id = 12345; [person.dogs addObject:dog]; [realm transactionWithBlock:^() { [realm addObject:person]; }]; // Later, query the specific person Person *specificPerson = [Person objectForPrimaryKey:@12345]; // Access directly through a relationship NSLog(@"# dogs: %lu", [specificPerson.dogs count]); NSLog(@"First dog's name: %@", specificPerson.dogs[0].name);
let realm = try! Realm() // Establish a relationship let dog = Dog() dog.name = "Rex" dog.age = 10 let person = Person() person.id = 12345 person.dogs.append(dog) try! realm.write { realm.add(person) } // Later, query the specific person let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345) // Access directly through a relationship let specificPersonDogs = specificPerson!.dogs let firstDog = specificPersonDogs[0] print("# dogs: \(specificPersonDogs.count)") print("First dog's name: \(firstDog.name)")
Consultar um Relacionamento Inverso
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.
RLMRealm *realm = [RLMRealm defaultRealm]; // Establish a relationship Person *person = [[Person alloc] init]; person._id = 12345; DogClub *club = [[DogClub alloc] init]; club.name = @"Pooch Pals"; [club.members addObject:person]; [realm transactionWithBlock:^() { [realm addObject:club]; }]; // Later, query the specific person Person *specificPerson = [Person objectForPrimaryKey:@12345]; // Access directly through an inverse relationship NSLog(@"# memberships: %lu", [specificPerson.clubs count]); NSLog(@"First club's name: %@", [specificPerson.clubs[0] name]);
let realm = try! Realm() // Establish an inverse relationship let person = Person() person.id = 12345 let club = DogClub() club.name = "Pooch Pals" club.members.append(person) try! realm.write { realm.add(club) } // Later, query the specific person let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345) // Access directly through an inverse relationship let clubs = specificPerson!.clubs let firstClub = clubs[0] print("# memberships: \(clubs.count)") print("First club's name: \(firstClub.name)")
Consultar uma Coleção sobre Propriedades de Objetos Embarcados
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.
Novidades na versão 10,19,0.
// Open the default realm let realm = try! Realm() // Get all contacts in Los Angeles, sorted by street address let losAngelesPeople = realm.objects(Person.self) .where { $0.address.city == "Los Angeles" } .sorted(byKeyPath: "address.street") print("Los Angeles Person: \(losAngelesPeople)")
// Open the default realm let realm = try! Realm() // Get all people in Los Angeles, sorted by street address let losAngelesPeople = realm.objects(Person.self) .filter("address.city = %@", "Los Angeles") .sorted(byKeyPath: "address.street") print("Los Angeles Person: \(losAngelesPeople)")
RLMRealm *realm = [RLMRealm defaultRealm]; RLMResults<Contact *> *losAngelesContacts = [Contact objectsInRealm:realm where:@"address.city = %@", @"Los Angeles"]; losAngelesContacts = [losAngelesContacts sortedResultsUsingKeyPath:@"address.street" ascending:YES]; NSLog(@"Los Angeles Contacts: %@", losAngelesContacts);
Consultar uma Propriedade de Mapa
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)") } }
Fazer query em uma propriedade MutableSet
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"
Ler e Consultar Propriedade AnyRealmValue
Ao ler uma propriedade AnyRealmValue, verifique o tipo do valor antes de fazer qualquer coisa com ele. O Realm Swift SDK fornece um enumeração 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, double, 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 tiponot equals
consultas fazem a correspondência de objetos com valores ou tipos diferentesdomínio 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.
Executar query de dados geoespaciais
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 doubles 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.
Definir formas geoespaciais
Um GeoCircle
é uma forma circular cujos limites têm como origem um GeoPoint
central e tem um tamanho correspondente a um raio medido em radianos. Você pode usar o tipo de dados conveniente RLMDistance
do SDK para trabalhar com raios em unidades diferentes.
RLMDistance
permite especificar a distância de raio para as suas formas geográficas em uma das quatro unidades:
.degrees
.kilometers
.miles
.radians
Opcionalmente, você pode usar os métodos de conveniência fornecidos para converter uma medida em outras unidades de distância.
// You can create a GeoCircle radius measured in radians. // This radian distance corresponds with 0.25 degrees. let smallCircle = GeoCircle(center: (47.3, -121.9), radiusInRadians: 0.004363323) // You can also create a GeoCircle radius measured with a Distance. // You can specify a Distance in .degrees, .kilometers, .miles, or .radians. let largeCircle = GeoCircle(center: GeoPoint(latitude: 47.8, longitude: -122.6)!, radius: Distance.kilometers(44.4)!)

Um GeoBox
é uma forma retângulo cujos limites são determinados por coordenadas para um canto inferior esquerdo e um canto superior direito.
let largeBox = GeoBox(bottomLeft: (47.3, -122.7), topRight: (48.1, -122.1)) let smallBoxBottomLeft = GeoPoint(latitude: 47.5, longitude: -122.4)! let smallBoxTopRight = GeoPoint(latitude: 47.9, longitude: -121.8) let smallBox = GeoBox(bottomLeft: smallBoxBottomLeft, topRight: smallBoxTopRight!)

Um GeoPolygon
é uma forma de polígono cujos limites consistem em um anel externo e 0 ou mais orifícios internos a serem excluídos da query geoespacial.
O anel externo de um polígono deve conter pelo menos três segmentos. O último e o primeiro GeoPoint
devem ser iguais, o que indica um polígono fechado. Isto significa que são necessários pelo menos quatro GeoPoint
valores para construir um polígono.
Os orifícios internos em um GeoPolygon
devem estar inteiramente contidos no anel externo.
Os furos têm as seguintes restrições:
Os orifícios podem não se cruzar. O limite de um orifício não pode cruzar o interno e o externo de qualquer outro orifício.
Os furos podem não compartilhar bordas. Se um orifício contém uma aresta BI, nenhum outro orifício pode contê-la.
Os furos podem compartilhar vértices. No entanto, nenhum vértice pode aparecer duas vezes em um único orifício.
Nenhum vazio pode estar vazio.
Apenas um aninhamento é permitido.
// Create a basic polygon let basicPolygon = GeoPolygon(outerRing: [ (48.0, -122.8), (48.2, -121.8), (47.6, -121.6), (47.0, -122.0), (47.2, -122.6), (48.0, -122.8) ]) // Create a polygon with one hole let outerRing: [GeoPoint] = [ GeoPoint(latitude: 48.0, longitude: -122.8)!, GeoPoint(latitude: 48.2, longitude: -121.8)!, GeoPoint(latitude: 47.6, longitude: -121.6)!, GeoPoint(latitude: 47.0, longitude: -122.0)!, GeoPoint(latitude: 47.2, longitude: -122.6)!, GeoPoint(latitude: 48.0, longitude: -122.8)! ] let hole: [GeoPoint] = [ GeoPoint(latitude: 47.8, longitude: -122.6)!, GeoPoint(latitude: 47.7, longitude: -122.2)!, GeoPoint(latitude: 47.4, longitude: -122.6)!, GeoPoint(latitude: 47.6, longitude: -122.5)!, GeoPoint(latitude: 47.8, longitude: -122.6)! ] let polygonWithOneHole = GeoPolygon(outerRing: outerRing, holes: [hole]) // Add a second hole to the polygon let hole2: [GeoPoint] = [ GeoPoint(latitude: 47.55, longitude: -122.05)!, GeoPoint(latitude: 47.55, longitude: -121.9)!, GeoPoint(latitude: 47.3, longitude: -122.1)!, GeoPoint(latitude: 47.55, longitude: -122.05)! ] let polygonWithTwoHoles = GeoPolygon(outerRing: outerRing, holes: [hole, hole2])

Executar query com formas geoespaciais
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 tipoUsar um
.filter()
com RQLUsar 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))

let companiesInSmallCircle = realm.objects(Geospatial_Company.self).where { $0.location.geoWithin(smallCircle!) } print("Number of companies in small circle: \(companiesInSmallCircle.count)") let companiesInLargeCircle = realm.objects(Geospatial_Company.self) .filter("location IN %@", largeCircle) print("Number of companies in large circle: \(companiesInLargeCircle.count)")

let companiesInSmallBox = realm.objects(Geospatial_Company.self).where { $0.location.geoWithin(smallBox) } print("Number of companies in small box: \(companiesInSmallBox.count)") let filterArguments = NSMutableArray() filterArguments.add(largeBox) let companiesInLargeBox = realm.objects(Geospatial_Company.self) .filter(NSPredicate(format: "location IN %@", argumentArray: filterArguments as? [Any])) print("Number of companies in large box: \(companiesInLargeBox.count)")

let companiesInBasicPolygon = realm.objects(Geospatial_Company.self).where { $0.location.geoWithin(basicPolygon!) } print("Number of companies in basic polygon: \(companiesInBasicPolygon.count)") let companiesInPolygonWithTwoHoles = realm.objects(Geospatial_Company.self).where { $0.location.geoWithin(polygonWithTwoHoles!) } print("Number of companies in polygon with two holes: \(companiesInPolygonWithTwoHoles.count)")

Fazer query em uma propriedade persistente personalizada
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.
Consultas sobre Objetos de Realm
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")
consultas sobre objetos embarcados
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.
APIs dinâmicas
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.
Ler um Objeto de Forma Assíncrona
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.
Classificar Resultados da Consulta
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.
Para classificar, chame -[RLMResults sortedResultsUsingKeyPath:ascending:] com o caminho da chave desejado para a classificação.
RLMRealm *realm = [RLMRealm defaultRealm]; RLMResults *dogs = [Dog allObjectsInRealm:realm]; // Sort dogs by name RLMResults *dogsSorted = [dogs sortedResultsUsingKeyPath:@"name" ascending:NO]; // You can also sort on the members of linked objects. In this example, // we sort the dogs by their favorite toys' names. RLMResults *dogsSortedByFavoriteToyName = [dogs sortedResultsUsingKeyPath:@"favoriteToy.name" ascending:YES];
Novidade na versão 10.11.0.
Você pode classificar com o keyPath seguro ao chamar Results.sorted(by: ) com o nome do keyPath e a ordem de classificação opcional:
let realm = try! Realm() // Access all dogs in the realm let dogs = realm.objects(Dog.self) // Sort by type-safe keyPath let dogsSorted = dogs.sorted(by: \.name)
Para classificar usando a API mais antiga, chame Results.sorted(byKeyPath:ascending:) com o caminho da chave desejado para a classificação.
let realm = try! Realm() // Access all dogs in the realm let dogs = realm.objects(Dog.self) let dogsSorted = dogs.sorted(byKeyPath: "name", ascending: false) // You can also sort on the members of linked objects. In this example, // we sort the dogs by their favorite toys' names. let dogsSortedByFavoriteToyName = dogs.sorted(byKeyPath: "favoriteToy.name")
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).
Resultados da Consulta da Seção
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 SectionedResults
e ResultsSection
e ambos estão em conformidade com ThreadConfined.
Dados agregados
Você pode usar os operadores de agregação do Realm para consultas sofisticadas em relação às propriedades da lista.
Novidades na versão 10,19,0.
let realm = try! Realm() let people = realm.objects(Person.self) // People whose dogs' average age is 5 people.where { $0.dogs.age.avg == 5 } // People with older dogs people.where { $0.dogs.age.min > 5 } // People with younger dogs people.where { $0.dogs.age.max < 2 } // People with many dogs people.where { $0.dogs.count > 2 } // People whose dogs' ages combined > 10 years people.where { $0.dogs.age.sum > 10 }
let realm = try! Realm() let people = realm.objects(Person.self) // People whose dogs' average age is 5 people.filter("dogs.@avg.age == 5") // People with older dogs people.filter("dogs.@min.age > 5") // People with younger dogs people.filter("dogs.@max.age < 2") // People with many dogs people.filter("dogs.@count > 2") // People whose dogs' ages combined > 10 years people.filter("dogs.@sum.age > 10")
RLMRealm *realm = [RLMRealm defaultRealm]; RLMResults *people = [Person allObjectsInRealm:realm]; // People whose dogs' average age is 5 [people objectsWhere:@"dogs.@avg.age == 5"]; // People with older dogs [people objectsWhere:@"dogs.@min.age > 5"]; // People with younger dogs [people objectsWhere:@"dogs.@max.age < 2"]; // People with many dogs [people objectsWhere:@"dogs.@count > 2"]; // People whose dogs' ages combined > 10 years [people objectsWhere:@"dogs.@sum.age > 10"];
Consultas em cadeia
Como os resultados são avaliados preguiçosamente, você pode agrupar várias consultas. Diferentemente dos bancos de dados tradicionais, isso não exige uma viagem separada ao banco de dados para cada consulta 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:
Novidades na versão 10,19,0.
let realm = try! Realm() let tanDogs = realm.objects(Dog.self).where { $0.color == "tan" } let tanDogsWithBNames = tanDogs.where { $0.name.starts(with: "B") }
let realm = try! Realm() let tanDogs = realm.objects(Dog.self).filter("color = 'tan'") let tanDogsWithBNames = tanDogs.filter("name BEGINSWITH 'B'")
RLMRealm *realm = [RLMRealm defaultRealm]; RLMResults<Dog *> *tanDogs = [Dog objectsInRealm:realm where:@"color = 'tan'"]; RLMResults<Dog *> *tanDogsWithBNames = [tanDogs objectsWhere:@"name BEGINSWITH 'B'"];
Projeções de Classes de Consulta
Para consultar as projeções de classe em um domínio, 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 domínio.
// 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.