我建立一个虚拟的iOS项目,以了解如何与斯威夫特核心数据执行验证。该项目的核心数据模型有一个名为Person
一个实体,它包含两个属性:firstName
和lastName
。该项目是基于雨燕但是,为了启动它,我使用的Objective-C定义NSManagedObject
子类:核心数据验证:从Objective-C的斯威夫特
Person.h
@interface Person : NSManagedObject
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;
@end
Person.m
@implementation Person
@dynamic firstName;
@dynamic lastName;
-(BOOL)validateFirstName:(id *)ioValue error:(NSError **)outError {
if (*ioValue == nil || [*ioValue isEqualToString: @""]) {
if (outError != NULL) {
NSString *errorStr = NSLocalizedStringFromTable(@"First name can't be empty", @"Person", @"validation: first name error");
NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorStr };
NSError *error = [[NSError alloc] initWithDomain:@"Domain" code: 101 userInfo: userInfoDict];
*outError = error;
}
return NO;
}
return YES;
}
@end
人桥接-Header.h
#import "Person.h"
在核心数据模型编辑器,我给自己定的实体类的数据模型督察里面所示:
class: Person
我第一次启动这个项目,我在创建Person
实例AppDelegate
application:didFinishLaunchingWithOptions:
方法用下面的代码:
if !NSUserDefaults.standardUserDefaults().boolForKey("isNotInitialLoad") {
let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: managedObjectContext!) as Person
person.firstName = "John"
person.lastName = "Doe"
var error: NSError?
if !managedObjectContext!.save(&error) {
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isNotInitialLoad")
NSUserDefaults.standardUserDefaults().synchronize()
}
该项目有一个UIViewController
用下面的代码:
class ViewController: UIViewController {
var managedObjectContext: NSManagedObjectContext!
var person: Person!
override func viewDidLoad() {
super.viewDidLoad()
//Fetch the Person object
var error: NSError?
let fetchRequest = NSFetchRequest(entityName: "Person")
let array = managedObjectContext.executeFetchRequest(fetchRequest, error:&error)
if array == nil {
println("Unresolved error \(error), \(error!.userInfo)")
abort()
}
person = array![0] as Person
}
@IBAction func changeFirstName(sender: AnyObject) {
//Generate a random firstName
let array = ["John", "Jimmy", "James", "Johnny", ""]
person.firstName = array[Int(arc4random_uniform(UInt32(5)))]
var error: NSError?
if !managedObjectContext.save(&error) {
println("Unresolved error \(error), \(error!.userInfo)")
return
}
//If success, display the new person's name
println("\(person.firstName)" + " " + "\(person.lastName)")
}
}
changeFirstName:
链接到UIButton
。因此,无论何时点击此按钮,都会随机生成一个新的String
并指定给person.firstName
。如果这个新的String
为空,则validateFirstName:error:
生成NSError
,并且保存操作失败。
这个伟大的工程,但是,为了有一个纯粹的斯威夫特项目,我已经决定删除Person.h
,Person.m
和Person-Bridging-Header.h
,并将其与一个单一的斯威夫特文件替换:
class Person: NSManagedObject {
@NSManaged var firstName: String
@NSManaged var lastName: String
func validateFirstName(ioValue: AnyObject, error: NSErrorPointer) -> Bool {
if ioValue as? String == "" {
if error != nil {
let myBundle = NSBundle(forClass: self.dynamicType)
let errorString = myBundle.localizedStringForKey("First name can't be empty", value: "validation: first name error", table: "Person")
let userInfo = NSMutableDictionary()
userInfo[NSLocalizedFailureReasonErrorKey] = errorString
userInfo[NSValidationObjectErrorKey] = self
var validationError = NSError(domain: "Domain", code: NSManagedObjectValidationError, userInfo: userInfo)
error.memory = validationError
}
return false
}
return true
}
}
在核心数据模型编辑器,我也改变了实体类的数据模型督察里面所示:
class: Person.Person //<Project name>.Person
现在的问题是,该项目的崩溃每当我打电话changeFirstName:
。最奇怪的是,如果我在validateFirstName:
内部放置一个断点,我可以看到这种方法从未被调用过。
我在做什么错?
有你桥接Objective-C和斯威夫特的一个原因。为什么不直接在Swift中完成呢?我自己在桥接两种语言时遇到了一些问题,所以通常尽我所能避免在这些情况下桥接 – AdamM
@AdamM:正如我理解的问题,它完全是“在Swift中完成”。 OP希望通过纯Swift实现来替代Objective-C代码。 –
啊,我做了一个代码示例的快速扫描,并在该部分上进行了扫描。我的错! – AdamM