Today, you will use the AddBookViewController view and its class file to implement these tasks:
- Validate required input fields
- Insert a managed object in the database
- Load a photo in the image view
Create a New Branch
Before you get started in implementing above tasks in the tutorial’s iOS project; I want you to use the Source Control ➤ Create New Branch… menu to create a new branch from the “master” branch. Give it the name “insert-managed-object”.
Validate Required Input Fields
Enter this validation code in the AddViewController.swift file’s doneButtonTapped() function. It dismiss the keyboard and validate required input fields; which are the Book Title text field and the Book Author text field.
@IBAction func doneButtonTapped(sender: AnyObject) { // Dismiss the keyboard bookTitle.resignFirstResponder() authorName.resignFirstResponder() photoUrl.resignFirstResponder() // Make sure required text fields aren't empty if bookTitle.text.isEmpty || authorName.text.isEmpty { textView.text = "Both the Book Title and the Author Name is requred" } else { // Display a success message in the text view textView.text = "Book saved!" } }
Output
Insert a Managed Object in The Database
Here is the code to add in the doneButtonTapped() function’s else block. The code create a managed object variable, set its properties with data you entered in the Add Book view’s text fields, then insert the managed object in the app’s database file.
} else { // Insert a managed object in the database insertManagedObject() }
Here is the code to implement the insertManagedObject() function called in the doneButtonTapped() function. Read the comments to get a sense of what the code does.
// This function insert a book object (managed object) in the database then dismiss the view func insertManagedObject() { // Put the Book entity in the context let entityDescripition = NSEntityDescription.entityForName("Book", inManagedObjectContext: context) // Create a managed object from the Book entity and put it in the context let bookObject = Book(entity: entityDescripition!, insertIntoManagedObjectContext: context) // Set the managed object's properties bookObject.bookTitle = bookTitle.text bookObject.authorName = authorName.text bookObject.photoUrl = photoUrl.text var savingError: NSError? // Insert the managed object in the database file if !context.save(&savingError) { // The context couldn't insert the managed object in the database, display an error message in the textView textView.text = "Failed to save the context with error = \(savingError?.localizedDescription)" } else { // The context successfully inserted the managed object in the database, display a success message in the text view textView.text = "Book saved!" // Clear out the text fields bookTitle.text = nil authorName.text = nil photoUrl.text = nil } }
If you were to run the app after entering above code in the file, the complier will issue several fatal errors. To prevent that from happening, you have to import the CoreData module in the AddMovieViewController class. Create a constant called context and initialize it with the AppDelegate’s managedObjectContext variable.
import UIKit import CoreData class AddViewController: UIViewController { ... let context = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext! }
Now, test the code you entered in the doneButtonTapped() function by using the Add Book View to add this book in the app’s database file. You will see output shown in the image below, when you click the Done button.
Book Title: One for The Money |
Author Name: Janet Evanovich |
Photo Url: https://unputdownables.files.wordpress.com/2010/09/7213750.jpg |
Output
When you finish entering a managed object (book object) in the app’s database file, it should appear in the Books View’s table view right? Well as of now, that’s not happening. Obviously, you have to add code in the BooksViewController.swift file to fetch all managed objects you inserted in the app’s database file, and display them in the Books View’s table view cells. You’ll do that in next week’s workshop.
In the mean time, I want you to use the Add Book View to add the book, “One for The Money” in the app’s database again. Next, add these ones in the database as well:
Book Title: Go Set a Watchman |
Author Name: Harper Lee |
Photo Url: http://img1.imagesbn.com/p/9780062409850_p0_v5_s260x420.JPG |
Book Title: Odd Hours: An Odd Thomas Novel |
Author Name: Dean Koontz |
Photo Url: http://img2.imagesbn.com/p/9780553591705_p0_v1_s114x166.JPG |
Load a Photo in The Image View
When you enter an url in the Add Book View’s Photo Url text field, then click away from the field. The app should load the url’s photo in the image view. If the url you entered in the Photo Url text field isn’t a valid url; the app should load a local photo in the image view.
Code you’ll enter in the AddBookViewController.swift file assume you’ve already inserted the local photo in the app’s bundle. So download this image put it in the project bundle by dragging-and-dropping it in the project’s Images.xcassets folder.
Here’s the code to load a photo in the image view. Implement it in the AddBookViewController.swift file.
func getImage(urlString: String) -> UIImage { var imageObject = UIImage(named: "noimage")! // Strip spaces from either end of the String let trimedUrlString = urlString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) let imgUrl: NSURL = NSURL(string: trimedUrlString)! // Make sure the urlString contain a valid url if imgUrl.scheme != nil && imgUrl.host != nil { // Download an NSData representation of the image at the remote url let imgData = NSData(contentsOfURL: imgUrl) if imgData != nil { // Put the downloaded image in the variable imageObject = UIImage(data: imgData!)! } } // Return the local/downloaded image return imageObject }
Call the getImage() function in the touchesBegan() function like this:
// This function is fired when you touch the view's background override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { // Dismiss the keyboard bookTitle.resignFirstResponder() authorName.resignFirstResponder() photoUrl.resignFirstResponder() // Load an image in the imageView control imageView.image = getImage(photoUrl.text) }
Output
Run the app in the iPhone 5s Simulator, then copy and past this url in the Photo Url text field, then click the view’s background:
http://img2.imagesbn.com/p/9780553591705_p0_v1_s114x166.JPG
The app download the url’s photo from the remote server and loaded it in the image view.
If you entered nothing in the Photo Url text field or entered an invalid url in the field, then click the view’s background. The app will load the image you copied to the app’s bundle, in the image view instead. Here’s what it will look like on the iPhone 5s Simulator’s screen:
That’s pretty cool, right? If you agree, leave a comment. The last thing I want you to do is return to Xcode and use the Source Control menu to “Commit…” changes you made to the project in the git repository.
You’ve reached the end of the first workshop in the Swift Core Data From Scratch tutorial. I will bring you workshop 2 next week. In the mean time, comments are welcomed! 🙂