Reputation: 1643
I am using FCModel in some new Swift code to persist my model data. In my schema management/migration code I get a compile time error when I perform a logical comparison on an Int. I cannot tell if there is a syntax or type error here, or if I have found a compiler bug.
Is this a valid logical operation? Is there a mistake I missed?
Error: AppDelegate.swift:53:30: Could not find an overload for '<' that accepts the supplied arguments
Relevant code:
var schemaVersion: Int = (settings["schemaVersion"] as String).toInt()!
FCModel.openDatabaseAtPath(databasePath, withSchemaBuilder: { database, schemaVersion in
database.crashOnErrors = true
database.traceExecution = true
database.beginTransaction()
// 'failedAt' closure removed for brevity
if schemaVersion < 1 { // ERROR HAPPENS HERE
if !database.executeUpdate("SQL STATEMENT HERE", withArgumentsInArray: nil)
{ failedAt(1) }
schemaVersion = 1
}
Update
openDatabaseAtPath()
is defined as:
func openDatabaseAtPath(path: String!, withSchemaBuilder schemaBuilder: ((FMDatabase!, CMutablePointer<CInt>) -> Void)!)
Update #2 With Sulthan's help below I think I've narrowed down where the issue is, but I have no idea why. Again, I think this may be a bug in Swift.
Updated code:
var schemaVersion: Int = 0
let database: FMDatabase = FMDatabase(path: databasePath)
FCModel.openDatabaseAtPath(databasePath, withSchemaBuilder: { (database, schemaVersion: CMutablePointer<CInt>) in
var x:Int = Int(schemaVersion.withUnsafePointer( { (unsafeSchemaVersion: UnsafePointer<CInt>) -> CInt in
return unsafeSchemaVersion.memory
}))
...
})
When I debug and use the REPL in Xcode something interesting happens. When execution is in the withSchemaBuilder
block database
is not nil, and matches the object created above. schemaVersion
is not a recognized identifier:
error: use of unresolved identifier 'schemaVersion'
schemaVersion
and:
$R0: FMDatabase! = {
Some = {
NSObject = {
isa = FMDatabase
}
_db =
_databasePath = @"/Users/brian/Library/Developer/CoreSimulator/Devices/25115FDE-0DA8-4F2B-B4E5-5A0600720772/data/Containers/Data/Application/579A64D7-6C6B-4690-B503-2CA5B4229D55/Documents/userData.sqlite"
_logsErrors = YES
_crashOnErrors = NO
_traceExecution = NO
_checkedOut = NO
_shouldCacheStatements = NO
_isExecutingStatement = NO
_inTransaction = NO
_maxBusyRetryTimeInterval = 2
_startBusyRetryTime = 0
_cachedStatements = nil
_openResultSets = 0 objects
_openFunctions = nil
_dateFormat = nil
}
}
Any thoughts?
Upvotes: 1
Views: 1689
Reputation: 130102
The declaration
var schemaVersion: Int = (settings["schemaVersion"] as String).toInt()!
doesn't have anything to do with your error since you are redefining schemaVersion
locally here:
... withSchemaBuilder: { database, schemaVersion in
The method is defined as
+ (void)openDatabaseAtPath:(NSString *)path
withSchemaBuilder:(void (^)(FMDatabase *db, int *schemaVersion))schemaBuilder;
so I assume the type of schemaVersion
in the block will be something like CMutablePointer <CInt>
Logically, you can't compare that to an Int
(1
) directly. If it's really an CMutablePointer<Int>
, you should use something like:
schemaVersion.withUnsafePointer { unsafeSchemaVersion in
if unsafeSchemaVersion.memory < 1
...
unsafeSchemaVersion.memory = 1
}
That's equivalent to the following in Obj-C:
if (*schemaVersion < 1) {
...
*schemaVersion = 1;
}
If you want to reference the variable you have defined outside the closure, you should rename it or rename the closure parameter.
Upvotes: 4