From e0894c9313bb3c9206845214ef98f8dfbd9dd8bd Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Fri, 12 Apr 2019 05:16:31 -0500 Subject: [PATCH] Move IosFiles implementation to Kotlin; setup tests for ios target --- core/build.gradle | 33 +++++++ core/settings.gradle | 2 + .../org/isoron/uhabits/backend/Backend.kt | 65 +++++++------ .../org/isoron/platform/io/FilesTest.kt | 15 ++- .../kotlin/org/isoron/platform/io/IosFiles.kt | 59 ++++++++++++ .../kotlin/org/isoron/DependencyResolver.kt | 28 +++++- .../kotlin/org/isoron/IosAsyncTests.kt | 42 +++++++++ .../Frontend/MainScreenController.swift | 4 +- ios/Application/Platform/IosCanvas.swift | 44 ++++----- ios/Application/Platform/IosFiles.swift | 83 ----------------- ios/Tests/Platform/IosCanvasTest.swift | 1 - ios/Tests/Platform/IosDatabaseTest.swift | 92 +++++++++---------- ios/Tests/Platform/IosFilesTest.swift | 45 --------- ios/uhabits.xcodeproj/project.pbxproj | 8 -- 14 files changed, 271 insertions(+), 250 deletions(-) create mode 100644 core/src/iosMain/kotlin/org/isoron/platform/io/IosFiles.kt create mode 100644 core/src/iosTest/kotlin/org/isoron/IosAsyncTests.kt delete mode 100644 ios/Application/Platform/IosFiles.swift delete mode 100644 ios/Tests/Platform/IosFilesTest.swift diff --git a/core/build.gradle b/core/build.gradle index 96deb0782..230f9a8c4 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -91,5 +91,38 @@ kotlin { implementation kotlin('test-js') } } + + iosMain { + dependencies { + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.2.0-alpha-2' + } + } + + iosTest { + dependencies { + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.2.0-alpha-2' + } + } + } + + task iosTestCopyResources(type: Copy) { + dependsOn 'linkTestIos' + from 'assets/test/' + from 'assets/main/' + into 'build/bin/ios/testDebugExecutable' + } + + task iosTest { + dependsOn 'linkTestIos', 'iosTestCopyResources' + group = JavaBasePlugin.VERIFICATION_GROUP + description = "Runs tests on iOS simulator" + + doLast { + def emulatorName = "iPhone 8 Plus" + def binary = kotlin.targets.ios.compilations.test.getBinary('EXECUTABLE', 'DEBUG') + exec { + commandLine 'xcrun', 'simctl', 'spawn', emulatorName, binary.absolutePath + } + } } } \ No newline at end of file diff --git a/core/settings.gradle b/core/settings.gradle index 20ee303a3..80e2d76a1 100644 --- a/core/settings.gradle +++ b/core/settings.gradle @@ -7,3 +7,5 @@ pluginManagement { } } } + +enableFeaturePreview("GRADLE_METADATA") \ No newline at end of file diff --git a/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt b/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt index 5b6142162..a14c66b38 100644 --- a/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt +++ b/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt @@ -26,34 +26,31 @@ import org.isoron.uhabits.components.* import org.isoron.uhabits.i18n.* import org.isoron.uhabits.models.* -//class Backend(databaseName: String, -// databaseOpener: DatabaseOpener, -// fileOpener: FileOpener, -// localeHelper: LocaleHelper, -// val log: Log, -// val taskRunner: TaskRunner) { -// -// val database: Database -// -// val habitsRepository: HabitRepository -// -// val checkmarkRepository: CheckmarkRepository -// -// val habits = mutableMapOf() -// -// val checkmarks = mutableMapOf() -// -// val scores = mutableMapOf() +class Backend(databaseName: String, + databaseOpener: DatabaseOpener, + fileOpener: FileOpener, + localeHelper: LocaleHelper, + private val log: Log, + private val taskRunner: TaskRunner) { + +// private val database: Database // -// val mainScreenDataSource: MainScreenDataSource +// private val habitsRepository: HabitRepository // -// val strings = localeHelper.getStringsForCurrentLocale() +// private val checkmarkRepository: CheckmarkRepository // -// val preferences: Preferences +// private val habits = mutableMapOf() // -// var theme: Theme = LightTheme() +// private val checkmarks = mutableMapOf() // -// init { +// private val scores = mutableMapOf() + + val mainScreenDataSource: MainScreenDataSource? = null + val strings = localeHelper.getStringsForCurrentLocale() + val preferences: Preferences? = null + var theme: Theme = LightTheme() + + init { // val dbFile = fileOpener.openUserFile(databaseName) // if (!dbFile.exists()) { // val templateFile = fileOpener.openResourceFile("databases/template.db") @@ -78,9 +75,9 @@ import org.isoron.uhabits.models.* // checkmarks, // scores, // taskRunner) -// } -// -// fun createHabit(habit: Habit) { + } + + fun createHabit(habit: Habit) { // val id = habitsRepository.nextId() // habit.id = id // habit.position = habits.size @@ -88,20 +85,20 @@ import org.isoron.uhabits.models.* // checkmarks[habit] = CheckmarkList(habit.frequency, habit.type) // habitsRepository.insert(habit) // mainScreenDataSource.requestData() -// } -// -// fun deleteHabit(id: Int) { + } + + fun deleteHabit(id: Int) { // habits[id]?.let { habit -> // habitsRepository.delete(habit) // habits.remove(id) // mainScreenDataSource.requestData() // } -// } -// -// fun updateHabit(modified: Habit) { + } + + fun updateHabit(modified: Habit) { // habits[modified.id]?.let { existing -> // modified.position = existing.position // habitsRepository.update(modified) // } -// } -//} + } +} diff --git a/core/src/commonTest/kotlin/org/isoron/platform/io/FilesTest.kt b/core/src/commonTest/kotlin/org/isoron/platform/io/FilesTest.kt index 1bf7ab2bf..4958ade2c 100644 --- a/core/src/commonTest/kotlin/org/isoron/platform/io/FilesTest.kt +++ b/core/src/commonTest/kotlin/org/isoron/platform/io/FilesTest.kt @@ -26,11 +26,16 @@ class FilesTest() : BaseTest() { suspend fun testLines() { val fileOpener = resolver.getFileOpener() - assertFalse(fileOpener.openUserFile("non-existing.txt").exists()) - assertFalse(fileOpener.openResourceFile("non-existing.txt").exists()) + assertFalse(fileOpener.openUserFile("non-existing-usr.txt").exists(), + "non-existing-usr.txt shouldn't exist") + + assertFalse(fileOpener.openResourceFile("non-existing-res.txt").exists(), + "non-existing-res.txt shouldn't exist") val hello = fileOpener.openResourceFile("hello.txt") + assertTrue(hello.exists(), "hello.txt should exist") var lines = hello.lines() + assertEquals(2, lines.size) assertEquals("Hello World!", lines[0]) assertEquals("This is a resource.", lines[1]) @@ -40,13 +45,13 @@ class FilesTest() : BaseTest() { assertEquals("Hello World!", lines[0]) assertEquals("This is a resource.", lines[1]) - assertTrue(helloCopy.exists()) + assertTrue(helloCopy.exists(), "helloCopy should exist") helloCopy.delete() - assertFalse(helloCopy.exists()) + assertFalse(helloCopy.exists(), "helloCopy shouldn't exist") val migration = fileOpener.openResourceFile("migrations/012.sql") - assertTrue(migration.exists()) + assertTrue(migration.exists(), "migrations/012.sql should exist") lines = migration.lines() assertEquals("delete from Score", lines[0]) } diff --git a/core/src/iosMain/kotlin/org/isoron/platform/io/IosFiles.kt b/core/src/iosMain/kotlin/org/isoron/platform/io/IosFiles.kt new file mode 100644 index 000000000..c87c7b87b --- /dev/null +++ b/core/src/iosMain/kotlin/org/isoron/platform/io/IosFiles.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016-2019 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +@file:Suppress("UNCHECKED_CAST") + +package org.isoron.platform.io + +import platform.Foundation.* + +class IosFileOpener : FileOpener { + override fun openResourceFile(path: String): ResourceFile { + val resPath = NSBundle.mainBundle.resourcePath!! + return IosFile("$resPath/$path") + } + + override fun openUserFile(path: String): UserFile { + val manager = NSFileManager.defaultManager + val basePath = manager.URLsForDirectory(NSDocumentDirectory, + NSUserDomainMask) as List + val filePath = basePath.first().URLByAppendingPathComponent(path)!!.path!! + return IosFile(filePath) + } +} + +class IosFile(val path: String) : UserFile, ResourceFile { + override suspend fun delete() { + NSFileManager.defaultManager.removeItemAtPath(path, null) + } + + override suspend fun exists(): Boolean { + return NSFileManager.defaultManager.fileExistsAtPath(path) + } + + override suspend fun lines(): List { + if (!exists()) throw Exception("File not found: $path") + val contents = NSString.stringWithContentsOfFile(path) + return contents.toString().lines() + } + + override suspend fun copyTo(dest: UserFile) { + NSFileManager.defaultManager.copyItemAtPath(path, (dest as IosFile).path, null) + } +} \ No newline at end of file diff --git a/core/src/iosTest/kotlin/org/isoron/DependencyResolver.kt b/core/src/iosTest/kotlin/org/isoron/DependencyResolver.kt index 93b74aff5..0568c1d9c 100644 --- a/core/src/iosTest/kotlin/org/isoron/DependencyResolver.kt +++ b/core/src/iosTest/kotlin/org/isoron/DependencyResolver.kt @@ -17,14 +17,34 @@ * with this program. If not, see . */ +@file:Suppress("UNCHECKED_CAST") + package org.isoron import org.isoron.platform.gui.* import org.isoron.platform.io.* +import platform.CoreGraphics.* +import platform.Foundation.* +import platform.UIKit.* actual class DependencyResolver { - actual fun getFileOpener(): FileOpener = TODO() - actual fun getDatabase(): Database = TODO() - actual fun createCanvas(width: Int, height: Int): Canvas = TODO() - actual fun exportCanvas(canvas: Canvas, filename: String): Unit = TODO() + actual suspend fun getFileOpener(): FileOpener { + return IosFileOpener() + } + + actual suspend fun getDatabase(): Database = TODO() + + actual fun createCanvas(width: Int, height: Int): Canvas { + UIGraphicsBeginImageContext(CGSizeMake(width=500.0, height=600.0)) + return IosCanvas() + } + + actual fun exportCanvas(canvas: Canvas, filename: String): Unit { + val image = UIGraphicsGetImageFromCurrentImageContext()!! + val manager = NSFileManager.defaultManager + val paths = manager.URLsForDirectory(NSDocumentDirectory, NSUserDomainMask) as List + val filePath = paths.first().URLByAppendingPathComponent("IosCanvasTest.png")!!.path!! + val data = UIImagePNGRepresentation(image)!! + data.writeToFile(filePath, false) + } } \ No newline at end of file diff --git a/core/src/iosTest/kotlin/org/isoron/IosAsyncTests.kt b/core/src/iosTest/kotlin/org/isoron/IosAsyncTests.kt new file mode 100644 index 000000000..aec40d079 --- /dev/null +++ b/core/src/iosTest/kotlin/org/isoron/IosAsyncTests.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2016-2019 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron + +import kotlinx.coroutines.* +import org.isoron.platform.io.* +import org.isoron.uhabits.models.* +import kotlin.test.* + +class IosAsyncTests { + @Test + fun testFiles() = runBlocking { FilesTest().testLines() } + +// @Test +// fun testDatabase() = runBlocking { DatabaseTest().testUsage() } +// +// @Test +// fun testCheckmarkRepository() = runBlocking { CheckmarkRepositoryTest().testCRUD() } +// +// @Test +// fun testHabitRepository() = runBlocking { HabitRepositoryTest().testCRUD() } +// +// @Test +// fun testPreferencesRepository() = runBlocking { PreferencesRepositoryTest().testUsage() } +} \ No newline at end of file diff --git a/ios/Application/Frontend/MainScreenController.swift b/ios/Application/Frontend/MainScreenController.swift index dddfa9c2c..2d2b52b3e 100644 --- a/ios/Application/Frontend/MainScreenController.swift +++ b/ios/Application/Frontend/MainScreenController.swift @@ -109,9 +109,9 @@ class MainScreenController: UITableViewController, MainScreenDataSourceListener init(withBackend backend:Backend) { self.backend = backend self.strings = backend.strings - self.dataSource = backend.mainScreenDataSource + self.dataSource = backend.mainScreenDataSource! self.theme = backend.theme - self.preferences = backend.preferences + self.preferences = backend.preferences! super.init(nibName: nil, bundle: nil) self.dataSource.observable.addListener(listener: self) self.dataSource.requestData() diff --git a/ios/Application/Platform/IosCanvas.swift b/ios/Application/Platform/IosCanvas.swift index e68241851..fd605918d 100644 --- a/ios/Application/Platform/IosCanvas.swift +++ b/ios/Application/Platform/IosCanvas.swift @@ -42,28 +42,6 @@ class ComponentView : UIView { } class IosCanvas : NSObject, Canvas { - func fillArc(centerX: Double, centerY: Double, radius: Double, startAngle: Double, swipeAngle: Double) { - let center = CGPoint(x: CGFloat(centerX), y: CGFloat(centerY)) - let a1 = startAngle / 180 * .pi * (-1) - let a2 = a1 - swipeAngle / 180 * .pi - self.ctx.beginPath() - self.ctx.move(to: center) - self.ctx.addArc(center: center, - radius: CGFloat(radius), - startAngle: CGFloat(a1), - endAngle: CGFloat(a2), - clockwise: swipeAngle >= 0) - self.ctx.closePath() - self.ctx.fillPath() - } - - func fillCircle(centerX: Double, centerY: Double, radius: Double) { - self.ctx.fillEllipse(in: CGRect(x: CGFloat(centerX - radius), - y: CGFloat(centerY - radius), - width: CGFloat(radius * 2), - height: CGFloat(radius * 2))) - } - var bounds: CGRect var ctx: CGContext @@ -157,4 +135,26 @@ class IosCanvas : NSObject, Canvas { func setTextAlign(align: TextAlign) { self.textAlign = align } + + func fillArc(centerX: Double, centerY: Double, radius: Double, startAngle: Double, swipeAngle: Double) { + let center = CGPoint(x: CGFloat(centerX), y: CGFloat(centerY)) + let a1 = startAngle / 180 * .pi * (-1) + let a2 = a1 - swipeAngle / 180 * .pi + self.ctx.beginPath() + self.ctx.move(to: center) + self.ctx.addArc(center: center, + radius: CGFloat(radius), + startAngle: CGFloat(a1), + endAngle: CGFloat(a2), + clockwise: swipeAngle >= 0) + self.ctx.closePath() + self.ctx.fillPath() + } + + func fillCircle(centerX: Double, centerY: Double, radius: Double) { + self.ctx.fillEllipse(in: CGRect(x: CGFloat(centerX - radius), + y: CGFloat(centerY - radius), + width: CGFloat(radius * 2), + height: CGFloat(radius * 2))) + } } diff --git a/ios/Application/Platform/IosFiles.swift b/ios/Application/Platform/IosFiles.swift deleted file mode 100644 index 223b47b38..000000000 --- a/ios/Application/Platform/IosFiles.swift +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016-2019 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -import Foundation - -class IosResourceFile : NSObject, ResourceFile { - - var path: String - var fileManager = FileManager.default - - init(forPath path: String) { - self.path = path - } - - func readLines() -> [String] { - do { - let contents = try String(contentsOfFile: self.path, encoding: .utf8) - return contents.components(separatedBy: CharacterSet.newlines) - } catch { - return ["ERROR"] - } - } - - func doCopyTo(dest: UserFile) { - try! fileManager.copyItem(atPath: self.path, toPath: (dest as! IosUserFile).path) - } -} - -class IosUserFile : NSObject, UserFile { - - var path: String - - init(forPath path: String) { - self.path = path - } - - func delete() { - do { - try FileManager.default.removeItem(atPath: path) - } catch { - - } - } - - func exists() -> Bool { - return FileManager.default.fileExists(atPath: path) - } -} - -class IosFileOpener : NSObject, FileOpener { - func openResourceFile(filename: String) -> ResourceFile { - let path = "\(Bundle.main.resourcePath!)/\(filename)" - return IosResourceFile(forPath: path) - } - - func openUserFile(filename: String) -> UserFile { - do { - let root = try FileManager.default.url(for: .documentDirectory, - in: .userDomainMask, - appropriateFor: nil, - create: false).path - return IosUserFile(forPath: "\(root)/\(filename)") - } catch { - return IosUserFile(forPath: "invalid") - } - } -} diff --git a/ios/Tests/Platform/IosCanvasTest.swift b/ios/Tests/Platform/IosCanvasTest.swift index 5fc790655..2ae212914 100644 --- a/ios/Tests/Platform/IosCanvasTest.swift +++ b/ios/Tests/Platform/IosCanvasTest.swift @@ -64,6 +64,5 @@ class IosCanvasTest : XCTestCase { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let filePath = paths.first?.appendingPathComponent("IosCanvasTest.png") try! image.pngData()!.write(to: filePath!, options: .atomic) - UIGraphicsEndImageContext() } } diff --git a/ios/Tests/Platform/IosDatabaseTest.swift b/ios/Tests/Platform/IosDatabaseTest.swift index eeac2df9e..e1ed7de15 100644 --- a/ios/Tests/Platform/IosDatabaseTest.swift +++ b/ios/Tests/Platform/IosDatabaseTest.swift @@ -22,52 +22,52 @@ import XCTest class IosDatabaseTest: XCTestCase { func testUsage() { - let databaseOpener = IosDatabaseOpener(withLog: StandardLog()) - let fileOpener = IosFileOpener() - - let dbFile = fileOpener.openUserFile(filename: "test.sqlite3") - if dbFile.exists() { + let databaseOpener = IosDatabaseOpener(withLog: StandardLog()) + let fileOpener = IosFileOpener() + + let dbFile = fileOpener.openUserFile(path: "test.sqlite3") + if dbFile.exists() { + dbFile.delete() + } + let db = databaseOpener.open(file: dbFile) + + var stmt = db.prepareStatement(sql: "drop table if exists demo") + stmt.step() + stmt.finalize() + + stmt = db.prepareStatement(sql: "begin") + stmt.step() + stmt.finalize() + + stmt = db.prepareStatement(sql: "create table if not exists demo(key int, value text)") + stmt.step() + stmt.finalize() + + stmt = db.prepareStatement(sql: "insert into demo(key, value) values (?, ?)") + stmt.bindInt(index: 0, value: 42) + stmt.bindText(index: 1, value: "Hello World") + stmt.step() + stmt.finalize() + + stmt = db.prepareStatement(sql: "select * from demo where key > ?") + stmt.bindInt(index: 0, value: 10) + var result = stmt.step() + XCTAssertEqual(result, StepResult.row) + XCTAssertEqual(stmt.getInt(index: 0), 42) + XCTAssertEqual(stmt.getText(index: 1), "Hello World") + result = stmt.step() + XCTAssertEqual(result, StepResult.done) + stmt.finalize() + + stmt = db.prepareStatement(sql: "drop table demo") + stmt.step() + stmt.finalize() + + stmt = db.prepareStatement(sql: "commit") + stmt.step() + stmt.finalize() + + db.close() dbFile.delete() - } - let db = databaseOpener.open(file: dbFile) - - var stmt = db.prepareStatement(sql: "drop table if exists demo") - stmt.step() - stmt.finalize() - - stmt = db.prepareStatement(sql: "begin") - stmt.step() - stmt.finalize() - - stmt = db.prepareStatement(sql: "create table if not exists demo(key int, value text)") - stmt.step() - stmt.finalize() - - stmt = db.prepareStatement(sql: "insert into demo(key, value) values (?, ?)") - stmt.bindInt(index: 0, value: 42) - stmt.bindText(index: 1, value: "Hello World") - stmt.step() - stmt.finalize() - - stmt = db.prepareStatement(sql: "select * from demo where key > ?") - stmt.bindInt(index: 0, value: 10) - var result = stmt.step() - XCTAssertEqual(result, StepResult.row) - XCTAssertEqual(stmt.getInt(index: 0), 42) - XCTAssertEqual(stmt.getText(index: 1), "Hello World") - result = stmt.step() - XCTAssertEqual(result, StepResult.done) - stmt.finalize() - - stmt = db.prepareStatement(sql: "drop table demo") - stmt.step() - stmt.finalize() - - stmt = db.prepareStatement(sql: "commit") - stmt.step() - stmt.finalize() - - db.close() - dbFile.delete() } } diff --git a/ios/Tests/Platform/IosFilesTest.swift b/ios/Tests/Platform/IosFilesTest.swift deleted file mode 100644 index a7a19eb16..000000000 --- a/ios/Tests/Platform/IosFilesTest.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016-2019 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -import XCTest -@testable import uhabits - -class IosFilesTest: XCTestCase { - func testResourceFiles() { - let fileOpener = IosFileOpener() - let file = fileOpener.openResourceFile(filename: "migrations/010.sql") - let lines = file.readLines() - XCTAssertEqual(lines[0], "delete from Score") - } - - func testUserFiles() throws { - let fm = FileManager.default - let root = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path - let path = "\(root)/test.txt" - print(path) - fm.createFile(atPath: path, contents: "Hello world\nThis is line 2".data(using: .utf8), attributes: nil) - - let fileOpener = IosFileOpener() - let file = fileOpener.openUserFile(filename: "test.txt") - XCTAssertTrue(file.exists()) - - file.delete() - XCTAssertFalse(file.exists()) - } -} diff --git a/ios/uhabits.xcodeproj/project.pbxproj b/ios/uhabits.xcodeproj/project.pbxproj index 58dc83d05..535ff2f47 100644 --- a/ios/uhabits.xcodeproj/project.pbxproj +++ b/ios/uhabits.xcodeproj/project.pbxproj @@ -12,10 +12,8 @@ 00A5B42822009F590024E00C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A5B42722009F590024E00C /* AppDelegate.swift */; }; 00A5B42A22009F590024E00C /* MainScreenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A5B42922009F590024E00C /* MainScreenController.swift */; }; 00A5B42F22009F5A0024E00C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 00A5B42E22009F5A0024E00C /* Assets.xcassets */; }; - 00C0C6A52246537A003D8AF0 /* IosFilesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A122465365003D8AF0 /* IosFilesTest.swift */; }; 00C0C6A62246537E003D8AF0 /* IosDatabaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A222465365003D8AF0 /* IosDatabaseTest.swift */; }; 00C0C6A8224654A2003D8AF0 /* IosDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A7224654A2003D8AF0 /* IosDatabase.swift */; }; - 00C0C6AA224654F4003D8AF0 /* IosFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C0C6A9224654F4003D8AF0 /* IosFiles.swift */; }; 00C0C6BD22465F65003D8AF0 /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = 00C0C6BA22465F65003D8AF0 /* fonts */; }; 00C0C6BE22465F65003D8AF0 /* databases in Resources */ = {isa = PBXBuildFile; fileRef = 00C0C6BB22465F65003D8AF0 /* databases */; }; 00C0C6BF22465F65003D8AF0 /* migrations in Resources */ = {isa = PBXBuildFile; fileRef = 00C0C6BC22465F65003D8AF0 /* migrations */; }; @@ -66,10 +64,8 @@ 00A5B43322009F5A0024E00C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00A5B43822009F5A0024E00C /* uhabitsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = uhabitsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00A5B43E22009F5A0024E00C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00C0C6A122465365003D8AF0 /* IosFilesTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IosFilesTest.swift; sourceTree = ""; }; 00C0C6A222465365003D8AF0 /* IosDatabaseTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IosDatabaseTest.swift; sourceTree = ""; }; 00C0C6A7224654A2003D8AF0 /* IosDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IosDatabase.swift; sourceTree = ""; }; - 00C0C6A9224654F4003D8AF0 /* IosFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IosFiles.swift; sourceTree = ""; }; 00C0C6AE224655D8003D8AF0 /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 00C0C6BA22465F65003D8AF0 /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = fonts; sourceTree = ""; }; 00C0C6BB22465F65003D8AF0 /* databases */ = {isa = PBXFileReference; lastKnownFileType = folder; path = databases; sourceTree = ""; }; @@ -185,7 +181,6 @@ 00C0C6A7224654A2003D8AF0 /* IosDatabase.swift */, 00C0C6DA2247E6B0003D8AF0 /* IosDates.swift */, 00C0C6CD2246EFB3003D8AF0 /* IosExtensions.swift */, - 00C0C6A9224654F4003D8AF0 /* IosFiles.swift */, 006EFE4D2252EA2B008464E0 /* IosLocale.swift */, ); path = Platform; @@ -197,7 +192,6 @@ 00C0C6D82247DC13003D8AF0 /* IosCanvasTest.swift */, 00C0C6A222465365003D8AF0 /* IosDatabaseTest.swift */, 00C0C6DC2247E6C4003D8AF0 /* IosDatesTest.swift */, - 00C0C6A122465365003D8AF0 /* IosFilesTest.swift */, ); path = Platform; sourceTree = ""; @@ -328,7 +322,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00C0C6AA224654F4003D8AF0 /* IosFiles.swift in Sources */, 00C0C6D122470705003D8AF0 /* IosCanvas.swift in Sources */, 00C0C6CE2246EFB3003D8AF0 /* IosExtensions.swift in Sources */, 00C0C6E0224A3602003D8AF0 /* DetailScreenController.swift in Sources */, @@ -347,7 +340,6 @@ buildActionMask = 2147483647; files = ( 00C0C6DD2247E6C4003D8AF0 /* IosDatesTest.swift in Sources */, - 00C0C6A52246537A003D8AF0 /* IosFilesTest.swift in Sources */, 00C0C6D92247DC13003D8AF0 /* IosCanvasTest.swift in Sources */, 00C0C6A62246537E003D8AF0 /* IosDatabaseTest.swift in Sources */, );