繁体   English   中英

核心数据验证:从Objective-C到Swift

[英]Core Data validation: from Objective-C to Swift

我正在构建一个虚拟iOS项目,以了解如何使用Swift在Core Data中实现验证。 项目的核心数据模型有一个名为Person实体,它包含两个属性: firstNamelastName 该项目基于Swift,但为了启动它,我使用Objective-C来定义NSManagedObject子类:

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

第一次启动项目时,我在AppDelegate application:didFinishLaunchingWithOptions:创建了一个Person实例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并且保存操作失败。

这很好但是,为了有一个纯粹的Swift项目,我决定删除Person.hPerson.mPerson-Bridging-Header.h并用一个Swift文件替换它们:

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:时项目都会崩溃changeFirstName: 最奇怪的是,如果我在validateFirstName:放置一个断点,我可以看到永远不会调用此方法。

我究竟做错了什么?

我在这里有点猜测,但是(id *)ioValue参数映射到Swift as

ioValue: AutoreleasingUnsafeMutablePointer<AnyObject?>

因此,Swift变体应该看起来像

func validateFirstName(ioValue: AutoreleasingUnsafeMutablePointer<AnyObject?>, error: NSErrorPointer) -> Bool {
    if let firstName = ioValue.memory as? String {
        if firstName == "" {
            // firstName is empty string
            // ...
        }
    } else {
        // firstName is nil (or not a String)
        // ...
    }
    return true
}

Swift 2更新

func validateFirstName(ioValue: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
    guard let firstName = ioValue.memory as? String where firstName != ""  else {
        // firstName is nil, empty, or not a String
        let errorString = "First name can't be empty"
        let userDict = [ NSLocalizedDescriptionKey: errorString ]
        throw NSError(domain: "domain", code: NSManagedObjectValidationError, userInfo: userDict)
    }
    // firstName is a non-empty string
}

正如@SantaClaus正确注意到的那样,验证函数现在必须在验证失败时抛出错误。

Apple的核心数据编程指南现在已针对Swift 3进行了更新。以下是管理对象生命周期>对象验证页面中的示例代码( memory已重命名为pointee ):

func validateAge(value: AutoreleasingUnsafeMutablePointer<AnyObject?>!) throws {
    if value == nil {
        return
    }

    let valueNumber = value!.pointee as! NSNumber
    if valueNumber.floatValue > 0.0 {
        return
    }
    let errorStr = NSLocalizedString("Age must be greater than zero", tableName: "Employee", comment: "validation: zero age error")
    let userInfoDict = [NSLocalizedDescriptionKey: errorStr]
    let error = NSError(domain: "EMPLOYEE_ERROR_DOMAIN", code: 1123, userInfo: userInfoDict)
    throw error
}

编辑:这个例子不太正确。 为了使它工作,我已经将AutoreleasingUnsafeMutablePointer<AnyObject?>更改为一个未包装的可选value?.pointeevalue?.pointeevalue.pointee

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM