Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions P10-Keyboard-Input/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ How does the app know if we want to edit/create or view a new note? It doesn't!
For example, if a note has no title or content, it stands to reason that you would want to edit it by default, as an empty note isn't very informative. Let's add an `edit` variable flag and have it set when a `didSet` is called on our note.

> [action]
> Open *NoteDisplayViewController*and add a new `edit` boolean variable to this class. Set it to a default value of `false`.
> Open *NoteDisplayViewController* and add a new `edit` boolean variable to this class. Set it to a default value of `false`.
>
Now modify `func viewWillAppear` as follows:
>
Expand All @@ -31,8 +31,8 @@ Now modify `func viewWillAppear` as follows:
>
}
>
> - 1: We are renaming the 'Return' button on the keyboard to 'Next'. For our app it makes more sense from a user experience perspective that you most likely want to move on to the next input field after entering the title. We can handle this in the *UITextFieldDelegate* soon.
> - 2: Set the `titleTextField` delegate. We will implement the delegate as a class extension as we did with our Table View Delegate.
1. We are renaming the 'Return' button on the keyboard to 'Next'. For our app it makes more sense from a user experience perspective that you most likely want to move on to the next input field after entering the title. We can handle this in the *UITextFieldDelegate* soon.
2. Set the `titleTextField` delegate. We will implement the delegate as a class extension as we did with our Table View Delegate.

Time to set our edit flag status based upon the note content.

Expand All @@ -53,8 +53,8 @@ Time to set our edit flag status based upon the note content.
}
}
>
> - 1: Here we're checking the length of our note content strings. If there is no content, we'll assume 'Edit' mode and set the first responder. This will set focus to the titleTextField and prompt the user with the keyboard ready for title input.
> If we are not in 'Edit' mode, then the note will be displayed as is and no keyboard will pop up until the user initiates this action for themselves.
1. Here we're checking the length of our note content strings. If there is no content, we'll assume 'Edit' mode and set the first responder. This will set focus to the titleTextField and prompt the user with the keyboard ready for title input.
If we are not in 'Edit' mode, then the note will be displayed as is and no keyboard will pop up until the user initiates this action for themselves.

OK! We still need to add a delegate for our textField so it knows if it should move on to the next field.

Expand All @@ -67,7 +67,8 @@ OK! We still need to add a delegate for our textField so it knows if it should m
>
func textFieldShouldReturn(textField: UITextField) -> Bool {
>
if (textField == titleTextField) { //1
if (textField == titleTextField) {
//1
contentTextView.returnKeyType = .Done
contentTextView.becomeFirstResponder()
}
Expand All @@ -76,8 +77,7 @@ OK! We still need to add a delegate for our textField so it knows if it should m
}
}
>

> - 1: When the 'Return' button is pressed, or in our case 'Next', this delegate will be called. We need to check that the `textField` in question is our `titleTextField`. If so, then
1. When the 'Return' button is pressed, or in our case 'Next', this delegate will be called. We need to check that the `textField` in question is our `titleTextField`. If so, then
we want to move the user input focus onto editing the `contentTextView`. This makes the user experience nicer.

![image](simulator_keyboard.png)
Expand All @@ -94,7 +94,11 @@ Let's set the scene for some constraint magic.
## Constraint Connection

> [action]
> Add the following variables to your *NoteDisplayViewController*:
Add the following import statement to the top of the `NoteDisplayViewController.swift` file (outside of the class declaration):
>
import ConvenienceKit
>
> Then add the following variables to your *NoteDisplayViewController* class:
>
@IBOutlet weak var deleteButton: UIBarButtonItem!
@IBOutlet weak var toolbarBottomSpace: NSLayoutConstraint!
Expand Down Expand Up @@ -162,7 +166,7 @@ Run your app. It's looking much nicer!

## The Trash Can

However, one last niggle: the trash can is still enabled when we're creating a new note. This doesn't make a whole lot of sense - when writing a new note, we'll either cancel (so the note won't be created at all) or click save. The trash can has nothing to do with either of those actions. Let's disable it.
However, one last thing: the trash can is still enabled when we're creating a new note. This doesn't make a whole lot of sense - when writing a new note, we'll either cancel (so the note won't be created at all) or click save. The trash can has nothing to do with either of those actions. Let's disable it.

> [action]
> Add the following code to `func viewWillAppear`:
Expand Down
21 changes: 13 additions & 8 deletions P11-Search/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Let's add this outlet and possible search states.
class NotesViewController: UIViewController {
>
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!
>
enum State {
case DefaultMode
Expand Down Expand Up @@ -123,19 +122,25 @@ We are setting the default state. However nothing will happen unless we use the
case .DefaultMode:
do {
let realm = try Realm()
notes = realm.objects(Note).sorted("modificationDate", ascending: false) //1
self.navigationController!.setNavigationBarHidden(false, animated: true) //2
searchBar.resignFirstResponder() // 3
// 1
notes = realm.objects(Note).sorted("modificationDate", ascending: false)
// 2
self.navigationController!.setNavigationBarHidden(false, animated: true)
// 3
searchBar.resignFirstResponder()
searchBar.text = ""
searchBar.showsCancelButton = false
} catch {
print("realm error")
}
case .SearchMode:
let searchText = searchBar?.text ?? ""
searchBar.setShowsCancelButton(true, animated: true) //4
notes = searchNotes(searchText) //5
self.navigationController!.setNavigationBarHidden(true, animated: true) //6
// 4
searchBar.setShowsCancelButton(true, animated: true)
// 5
notes = searchNotes(searchText)
// 6
self.navigationController!.setNavigationBarHidden(true, animated: true)
}
}
}
Expand All @@ -147,7 +152,7 @@ We are setting the default state. However nothing will happen unless we use the
> 3. Remove keyboard popup.
> 4. Animate in a cancel button beside the search bar. This just looks nice (UI Polish).
> 5. Perform a search on any text entered into the search bar.
> 6. This makes the search bar take p rominence in our view. By hiding the navigation bar the user is focused on search. (UI Polish)
> 6. This makes the search bar take prominence in our view. By hiding the navigation bar the user is focused on search. (UI Polish)
>

