Skip to content

Commit 806bec3

Browse files
ObjectBox Swift database 4.2.0
1 parent 565e4c5 commit 806bec3

19 files changed

+647
-43
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ Notable changes to the ObjectBox Swift library.
44

55
For more insights into what changed in the ObjectBox C++ core, [check the ObjectBox C changelog](https://github.com/objectbox/objectbox-c/blob/main/CHANGELOG.md).
66

7-
## Next release
7+
## 4.2.0 - 2025-04-09
88

99
- Vector Search: add new `geo` distance type to perform vector searches on geographical coordinates.
1010
This is particularly useful for location-based applications.
1111
- Make `Store.close()` public. This function may be useful for when the deinitializer of `Store` is called too late
1212
(which closes the Store as well), or for unit tests.
13+
- Update ObjectBox database to [4.2.0](https://github.com/objectbox/objectbox-c/releases/tag/v4.2.0).
1314

1415
## 4.0.1 - 2024-10-16
1516

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ Here's a list of ObjectBox releases, and the Swift versions they were compiled w
107107

108108
| ObjectBox version(s) | Swift version |
109109
|:--------------------:|:-------------:|
110+
| 4.2.0 | 5.10 |
111+
| 4.1.0 | 6.0 |
110112
| 4.0.1 | 5.9 |
111113
| 4.0.0 | 5.9 |
112114
| 2.0.0 | 5.9 |
@@ -166,7 +168,7 @@ ObjectBox is a cross-platform database supporting sustainable app development in
166168
## License
167169

168170
```text
169-
Copyright 2018-2024 ObjectBox Ltd. All rights reserved.
171+
Copyright 2018-2025 ObjectBox Ltd. All rights reserved.
170172
171173
Licensed under the Apache License, Version 2.0 (the "License");
172174
you may not use this file except in compliance with the License.

Source/.ruby-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.4.2
1+
3.2.7

Source/fetch_dependencies.command

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ set -e
1313

1414
# objectbox-swift release version on GitHub:
1515
# https://github.com/objectbox/objectbox-swift/releases/download/v${version}
16-
version=4.1.0
16+
version=4.2.0
1717

1818
# C library version attached to the GitHub release:
1919
# ObjectBoxCore-static-${c_version}.zip
20-
c_version=4.1.0
20+
c_version=4.2.0
2121

2222
# Params supported by apple-build-static-libs.sh
2323
if [ -n "$OBX_SKIP_STATIC_C_TESTS" ]; then
@@ -67,6 +67,9 @@ if [ -d "$code_dir" ] && [ "$staging_repo" != "true" ]; then # Do we have an exi
6767
xcode_version="$(xcodebuild -version | head -n 1 | tr -cd '[a-zA-Z0-9]._-')"
6868
echo "Xcode version: $xcode_version"
6969

70+
# Enable the Vector Search feature objectbox/objectbox#1038
71+
export OBX_FEATURES="VectorSearch"
72+
7073
# Build cache key: includes commit, XCode version, extra features, build command parameters
7174
commit_id=$(git rev-parse HEAD)
7275
cache_key="${commit_id}-$xcode_version"

Source/ios-framework/CodeGenTests/ToolTestProject59.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright © 2024 ObjectBox Ltd. All rights reserved.
2+
// Copyright © 2024-2025 ObjectBox Ltd. All rights reserved.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@ class CityDefaults {
2929
class CityAllProperties {
3030
var id: Id = 0
3131

32-
// objectbox:hnswIndex: dimensions=2, neighborsPerNode=30, indexingSearchCount=100, flags="debugLogs,debugLogsDetailed,reparationLimitCandidates,vectorCacheSimdPaddingOff", distanceType="euclidean", reparationBacklinkProbability=0.95, vectorCacheHintSizeKB=2097152
32+
// objectbox:hnswIndex: dimensions=2, neighborsPerNode=30, indexingSearchCount=100, flags="debugLogs,debugLogsDetailed,reparationLimitCandidates,vectorCacheSimdPaddingOff", distanceType="geo", reparationBacklinkProbability=0.95, vectorCacheHintSizeKB=2097152
3333
var coordinates: [Float]?
3434

3535
}

Source/ios-framework/CodeGenTests/expected/entity-info/EntityInfo.generated59.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extension CityAllProperties: ObjectBox.EntityInspectable {
3030
let entityBuilder = try modelBuilder.entityBuilder(for: CityAllProperties.self, id: 1, uid: 17664)
3131
try entityBuilder.addProperty(name: "id", type: PropertyType.long, flags: [.id], id: 1, uid: 14592)
3232
try entityBuilder.addProperty(name: "coordinates", type: PropertyType.floatVector, flags: [.indexed], id: 2, uid: 16640, indexId: 1, indexUid: 15616)
33-
.hnswParams(dimensions: 2, neighborsPerNode: 30, indexingSearchCount: 100, flags: [HnswFlags.debugLogs, HnswFlags.debugLogsDetailed, HnswFlags.reparationLimitCandidates, HnswFlags.vectorCacheSimdPaddingOff], distanceType: HnswDistanceType.euclidean, reparationBacklinkProbability: 0.95, vectorCacheHintSizeKB: 2097152)
33+
.hnswParams(dimensions: 2, neighborsPerNode: 30, indexingSearchCount: 100, flags: [HnswFlags.debugLogs, HnswFlags.debugLogsDetailed, HnswFlags.reparationLimitCandidates, HnswFlags.vectorCacheSimdPaddingOff], distanceType: HnswDistanceType.geo, reparationBacklinkProbability: 0.95, vectorCacheHintSizeKB: 2097152)
3434

3535
try entityBuilder.lastProperty(id: 2, uid: 16640)
3636
}

Source/ios-framework/CodeGenTests/expected/schema-dump/schemaDump59.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Schema {
4343
neighborsPerNode = Optional(30)
4444
indexingSearchCount = Optional(100)
4545
flags = Optional("[HnswFlags.debugLogs, HnswFlags.debugLogsDetailed, HnswFlags.reparationLimitCandidates, HnswFlags.vectorCacheSimdPaddingOff]")
46-
distanceType = Optional("HnswDistanceType.euclidean")
46+
distanceType = Optional("HnswDistanceType.geo")
4747
reparationBacklinkProbability = Optional(0.95)
4848
vectorCacheHintSizeKB = Optional(2097152)
4949
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
// Generated using the ObjectBox Swift Generator — https://objectbox.io
2+
// DO NOT EDIT
3+
4+
// swiftlint:disable all
5+
import ObjectBox
6+
import Foundation
7+
8+
// MARK: - Entity metadata
9+
10+
extension CityAllProperties: ObjectBox.Entity {}
11+
extension CityDefaults: ObjectBox.Entity {}
12+
13+
extension CityAllProperties: ObjectBox.__EntityRelatable {
14+
internal typealias EntityType = CityAllProperties
15+
16+
internal var _id: EntityId<CityAllProperties> {
17+
return EntityId<CityAllProperties>(self.id.value)
18+
}
19+
}
20+
21+
extension CityAllProperties: ObjectBox.EntityInspectable {
22+
internal typealias EntityBindingType = CityAllPropertiesBinding
23+
24+
/// Generated metadata used by ObjectBox to persist the entity.
25+
internal static var entityInfo = ObjectBox.EntityInfo(name: "CityAllProperties", id: 1)
26+
27+
internal static var entityBinding = EntityBindingType()
28+
29+
fileprivate static func buildEntity(modelBuilder: ObjectBox.ModelBuilder) throws {
30+
let entityBuilder = try modelBuilder.entityBuilder(for: CityAllProperties.self, id: 1, uid: 17664)
31+
try entityBuilder.addProperty(name: "id", type: PropertyType.long, flags: [.id], id: 1, uid: 14592)
32+
try entityBuilder.addProperty(name: "coordinates", type: PropertyType.floatVector, flags: [.indexed], id: 2, uid: 16640, indexId: 1, indexUid: 15616)
33+
.hnswParams(dimensions: 2, neighborsPerNode: 30, indexingSearchCount: 100, flags: [HnswFlags.debugLogs, HnswFlags.debugLogsDetailed, HnswFlags.reparationLimitCandidates, HnswFlags.vectorCacheSimdPaddingOff], distanceType: HnswDistanceType.euclidean, reparationBacklinkProbability: 0.95, vectorCacheHintSizeKB: 2097152)
34+
35+
try entityBuilder.lastProperty(id: 2, uid: 16640)
36+
}
37+
}
38+
39+
extension CityAllProperties {
40+
/// Generated entity property information.
41+
///
42+
/// You may want to use this in queries to specify fetch conditions, for example:
43+
///
44+
/// box.query { CityAllProperties.id == myId }
45+
internal static var id: Property<CityAllProperties, Id, Id> { return Property<CityAllProperties, Id, Id>(propertyId: 1, isPrimaryKey: true) }
46+
/// Generated entity property information.
47+
///
48+
/// You may want to use this in queries to specify fetch conditions, for example:
49+
///
50+
/// box.query { CityAllProperties.coordinates.isNotNil() }
51+
internal static var coordinates: Property<CityAllProperties, HnswIndexPropertyType, Void> { return Property<CityAllProperties, HnswIndexPropertyType, Void>(propertyId: 2, isPrimaryKey: false) }
52+
53+
fileprivate func __setId(identifier: ObjectBox.Id) {
54+
self.id = Id(identifier)
55+
}
56+
}
57+
58+
extension ObjectBox.Property where E == CityAllProperties {
59+
/// Generated entity property information.
60+
///
61+
/// You may want to use this in queries to specify fetch conditions, for example:
62+
///
63+
/// box.query { .id == myId }
64+
65+
internal static var id: Property<CityAllProperties, Id, Id> { return Property<CityAllProperties, Id, Id>(propertyId: 1, isPrimaryKey: true) }
66+
67+
/// Generated entity property information.
68+
///
69+
/// You may want to use this in queries to specify fetch conditions, for example:
70+
///
71+
/// box.query { .coordinates.isNotNil() }
72+
73+
internal static var coordinates: Property<CityAllProperties, HnswIndexPropertyType, Void> { return Property<CityAllProperties, HnswIndexPropertyType, Void>(propertyId: 2, isPrimaryKey: false) }
74+
75+
}
76+
77+
78+
/// Generated service type to handle persisting and reading entity data. Exposed through `CityAllProperties.EntityBindingType`.
79+
internal class CityAllPropertiesBinding: ObjectBox.EntityBinding {
80+
internal typealias EntityType = CityAllProperties
81+
internal typealias IdType = Id
82+
83+
internal required init() {}
84+
85+
internal func generatorBindingVersion() -> Int { 1 }
86+
87+
internal func setEntityIdUnlessStruct(of entity: EntityType, to entityId: ObjectBox.Id) {
88+
entity.__setId(identifier: entityId)
89+
}
90+
91+
internal func entityId(of entity: EntityType) -> ObjectBox.Id {
92+
return entity.id.value
93+
}
94+
95+
internal func collect(fromEntity entity: EntityType, id: ObjectBox.Id,
96+
propertyCollector: ObjectBox.FlatBufferBuilder, store: ObjectBox.Store) throws {
97+
let propertyOffset_coordinates = propertyCollector.prepare(values: entity.coordinates)
98+
99+
propertyCollector.collect(id, at: 2 + 2 * 1)
100+
propertyCollector.collect(dataOffset: propertyOffset_coordinates, at: 2 + 2 * 2)
101+
}
102+
103+
internal func createEntity(entityReader: ObjectBox.FlatBufferReader, store: ObjectBox.Store) -> EntityType {
104+
let entity = CityAllProperties()
105+
106+
entity.id = entityReader.read(at: 2 + 2 * 1)
107+
entity.coordinates = entityReader.read(at: 2 + 2 * 2)
108+
109+
return entity
110+
}
111+
}
112+
113+
114+
115+
extension CityDefaults: ObjectBox.__EntityRelatable {
116+
internal typealias EntityType = CityDefaults
117+
118+
internal var _id: EntityId<CityDefaults> {
119+
return EntityId<CityDefaults>(self.id.value)
120+
}
121+
}
122+
123+
extension CityDefaults: ObjectBox.EntityInspectable {
124+
internal typealias EntityBindingType = CityDefaultsBinding
125+
126+
/// Generated metadata used by ObjectBox to persist the entity.
127+
internal static var entityInfo = ObjectBox.EntityInfo(name: "CityDefaults", id: 2)
128+
129+
internal static var entityBinding = EntityBindingType()
130+
131+
fileprivate static func buildEntity(modelBuilder: ObjectBox.ModelBuilder) throws {
132+
let entityBuilder = try modelBuilder.entityBuilder(for: CityDefaults.self, id: 2, uid: 21504)
133+
try entityBuilder.addProperty(name: "id", type: PropertyType.long, flags: [.id], id: 1, uid: 18688)
134+
try entityBuilder.addProperty(name: "coordinatesDefaults", type: PropertyType.floatVector, flags: [.indexed], id: 2, uid: 20736, indexId: 2, indexUid: 19712)
135+
.hnswParams(dimensions: 2, neighborsPerNode: nil, indexingSearchCount: nil, flags: nil, distanceType: nil, reparationBacklinkProbability: nil, vectorCacheHintSizeKB: nil)
136+
137+
try entityBuilder.lastProperty(id: 2, uid: 20736)
138+
}
139+
}
140+
141+
extension CityDefaults {
142+
/// Generated entity property information.
143+
///
144+
/// You may want to use this in queries to specify fetch conditions, for example:
145+
///
146+
/// box.query { CityDefaults.id == myId }
147+
internal static var id: Property<CityDefaults, Id, Id> { return Property<CityDefaults, Id, Id>(propertyId: 1, isPrimaryKey: true) }
148+
/// Generated entity property information.
149+
///
150+
/// You may want to use this in queries to specify fetch conditions, for example:
151+
///
152+
/// box.query { CityDefaults.coordinatesDefaults.isNotNil() }
153+
internal static var coordinatesDefaults: Property<CityDefaults, HnswIndexPropertyType, Void> { return Property<CityDefaults, HnswIndexPropertyType, Void>(propertyId: 2, isPrimaryKey: false) }
154+
155+
fileprivate func __setId(identifier: ObjectBox.Id) {
156+
self.id = Id(identifier)
157+
}
158+
}
159+
160+
extension ObjectBox.Property where E == CityDefaults {
161+
/// Generated entity property information.
162+
///
163+
/// You may want to use this in queries to specify fetch conditions, for example:
164+
///
165+
/// box.query { .id == myId }
166+
167+
internal static var id: Property<CityDefaults, Id, Id> { return Property<CityDefaults, Id, Id>(propertyId: 1, isPrimaryKey: true) }
168+
169+
/// Generated entity property information.
170+
///
171+
/// You may want to use this in queries to specify fetch conditions, for example:
172+
///
173+
/// box.query { .coordinatesDefaults.isNotNil() }
174+
175+
internal static var coordinatesDefaults: Property<CityDefaults, HnswIndexPropertyType, Void> { return Property<CityDefaults, HnswIndexPropertyType, Void>(propertyId: 2, isPrimaryKey: false) }
176+
177+
}
178+
179+
180+
/// Generated service type to handle persisting and reading entity data. Exposed through `CityDefaults.EntityBindingType`.
181+
internal class CityDefaultsBinding: ObjectBox.EntityBinding {
182+
internal typealias EntityType = CityDefaults
183+
internal typealias IdType = Id
184+
185+
internal required init() {}
186+
187+
internal func generatorBindingVersion() -> Int { 1 }
188+
189+
internal func setEntityIdUnlessStruct(of entity: EntityType, to entityId: ObjectBox.Id) {
190+
entity.__setId(identifier: entityId)
191+
}
192+
193+
internal func entityId(of entity: EntityType) -> ObjectBox.Id {
194+
return entity.id.value
195+
}
196+
197+
internal func collect(fromEntity entity: EntityType, id: ObjectBox.Id,
198+
propertyCollector: ObjectBox.FlatBufferBuilder, store: ObjectBox.Store) throws {
199+
let propertyOffset_coordinatesDefaults = propertyCollector.prepare(values: entity.coordinatesDefaults)
200+
201+
propertyCollector.collect(id, at: 2 + 2 * 1)
202+
propertyCollector.collect(dataOffset: propertyOffset_coordinatesDefaults, at: 2 + 2 * 2)
203+
}
204+
205+
internal func createEntity(entityReader: ObjectBox.FlatBufferReader, store: ObjectBox.Store) -> EntityType {
206+
let entity = CityDefaults()
207+
208+
entity.id = entityReader.read(at: 2 + 2 * 1)
209+
entity.coordinatesDefaults = entityReader.read(at: 2 + 2 * 2)
210+
211+
return entity
212+
}
213+
}
214+
215+
216+
/// Helper function that allows calling Enum(rawValue: value) with a nil value, which will return nil.
217+
fileprivate func optConstruct<T: RawRepresentable>(_ type: T.Type, rawValue: T.RawValue?) -> T? {
218+
guard let rawValue = rawValue else { return nil }
219+
return T(rawValue: rawValue)
220+
}
221+
222+
// MARK: - Store setup
223+
224+
fileprivate func cModel() throws -> OpaquePointer {
225+
let modelBuilder = try ObjectBox.ModelBuilder()
226+
try CityAllProperties.buildEntity(modelBuilder: modelBuilder)
227+
try CityDefaults.buildEntity(modelBuilder: modelBuilder)
228+
modelBuilder.lastEntity(id: 2, uid: 21504)
229+
modelBuilder.lastIndex(id: 2, uid: 19712)
230+
return modelBuilder.finish()
231+
}
232+
233+
extension ObjectBox.Store {
234+
/// A store with a fully configured model. Created by the code generator with your model's metadata in place.
235+
///
236+
/// # In-memory database
237+
/// To use a file-less in-memory database, instead of a directory path pass `memory:`
238+
/// together with an identifier string:
239+
/// ```swift
240+
/// let inMemoryStore = try Store(directoryPath: "memory:test-db")
241+
/// ```
242+
///
243+
/// - Parameters:
244+
/// - directoryPath: The directory path in which ObjectBox places its database files for this store,
245+
/// or to use an in-memory database `memory:<identifier>`.
246+
/// - maxDbSizeInKByte: Limit of on-disk space for the database files. Default is `1024 * 1024` (1 GiB).
247+
/// - fileMode: UNIX-style bit mask used for the database files; default is `0o644`.
248+
/// Note: directories become searchable if the "read" or "write" permission is set (e.g. 0640 becomes 0750).
249+
/// - maxReaders: The maximum number of readers.
250+
/// "Readers" are a finite resource for which we need to define a maximum number upfront.
251+
/// The default value is enough for most apps and usually you can ignore it completely.
252+
/// However, if you get the maxReadersExceeded error, you should verify your
253+
/// threading. For each thread, ObjectBox uses multiple readers. Their number (per thread) depends
254+
/// on number of types, relations, and usage patterns. Thus, if you are working with many threads
255+
/// (e.g. in a server-like scenario), it can make sense to increase the maximum number of readers.
256+
/// Note: The internal default is currently around 120. So when hitting this limit, try values around 200-500.
257+
/// - readOnly: Opens the database in read-only mode, i.e. not allowing write transactions.
258+
///
259+
/// - important: This initializer is created by the code generator. If you only see the internal `init(model:...)`
260+
/// initializer, trigger code generation by building your project.
261+
internal convenience init(directoryPath: String, maxDbSizeInKByte: UInt64 = 1024 * 1024,
262+
fileMode: UInt32 = 0o644, maxReaders: UInt32 = 0, readOnly: Bool = false) throws {
263+
try self.init(
264+
model: try cModel(),
265+
directory: directoryPath,
266+
maxDbSizeInKByte: maxDbSizeInKByte,
267+
fileMode: fileMode,
268+
maxReaders: maxReaders,
269+
readOnly: readOnly)
270+
}
271+
}
272+
273+
// swiftlint:enable all

0 commit comments

Comments
 (0)