In de vorige zelfstudie hebt u geleerd hoe u algemene beperkingen in het gegevensmodel definieert. In deze zelfstudie laat ik u zien hoe u meer geavanceerde beperkingen in code kunt definiëren.
Download het project dat we in de vorige tutorial hebben gemaakt vanuit GitHub en open het in Xcode. Open AppDelegate.swift en update de implementatie van applicatie (_: didFinishLaunchingWithOptions)
zoals hieronder getoond.
toepassing func (toepassing: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool if let entity = NSEntityDescription.entityForName ("User", inManagedObjectContext: self.managedObjectContext) // Creëer beheerd object laat gebruiker = NSManagedObject ( entity: entity, insertIntoManagedObjectContext: self.managedObjectContext) // Beheer Beheerd Object user.setValue (44, forKey: "age") user.setValue ("Bart", forKey: "first") user.setValue ("Jacobs", forKey : "laatste") user.setValue ("[email protected]", forKey: "email") do try user.validateForInsert () catch let validationError = error as NSError print (validationError) return true
Als u de toepassing in de simulator of op een fysiek apparaat uitvoert, mogen er geen fouten worden gegenereerd. Met andere woorden, het beheerde object dat we maken applicatie (_: didFinishLaunchingWithOptions)
geeft validatie door voor invoegen in de permanente opslag van de toepassing.
NSManagedObject
Om de waarde van een attribuut in code te valideren, moeten we een NSManagedObject
subklasse. Kiezen Nieuw> Bestand ... van Xcode's het dossier menu en selecteer de Kerngegevens> NSManagedObject-subklasse sjabloon uit de lijst met sjablonen.
Selecteer het gegevensmodel van het project en controleer de entiteiten waarvoor u een wilt maken NSManagedObject
subklasse.
Controleren Gebruik scalaire eigenschappen voor primitieve gegevenstypen, vertel Xcode waar u de bestanden voor de subklassen wilt opslaan en klik op creëren.
Om de eigenschap van een entiteit te valideren, implementeert u een methode die de volgende indeling heeft, bevestigen
. De methode moet een werpmethode zijn. Als de validatie mislukt, wordt er een fout gegenereerd en wordt aan de Core Data gemeld dat de waarde van de property ongeldig is.
In het onderstaande voorbeeld heb ik een validatiemethode geïmplementeerd voor de eerste
eigendom van de Gebruiker entiteit. Voeg het volgende fragment toe aan User.swift.
import CoreData import Foundation class Gebruiker: NSManagedObject let errorDomain = "UserErrorDomain" enum UserErrorType: Int case InvalidFirst func validateFirst (value: AutoreleasingUnsafeMutablePointer) werpt var fout: NSError? = nul; als let first = value.memory as? Tekenreeks if first == "" let errorType = UserErrorType.InvalidFirst error = NSError (domein: errorDomain, code: errorType.rawValue, userInfo: [NSLocalizedDescriptionKey: "De voornaam mag niet leeg zijn."]) Else let errorType = UserErrorType.InvalidFirst error = NSError (domein: errorDomain, code: errorType.rawValue, userInfo: [NSLocalizedDescriptionKey: "De voornaam mag niet leeg zijn."]) if let error = error throw error
De validatiemethode accepteert één parameter van het type AutoreleasingUnsafeMutablePointer
. Wat is dat? Laat het type parameter je niet afschrikken. Zoals de naam van het type aangeeft, is de AutoreleasingUnsafeMutablePointer
structuur is een veranderlijke aanwijzer. Het verwijst naar een objectreferentie. We hebben toegang tot de waarde waarnaar de aanwijzer doorheen wijst geheugen
eigendom.
Zoals ik zojuist al zei, de validateFirst (_ :)
methode is gooien. Als de waarde die ons wordt gegeven niet geldig is, geven we een foutmelding. Door een fout te geven, brengen we Core Data op de hoogte dat het beheerde object ongeldig is.
In het volgende voorbeeld implementeer ik een validatiemethode voor de eigenschap e-mail van de Gebruiker
klasse. We maken gebruik van een reguliere expressie om de waarde van het te valideren e-mail
eigendom.
func validateEmail (waarde: AutoreleasingUnsafeMutablePointer) werpt var fout: NSError? = nul als e-mail = value.memory as? Tekenreeks let regex = "^. + @ ([A-Za-z0-9 -] + \\.) + [A-Za-z] 2 [A-Za-z] * $" let predicate = NSPredicate (formaat: "SELF MATCHES% @", regex) if! Predicate.evaluateWithObject (email) let errorType = UserErrorType.InvalidEmail error = NSError (domein: errorDomain, code: errorType.rawValue, userInfo: [NSLocalizedDescriptionKey: "De e-mail adres is ongeldig. "]) else let errorType = UserErrorType.InvalidEmail error = NSError (domein: errorDomain, code: errorType.rawValue, userInfo: [NSLocalizedDescriptionKey:" Het e-mailadres is ongeldig. "]) if let error = fout throw error
Hoewel u de waarde van de eigenschap in een validatiemethode kunt wijzigen, moedigt Apple dit sterk af. Als u de waarde die aan u wordt gegeven in een validatiemethode wijzigt, kan geheugenbeheer in de war raken. Met dat in gedachten wordt de datavalidatiestroom heel eenvoudig. Valideer de waarde van de eigenschap en voer een foutmelding als deze ongeldig is. Zo simpel is het.
Wijzig de waarden van de kenmerken in applicatie (_: didFinishLaunchingWithOptions)
en voer de applicatie uit in de simulator. Als de waarden die u hebt ingevoerd ongeldig zijn, moet er een fout worden gegenereerd.
De NSManagedObject
klasse stelt drie extra hooks-subklassen voor die kunnen worden overschreven voor gegevensvalidatie:
validateForInsert ()
validateForUpdate ()
validateForDelete ()
Deze methoden worden door Core Data op het beheerde object aangeroepen voordat de bijbehorende record in de permanente store wordt ingevoegd, bijgewerkt of verwijderd. Elk van deze methoden is gooien. Als er een fout wordt gegenereerd, wordt het bijbehorende invoegen, bijwerken of verwijderen afgebroken.
Hoewel het voordeel dat deze hooks hebben ten opzichte van de eigendomsvalidatiemethoden die we eerder hebben besproken niet meteen voor de hand ligt, zijn ze van onschatbare waarde in verschillende scenario's. Stel dat een gebruikersrecord niet kan worden verwijderd, zolang er maar een of meer bijbehorende notitie-records aan gekoppeld zijn. In dat geval kunt u de overschrijven validateForDelete ()
methode in de Gebruiker
klasse.
override func validateForDelete () gooit try super.validateForDelete () var error: NSError? = nul indien let notes = notes if notes.count> 0 let errorType = UserErrorType.OneOrMoreNotes error = NSError (domain: errorDomain, code: errorType.rawValue, userInfo: [NSLocalizedDescriptionKey: "Een gebruiker met notities kan niet worden verwijderd ..." ]) if let error = error throw error
Merk op dat we de override
sleutelwoord en haal het aan validateForDelete ()
implementatie van de superklasse bovenaan. Als de gebruikersrecord aan een of meer notitierecords is gekoppeld, wordt er een fout gegenereerd, waardoor wordt voorkomen dat de gebruikersrecord wordt verwijderd.
Gegevensvalidatie is een belangrijk aspect van elke toepassing die met gegevens werkt. Core Data biedt ontwikkelaars verschillende API's voor het implementeren van gegevensvalidatie. Maar u vraagt zich misschien af welke optie of opties u in uw toepassing kunt gebruiken.
Dit hangt af van uw voorkeur en de vereisten van het project. Voor een eenvoudig gegevensmodel met gemeenschappelijke beperkingen zijn de opties die het gegevensmodel biedt wellicht voldoende. Dat gezegd hebbende, sommige ontwikkelaars houden de validatielogica liever in de modellessen, dat wil zeggen in de NSManagedObject
subklassen. Het voordeel is dat de logica voor een bepaalde modelklasse zich op één plaats bevindt.
Voor complexere validatielogica, aangepaste validatiemethoden voor eigenschappen of de validateForInsert ()
, validateForUpdate ()
, en validateForDelete ()
haken worden aanbevolen. Ze voegen kracht en flexibiliteit toe aan de validatie van objecten en u hebt ook het voordeel dat de modellaag de validatielogica bevat.
Het is belangrijk om te begrijpen dat gegevensvalidatie uit twee aspecten bestaat, de logica voor gegevensvalidatie en wanneer gegevensvalidatie moet worden uitgevoerd. De modellaag is verantwoordelijk voor gegevensvalidatie. De controller is verantwoordelijk voor het bepalen wanneer gegevensvalidatie moet worden uitgevoerd, bijvoorbeeld wanneer de gebruiker op een knop tikt om een account te maken. Dit is een subtiel maar belangrijk verschil.
En last but not least: zet geen datavalidatielogica in de controllerlaag. Het zorgt voor onnodige blokkering van de controllers van uw project en leidt meestal tot codeduplicatie.
Core Data maakt gegevensvalidatie eenvoudig en duidelijk. Het datamodel helpt u met algemene beperkingen, maar het framework biedt ook verschillende meer geavanceerde API's voor aangepaste gegevensvalidatie.