A student that completes this project shows that they can:
- understand and explain what Auto Layout is, and the problems it solves
- implement common layouts using constraints in Interface Builder
- implement common layouts using UIStackView
Q&A allows a user to ask a question, and also answer them. This project is meant to help you solidify Auto Layout skills.
Please watch the screen recording in order to know what the finished application should look like.
Please fork and clone this repository. Create a new Xcode project inside of the cloned repository. Note that these instructions will be intentionally vague in parts of the project you should have decent experience with.
First will be setting up the single model object and its controller for this project.
The model object should be a struct called Question. Create a new Swift file for it and give it the following properties:
- A
questionstring that represents the actual question the asker has - An
askerstring that will store the name of the person asking the question - An optional
answerstring that represents the answer to the question. This should be optional as there will not be an answer for a question as soon as it is created. - An optional
answererstring that is the name of the person answering the question
Create an initializer for this struct that gives default values of nil to the answer and answerer parameters.
Be conscious of which properties should be constants or variables.
Create a new Swift file called "QuestionController.swift" and in it, make a class called QuestionController.
Add the following to the QuestionController:
- An array of
Questionobjects calledquestionsthat will be used as the data source for the application. - A "Create" function that will initialize a
Questionobject and add it to thequestionsarray. - An "Update" function that takes in a
Question(that you want to update),answerstring, and ananswererstring to add to the question. - A "Delete" function that takes in a
Questionto be deleted, and removes it from thequestionsarray.
This application has three view controllers:
- One will show a list of
Questions that have been asked - One will allow a user to ask a question
- One will allow a user to answer a question.
All of these view controllers should be laid out and constrained yourself. Do not use of the options in the "Resolve Auto Layout Issues" button (the triangle TIE Fighter) such as "Add Missing Constraints" or "Reset to Suggested Constraints".
The first view controller the user will see in the application is the list of Questions.
- Drag out a
UITableViewControllerscene. - Embed it in a navigation controller, and set the navigation controller as the initial view controller.
- Give the table view contoller the title "Q&A".
- Add a bar button item, and give it the title "Ask Question"
The table view's cell is custom. It should look like this:
Using stack views, make your cell look similar to the screenshot above.
Hints:
- The cell has five labels, not three.
- The text style of the labels that say "Question", "Asked By", and the one on the last line should be set to medium.
- Put the labels that are next to each other horizontally in their own stack view. Then you may put those stack views in a "super" stack view that holds those two stack views and the label on the bottom
- Using the pin menu, constrain the "super" stack view to the cell at about 8 points in each direction.
Create Cocoa Touch Subclasses for both the table view controller scene, and the custom cell. Be sure to set their class in the Identity Inspector.
Add outlets to the custom cell.
In this view controller, you are not allowed to use stack views. This view controller will allow the user to ask a question. It will be shown when the user taps on the "Ask Question" bar button item in the table view controller.
- Add a
UIViewControllerscene to the storyboard. - Add a text field to the scene that will allow the user to enter their name. Constrain it to be 16 points from the top of the safe area, and 0 points away from the leading and trailing margins.
- Add a text view that is 8 points under the bottom of the text field, and 0 points away from the leading and trailing margins. Also, constrain it to be one third of the height of the view controller's view.
- Add a navigation item, then a bar button item. The bar button item's title should be "Submit Question".
- Create a Cocoa Touch Subclass for this view controller. Set the view controller scene's class in the Identity Inspector.
- Add outlets from the text field and text view, and an action from the "Submit Question" bar button item. Leave the action blank for now.
- Back on the table view controller scene, create a show segue from the "Ask Question" bar button item to the
AskQuestionViewControllerscene that you just finished setting up. Give the segue an identifier.
In this view controller, you must use a stack view to help you lay out the scene. This view controller will be shown when tapping on a question cell to allow the user to answer a question, and view the answer to a previously answered question.
- Add a
UIViewControllerscene to the storyboard. - Add two labels to the scene. One will display the question to be answered, while the other will show the name of the person who asked the question.
- Add a text field allowing the user to enter the name of the person answering the question
- Add a text view allowing the user to answer the question.
- Add all four UI elements to a stack view. Constrain the stack view to the top of the view controller. Make set its height to be half of the view controller's view's height.
- Add a navigation item, then a bar button item. The bar button item's title should be "Submit Answer".
- Back on the table view controller scene, create a show segue from the custom cell to the
AnswerViewControllerscene that you just finished setting up. Give the segue an identifier.
- If you haven't already, make outlets from the labels in the storyboard to the custom cell class.
- Add a variable
questionwhose type is an optionalQuestion. - Create a private method
updateViews(), that takes the values in thequestionvariable and sets the text of the labels accordingly. Make sure you unwrap thequestion. - Add a
didSetproperty observer to thequestionvariable, and callupdateViews()inside of it.
- Clean up this file. You will only need the required
UITableViewDataSourcemethods, thecommit editingStyleandprepareForSeguemethods. - Add a constant called
questionControllerand set its value to a new instance ofQuestionController. - Using this
questionController, implement thenumberOfRowInSectionfunction. - Implement the
cellForRowAtmethod. Remember that you are using a custom cell. This function should pass an instance ofQuestionto the cell. - Implement the
commit editingStylemethod to allow for deleting question cells. (remember to delete aQuestionbefore you delete the cell) - Add the
viewWillAppearmethod. Reload the table view in it so that when a new question or answer gets added, the table view will reflect these changes.
- Add a
questionController: QuestionController?variable. - In the action of the bar button item:
- Get the text from each text field, and make sure they aren't
nilor an empty string (""). - Call the model controller's
createQuestionmethod - Have the navigation controller pop to the previous view controller.
- Get the text from each text field, and make sure they aren't
- Add a
questionController: QuestionController?, and aquestion: Question?variable. - In the action of the bar button item:
- Get the text from the text field and text view, and make sure they aren't
nilor an empty string (""). - Call the model controller's "Update" method to add an answer and answerer to the question that you pass in.
- Have the navigation controller pop to the previous view controller.
- Get the text from the text field and text view, and make sure they aren't
- Create an
updateViews()method. As this view controller is only accessible upon tapping a question cell, grab the values from thequestionvariable and place them in the corresponding labels and text field or text view. Be aware that tapping a cell that doesn't have an answer and answerer should still display the question and the name of the person who asked it. If it does have an answer and answerer, those values should also be placed in the text field and text view accordinly.
Finally, go back to the QuestionsTableViewController class. Now that the destination view controllers that this view controller segues to are implemented, fill out the prepareForSegue method.
- If the segue is going to the
AskQuestionViewController, you need to pass thequestionController. - If the segue is going to the
AnswerQuestionViewController, you need to pass thequestionController, and also thequestionthat the user tapped on and wishes to view and/or add an answer to.
- Re-constrain the custom cell without using stack views at all.
- Modify the custom cell so that it will resize automatically to show the answer (if there is one) in its entirety.

