模拟器和设备之间的不同 NSPredicate 行为
Different NSPredicate behaviour between Simulator and device
我知道我在这里做 'wrong' 事情,但它在所有情况下都有效,但在针对 iPad Air 或 Retina 的模拟器中除外 - 它在模拟器上适用于不同的设备或受支持的物理设备(6S 和 Retina 测试),但在模拟器中 运行 时在 iPad Air 或 Retina 上失败。
Realm 的最新版本 (0.97) 和 iOS (9.2) 和 XCode (7.2)。要重现该问题,这里有一个非常人为的示例...
import UIKit
import RealmSwift
class MyObject: Object {
dynamic var x: Int64 = 0
dynamic var y: Int64 = 0
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
print("Realm path: \(Realm.Configuration.defaultConfiguration.path!)")
let realm = try! Realm()
try! realm.write({
realm.deleteAll()
})
let myObject = MyObject()
myObject.x = 1
myObject.y = 2
try! realm.write({
realm.add(myObject)
})
let findX: Int64 = 1
let findY: Int64 = 2
let p1 = NSPredicate(format: "x == %d and y == %d", findX, findY)
let p2 = NSPredicate(format: "x == %d", findX)
let p3 = NSPredicate(format: "x == %lld and y == %lld", findX, findY)
print("Test 1: Fail on iPad retina in Simulator: \(realm.objects(MyObject).filter(p1).count)")
print("Test 2: Pass on all platforms: \(realm.objects(MyObject).filter(p2).count)")
print("Test 3: Pass on all platforms: \(realm.objects(MyObject).filter(p3).count)")
return true
}
}
当你 运行 这个时,所有这些测试 "should" 打印“1”(是的,测试 3 是最正确的)。但是,至少对我而言,第一个测试 returns "0" if 运行 在模拟器中并针对 iPad Air 或 Retina。他们在物理设备上工作。
我知道第三个测试应该如何编码,但是(1)为什么第二个测试可以工作; (2) 为什么这只发生在这些特定设备的模拟器中? (我会让你知道找出根本原因需要很长时间!)
您的问题是用于构造 NSPredicate
的格式字符串。您可以通过将代码简化为以下内容来看到这一点:
let findX: Int64 = 1
let findY: Int64 = 2
let p1 = NSPredicate(format: "x == %d and y == %d", findX, findY)
let p2 = NSPredicate(format: "x == %lld and y == %lld", findX, findY)
print(p1)
print(p2)
在 32 位模拟器中打印:
x == 1 AND y == 0
x == 1 AND y == 2
在 64 位模拟器中它打印:
x == 1 AND y == 2
x == 1 AND y == 2
这表明使用格式字符串 x == %d and y == %d
会导致谓词无法表达您想要的查询。发生这种情况的原因是 p1
的格式说明符与您传递的参数类型不匹配。特别是,%d
格式字符串希望您传递 Int
,但您传递的是 Int64
。通过使用 %lld
,它可以正确查找您传递的 64 位值。
你为什么不这样写谓词?
NSPredicate(format: "x == \(findX) and y == \(findY)")
使用这种语法,您不必担心变量的类型。
我知道我在这里做 'wrong' 事情,但它在所有情况下都有效,但在针对 iPad Air 或 Retina 的模拟器中除外 - 它在模拟器上适用于不同的设备或受支持的物理设备(6S 和 Retina 测试),但在模拟器中 运行 时在 iPad Air 或 Retina 上失败。
Realm 的最新版本 (0.97) 和 iOS (9.2) 和 XCode (7.2)。要重现该问题,这里有一个非常人为的示例...
import UIKit
import RealmSwift
class MyObject: Object {
dynamic var x: Int64 = 0
dynamic var y: Int64 = 0
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
print("Realm path: \(Realm.Configuration.defaultConfiguration.path!)")
let realm = try! Realm()
try! realm.write({
realm.deleteAll()
})
let myObject = MyObject()
myObject.x = 1
myObject.y = 2
try! realm.write({
realm.add(myObject)
})
let findX: Int64 = 1
let findY: Int64 = 2
let p1 = NSPredicate(format: "x == %d and y == %d", findX, findY)
let p2 = NSPredicate(format: "x == %d", findX)
let p3 = NSPredicate(format: "x == %lld and y == %lld", findX, findY)
print("Test 1: Fail on iPad retina in Simulator: \(realm.objects(MyObject).filter(p1).count)")
print("Test 2: Pass on all platforms: \(realm.objects(MyObject).filter(p2).count)")
print("Test 3: Pass on all platforms: \(realm.objects(MyObject).filter(p3).count)")
return true
}
}
当你 运行 这个时,所有这些测试 "should" 打印“1”(是的,测试 3 是最正确的)。但是,至少对我而言,第一个测试 returns "0" if 运行 在模拟器中并针对 iPad Air 或 Retina。他们在物理设备上工作。
我知道第三个测试应该如何编码,但是(1)为什么第二个测试可以工作; (2) 为什么这只发生在这些特定设备的模拟器中? (我会让你知道找出根本原因需要很长时间!)
您的问题是用于构造 NSPredicate
的格式字符串。您可以通过将代码简化为以下内容来看到这一点:
let findX: Int64 = 1
let findY: Int64 = 2
let p1 = NSPredicate(format: "x == %d and y == %d", findX, findY)
let p2 = NSPredicate(format: "x == %lld and y == %lld", findX, findY)
print(p1)
print(p2)
在 32 位模拟器中打印:
x == 1 AND y == 0
x == 1 AND y == 2
在 64 位模拟器中它打印:
x == 1 AND y == 2
x == 1 AND y == 2
这表明使用格式字符串 x == %d and y == %d
会导致谓词无法表达您想要的查询。发生这种情况的原因是 p1
的格式说明符与您传递的参数类型不匹配。特别是,%d
格式字符串希望您传递 Int
,但您传递的是 Int64
。通过使用 %lld
,它可以正确查找您传递的 64 位值。
你为什么不这样写谓词?
NSPredicate(format: "x == \(findX) and y == \(findY)")
使用这种语法,您不必担心变量的类型。