Run the App
Expand Down
9 changes: 5 additions & 4 deletions P6-Introduction-Table-Views/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Let's take a sneak peek of **MakeSchoolNotes** a little bit further on in the tu
![image](app_preview_1.png)

Table views are on of the many components provided by Apple's UIKit framework. The UIKit framework is a collection
of components that makes it easier for developers to build apps. If you haven't built iOS apps before you should watch this lecture
of components that makes it easier for developers to build apps. If you haven't built iOS apps before you should watch this lecture
that introduces the main concepts of UIKit before moving on with this tutorial:

<iframe width="560" height="315" src="https://www.youtube.com/embed/vgl9X047-2s" frameborder="0" allowfullscreen></iframe>

You can download the slides for this lecture [here](https://s3.amazonaws.com/mgwu-misc/SA2015/LectureSlides/UIKitIntro.pdf).
You can download the slides for this lecture [here](https://s3.amazonaws.com/mgwu-misc/SA2015/LectureSlides/UIKitIntro.pdf).

## The UITableView

Expand Down Expand Up @@ -92,7 +92,8 @@ You can extend support to your existing class using an *Extension*. Extensions c
extension NotesViewController {
>
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("NoteCell", forIndexPath: indexPath) as! NoteTableViewCell //1
//1
let cell = tableView.dequeueReusableCellWithIdentifier("NoteCell", forIndexPath: indexPath) as! NoteTableViewCell
>
cell.textLabel?.text = "Hello World"
>
Expand Down Expand Up @@ -170,7 +171,7 @@ Hopefully yours will look something like this, ideally with a bit more swag than
Great! You now have your labels set up, but you will want to be able to access them programmatically, so you will need to create an *IBOutlet* to connect your labels from Interface Builder to code.

> [action]
1. Open *NotesViewController* and `Main.storyboard` in the *Assistant Editor* view (refer back to the *Connecting Objects* section of the last tutorial if you're having trouble with this).
1. Open *NoteTableViewCell* and `Main.storyboard` in the *Assistant Editor* view (refer back to the *Connecting Objects* section of the last tutorial if you're having trouble with this).
2. Add the following outlets to the *NoteTableViewCell* class.
>
class NoteTableViewCell: UITableViewCell {
Expand Down
14 changes: 7 additions & 7 deletions P8-New-Note-Controller/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Those look like a good start. See if you can implement the following by yoursel
> [action]
>
> 1. Add a `Navigation Item` from the Object library to the *NewNoteViewController* in Interface Builder
> 2. Change the name of the *NewNoteViewController* in Interface Builder "Add New Note"
> 2. Change the name of the *NewNoteViewController* in Interface Builder to "Add New Note"
> 3. Add a *Cancel* `Bar Button Item` on the left hand side of the bar.
> 4. Add a *Save* `Bar Button Item` on the right hand side of the bar.

Expand Down Expand Up @@ -178,9 +178,9 @@ First of all, we are going to create a new note in our *NewNoteViewController*.

> [action]
> Open `NewNoteViewController.swift`.
> 1. Add a variable to the class to hold our new Note.
> 2. Uncomment the `prepareForSegue` function and set up a dummy Note with a little bit of content.
> Hint: Look at `viewDidLoad` in *NotesViewController* to see this process.
1. Add a variable to the class to hold our new Note.
2. Uncomment the `prepareForSegue` function and set up a dummy Note with a little bit of content.
Hint: Look at `viewDidLoad` in *NotesViewController* to see this process.

Here's a possible solution:

Expand Down Expand Up @@ -210,7 +210,7 @@ We've already seen that we are alerted through our `unwindSegue` when the *Add*
> [action]
> Open `NotesViewController.swift` and locate the `unwindToSegue` function. Modify your code as follows:
>
if let identifier = segue.identifier {
if let identifier = segue.identifier {
>
do {
let realm = try Realm()
Expand All @@ -231,7 +231,7 @@ if let identifier = segue.identifier {
>
// 2
notes = realm.objects(Note).sorted("modificationDate", ascending: false)
} catch {
} catch {
print("handle error")
}
}
Expand Down Expand Up @@ -280,7 +280,7 @@ We touched upon the table view delegate in the *Introduction To Table Views* cha
> [action]
> Open `NotesViewController.swift` and add the following code to the end of your file:
>
extension NotesViewController {
extension NotesViewController {
>
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//1
Expand Down
4 changes: 2 additions & 2 deletions P9-Note-Display-Controller/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Great, let's add support for our new trash can segue.
> Open `NotesViewController.swift` and add the following to the `switch` statement in your `unwindToSegue` function.
>
case "Delete":
realm.write() {
try realm.write() {
realm.delete(self.selectedNote!)
}
>
Expand Down Expand Up @@ -129,7 +129,7 @@ Time to add some outlets.
>
override func viewDidLoad() {

Now let's get these new display objects to display our existing note information. We need to add a variable to hold our Note.
Don't forget to create connections from these outlets to the Text Field and Text View in your storyboard! Now let's get these new display objects to display our existing note information. We need to add a variable to hold our Note.

> [action]
> Add the following note declaration after the `contentTextView` declaration.
Expand Down