ios - Core Data validation: from Objective-C to Swift -
ios - Core Data validation: from Objective-C to Swift -
i'm building dummy ios project in order understand how implement validation in core info swift. core info model of project has 1 entity called person
contains 2 attributes: firstname
, lastname
. project based on swift but, in order start it, i'm using objective-c define nsmanagedobject
subclass:
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 empty", @"person", @"validation: first name error"); nsdictionary *userinfodict = @{ nslocalizeddescriptionkey : errorstr }; nserror *error = [[nserror alloc] initwithdomain:@"domain" code: 101 userinfo: userinfodict]; *outerror = error; } homecoming no; } homecoming yes; } @end
person-bridging-header.h
#import "person.h"
in core info model editor, i've set entity class within info model inspector indicated:
class: person
the first time launch project, create instance of person
in appdelegate
application:didfinishlaunchingwithoptions:
method next code:
if !nsuserdefaults.standarduserdefaults().boolforkey("isnotinitialload") { allow person = nsentitydescription.insertnewobjectforentityforname("person", inmanagedobjectcontext: managedobjectcontext!) 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() }
the project has 1 uiviewcontroller
next code:
class viewcontroller: uiviewcontroller { var managedobjectcontext: nsmanagedobjectcontext! var person: person! override func viewdidload() { super.viewdidload() //fetch person object var error: nserror? allow fetchrequest = nsfetchrequest(entityname: "person") allow array = managedobjectcontext.executefetchrequest(fetchrequest, error:&error) if array == nil { println("unresolved error \(error), \(error!.userinfo)") abort() } person = array![0] person } @ibaction func changefirstname(sender: anyobject) { //generate random firstname allow 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)") homecoming } //if success, display new person's name println("\(person.firstname)" + " " + "\(person.lastname)") } }
changefirstname:
linked uibutton
. therefore, whenever click on button, new string
randomly generated , assigned person.firstname
. if new string
empty, validatefirstname:error:
generates nserror
, save operation fails.
this works great but, in order have pure swift project, i've decided delete person.h
, person.m
, person-bridging-header.h
, replace them single swift file:
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 { allow mybundle = nsbundle(forclass: self.dynamictype) allow errorstring = mybundle.localizedstringforkey("first name can't empty", value: "validation: first name error", table: "person") allow userinfo = nsmutabledictionary() userinfo[nslocalizedfailurereasonerrorkey] = errorstring userinfo[nsvalidationobjecterrorkey] = self var validationerror = nserror(domain: "domain", code: nsmanagedobjectvalidationerror, userinfo: userinfo) error.memory = validationerror } homecoming false } homecoming true } }
in core info model editor, i've changed entity class within info model inspector indicated:
class: person.person //<project name>.person
the problem project crashes whenever phone call changefirstname:
. weirdest thing if set breakpoint within validatefirstname:
, can see method never called.
what doing wrong?
i little bit guessing here, (id *)iovalue
parameter mapped swift as
iovalue: autoreleasingunsafemutablepointer<anyobject?>
therefore swift variant should like
func validatefirstname(iovalue: autoreleasingunsafemutablepointer<anyobject?>, error: nserrorpointer) -> bool { if allow firstname = iovalue.memory as? string { if firstname == "" { // firstname empty string // ... } } else { // firstname nil (or not string) // ... } homecoming true }
update swift 2:
func validatefirstname(iovalue: autoreleasingunsafemutablepointer<anyobject?>) throws { guard allow firstname = iovalue.memory as? string firstname != "" else { // firstname nil, empty, or not string allow errorstring = "first name can't empty" allow userdict = [ nslocalizeddescriptionkey: errorstring ] throw nserror(domain: "domain", code: nsmanagedobjectvalidationerror, userinfo: userdict) } // firstname non-empty string }
as @santaclaus correctly noticed, validation function must throw error if validation fails.
ios objective-c validation core-data swift
Comments
Post a Comment