diff --git a/CHANGELOG.md b/CHANGELOG.md index 672ce1c4fc..47ab87c43e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception: ### New - [#706](https://github.com/groue/GRDB.swift/pull/706): Enhance SQLLiteral and SQL interpolation again +- [#712](https://github.com/groue/GRDB.swift/pull/712) by [@pakko972](https://github.com/pakko972): Automatic iOS memory management ### Breaking Change diff --git a/Documentation/DemoApps/GRDBDemoiOS/GRDBDemoiOS/AppDelegate.swift b/Documentation/DemoApps/GRDBDemoiOS/GRDBDemoiOS/AppDelegate.swift index 672c383c03..3df9947f3e 100644 --- a/Documentation/DemoApps/GRDBDemoiOS/GRDBDemoiOS/AppDelegate.swift +++ b/Documentation/DemoApps/GRDBDemoiOS/GRDBDemoiOS/AppDelegate.swift @@ -18,9 +18,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate { .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent("db.sqlite") dbQueue = try AppDatabase.openDatabase(atPath: databaseURL.path) - - // Be a nice iOS citizen, and don't consume too much memory - // See https://github.com/groue/GRDB.swift/blob/master/README.md#memory-management - dbQueue.setupMemoryManagement(in: application) } } diff --git a/GRDB/Core/DatabasePool.swift b/GRDB/Core/DatabasePool.swift index 50653f20f9..f4aa43b34e 100644 --- a/GRDB/Core/DatabasePool.swift +++ b/GRDB/Core/DatabasePool.swift @@ -24,10 +24,6 @@ public final class DatabasePool: DatabaseWriter { var databaseSnapshotCount = LockedBox(value: 0) - #if os(iOS) - private weak var application: UIApplication? - #endif - // MARK: - Database Information /// The path to the database. @@ -138,10 +134,16 @@ public final class DatabasePool: DatabaseWriter { } setupSuspension() + + // Be a nice iOS citizen, and don't consume too much memory + // See https://github.com/groue/GRDB.swift/#memory-management + #if os(iOS) + setupAutomaticMemoryManagement() + #endif } deinit { - // Undo job done in setupMemoryManagement() + // Undo job done in setupAutomaticMemoryManagement() // // https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11Error // Explicit unregistration is required before iOS 9 and OS X 10.11. @@ -194,8 +196,6 @@ extension DatabasePool { /// /// This method blocks the current thread until all database accesses /// are completed. - /// - /// See also setupMemoryManagement(application:) public func releaseMemory() { // Release writer memory writer.sync { $0.releaseMemory() } @@ -207,6 +207,12 @@ extension DatabasePool { #if os(iOS) + // swiftlint:disable:next line_length + @available(*, deprecated, message: "Memory management is now enabled by default. This deprecated method does nothing.") + public func setupMemoryManagement(in application: UIApplication) { + // No op. + } + /// Listens to UIApplicationDidEnterBackgroundNotification and /// UIApplicationDidReceiveMemoryWarningNotification in order to release /// as much memory as possible. @@ -214,8 +220,7 @@ extension DatabasePool { /// - param application: The UIApplication that will start a background /// task to let the database pool release its memory when the application /// enters background. - public func setupMemoryManagement(in application: UIApplication) { - self.application = application + private func setupAutomaticMemoryManagement() { let center = NotificationCenter.default center.addObserver( self, @@ -231,7 +236,7 @@ extension DatabasePool { @objc private func applicationDidEnterBackground(_ notification: NSNotification) { - guard let application = application else { + guard let application = notification.object as? UIApplication else { return } diff --git a/GRDB/Core/DatabaseQueue.swift b/GRDB/Core/DatabaseQueue.swift index 99c3928a8d..12dd4a1d93 100644 --- a/GRDB/Core/DatabaseQueue.swift +++ b/GRDB/Core/DatabaseQueue.swift @@ -7,9 +7,6 @@ import UIKit /// A DatabaseQueue serializes access to an SQLite database. public final class DatabaseQueue: DatabaseWriter { private var writer: SerializedDatabase - #if os(iOS) - private weak var application: UIApplication? - #endif // MARK: - Configuration @@ -43,6 +40,12 @@ public final class DatabaseQueue: DatabaseWriter { defaultLabel: "GRDB.DatabaseQueue") setupSuspension() + + // Be a nice iOS citizen, and don't consume too much memory + // See https://github.com/groue/GRDB.swift/#memory-management + #if os(iOS) + setupAutomaticMemoryManagement() + #endif } /// Opens an in-memory SQLite database. @@ -62,7 +65,7 @@ public final class DatabaseQueue: DatabaseWriter { } deinit { - // Undo job done in setupMemoryManagement() + // Undo job done in setupAutomaticMemoryManagement() // // https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11Error // Explicit unregistration is required before iOS 9 and OS X 10.11. @@ -77,13 +80,17 @@ extension DatabaseQueue { /// Free as much memory as possible. /// /// This method blocks the current thread until all database accesses are completed. - /// - /// See also setupMemoryManagement(application:) public func releaseMemory() { writer.sync { $0.releaseMemory() } } #if os(iOS) + // swiftlint:disable:next line_length + @available(*, deprecated, message: "Memory management is now enabled by default. This deprecated method does nothing.") + public func setupMemoryManagement(in application: UIApplication) { + // No op. + } + /// Listens to UIApplicationDidEnterBackgroundNotification and /// UIApplicationDidReceiveMemoryWarningNotification in order to release /// as much memory as possible. @@ -91,8 +98,7 @@ extension DatabaseQueue { /// - param application: The UIApplication that will start a background /// task to let the database queue release its memory when the application /// enters background. - public func setupMemoryManagement(in application: UIApplication) { - self.application = application + private func setupAutomaticMemoryManagement() { let center = NotificationCenter.default center.addObserver( self, @@ -108,7 +114,7 @@ extension DatabaseQueue { @objc private func applicationDidEnterBackground(_ notification: NSNotification) { - guard let application = application else { + guard let application = notification.object as? UIApplication else { return } diff --git a/Makefile b/Makefile index 011848f91d..7d30e94d38 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,14 @@ endif TEST_ACTIONS = clean build build-for-testing test-without-building # When adding support for an Xcode version, look for available devices with `instruments -s devices` -ifeq ($(XCODEVERSION),11.3) +ifeq ($(XCODEVERSION),11.4) + MAX_SWIFT_VERSION = 5.2 + MIN_SWIFT_VERSION = 4.2 + MAX_IOS_DESTINATION = "platform=iOS Simulator,name=iPhone 11,OS=13.4" + MIN_IOS_DESTINATION = "platform=iOS Simulator,name=iPhone 5,OS=10.3.1" + MAX_TVOS_DESTINATION = "platform=tvOS Simulator,name=Apple TV 4K,OS=13.4" + MIN_TVOS_DESTINATION = "platform=tvOS Simulator,name=Apple TV,OS=10.2" +else ifeq ($(XCODEVERSION),11.3) MAX_SWIFT_VERSION = 5.1 MIN_SWIFT_VERSION = 4.2 MAX_IOS_DESTINATION = "platform=iOS Simulator,name=iPhone 11,OS=13.3" diff --git a/README.md b/README.md index 768b36ece2..b32c4cb0f9 100644 --- a/README.md +++ b/README.md @@ -7147,12 +7147,7 @@ This method blocks the current thread until all current database accesses are co **The iOS operating system likes applications that do not consume much memory.** -[Database queues](#database-queues) and [pools](#database-pools) can call the `releaseMemory` method for you, when application receives memory warnings, and when application enters background: call the `setupMemoryManagement` method after creating the queue or pool instance: - -``` -let dbQueue = try DatabaseQueue(...) -dbQueue.setupMemoryManagement(in: UIApplication.shared) -``` +[Database queues](#database-queues) and [pools](#database-pools) automatically call the `releaseMemory` method when the application receives a memory warning, and when the application enters background. ## Data Protection