iOS University

Remote-iOS-Fall-2022 (@ Observer access)

Personal Member ID#: 19941

Submit your group milestone by Self-paced (1 group member only) in the Group Project page.

Milestone requirements can also be found in the Group Project page.
πŸ“¬ Submit your app assignment by Self-paced using the Submit button on the Assignment tab
⚠️ Don't forget to fill out the session survey at the end of each class session: Session Survey Link

Unit 5 - Building Instagram Part 1

Overview

In this unit, you'll be building the first part of an instagram-like app that allows users to take and post pics. You'll setup and utilize a custom backend database using Parse to store and retrieve user posts.

Here's What You'll be Building

Assignment 5 - Instagram Part 1

Build the first part of an instagram-like app that allows users to take and post pics. More details in the Assignment Tab


Lab 5 - Yelpy Chat

Implement chat feature into our Yelpy app to talk with other people using parse server backend! More details in the Lab Tab


Lesson Slides

  1. πŸ“• Unit Slides

Session Recordings

Group Milestone Requirements (10pts)

A complete Group Milestone must have the following items. Submit your Group Milestone at the top of this page.

  1. Creation of GitHub Organization and Group Project Repo (2pt)
  2. Using the Unit 5 Group Milestone README Template as a starting point, update your Group Project README.md with the following items. (Example README for reference)
    1. App Overview: Description and evaluation (Mobile, Story, Market, Habit & Scope) (3pts)
    2. App spec: user stories, screens & navigation flows (3pts)
  3. Updated group info in the Course Portal: Group Name + App Description. (2pt)
Make sure to complete all activities listed in this session in order to have a complete Group Milestone to submit by Self-paced.

Group Activity - Product Spec

In this activity, you'll meet with your group to decide on the app idea you want to move forward with. Once your app idea is finalized you'll get started on designing your product spec. This is about working with your team to define "What does our app do?" -- Screens, Navigation Flows and User Stories are all different aspects of describing how your app behaves and defining the things your app does from a user perspective. Everything from, logging in to posting new content can be represented as user stories.

Activity Agenda (60 min)

  1. Meet your group!
  2. Finalize your app idea
  3. App evaluation attributes (Mobile, Story, Market, Habit & Scope)
  4. Design a product spec
  5. Create a GitHub Organization and project repo
  6. Update group GitHub repo README to include product spec
  7. Update your app info in the course portal

1. Meet Your Group

If you're meeting with your group for the first time, take a few minutes for everyone to introduce themselves and get to know each other.

2. Finalize your app idea

The group formation postings included an app idea which was the app idea your group had most in common. This app idea is only a suggestion to get the conversation started, your group can use that app idea or come up with an entirely new one. However, keep in mind that you only have this week and the next for the app design phase so you'll want to finalize an app idea ASAP in order to move forward with the rest of the design steps and activities.

Come up with your top 3 app ideas and as a group, finalize the app you think would be the most fun to design and build, keeping in mind the framework for evaluating apps introduced in the App Brainstorming Guide.

3. Evaluate your app

  1. Create a HackMD document for your group to collaborate on. Share the link with each group member.
  2. Copy/paste the contents of the Unit 8 Group Milestone README Template into your group's shared HackMD document. Update each section as you work through each activity in this session. In the end, you'll copy/paste this doc into your Group Project's README.
  3. Add the name of your and and write up a general description of your app.
  4. Apply the Evaluating Ideas Protocol from the App Brainstorming Guide to your app and record your answers respective section of the HackMD. Here's an example.

4. Design your product spec

  1. Reference the Product Spec Guide for a detailed overview and example of a product spec.
  2. As a team, work through the following three aspects of the product spec, filling out the respective sections of your HackMD doc.
    Check out this Product Spec Intro & Demo Video for a detailed walkthrough of the process.

User Stories

Think of your user stories in 2 categories, required and optional. Required user stories should include only the most essential features your app needs to "do it's thing". This is what is known as a Minimum Viable Product or MVP. Optional user stories are any features that would enhance your app and would be really "nice to have", but are not absolutely essential for the main objective of your app.

Screens

Every app is composed of many different screens. Based on your required user stories, the next step is identifying the core screen archetypes, the different screens your app will need in order to function.

Navigation Flows

Next we want to take our screen archetypes and required user stories and define the navigation within our apps. This includes both the tabs in your app bar, and the flows from one screen to another.

Be sure to check out the product spec guide here for an example of each step of this process.

5. Create Group GitHub Organization

As you know, GitHub is an online platform that allows teams to collaborate for project and software development. In this section, you will create an organization for your group and then create a repo to manage your project.

  1. Designate a group member to create an organization on Github
    • Choose a name for your organization.
    • Select the Free plan.
    • Invite each group member to the organization, making sure they have write access permissions.
  2. Create a new repo
    • Choose a name for your repo
    • Choose, "initialize with README"

6. Update Group Project README - App Description & Spec

Copy/paste the contents of your group's HackMD doc from this activity into your GitHub README. Check out this Unit 8 Example README for reference.

7. Update Group Info - Course Portal

Follow this Update Group Info Guide to update your group's information on the course portal. Update your group info anytime your app's name or description change or after your build to add your demo video.

πŸ“¬ Submit your app assignment by Self-paced using the Submit button πŸ‘‰

Parstagram Part 1

Parstagram Required Features

Overview

Build an Instagram-like client with a custom backend server that allows users to post photos and view their feed.

Required User Stories

  1. User sees app icon in home screen and styled launch screen.
  2. User can sign up to create a new account.
  3. User can log in.
  4. User can take a photo, add a caption, and post it to the server.
  5. User can view the last 20 posts.

Bonus User Stories

  1. User can pull to refresh.
  2. User can load past photos infinitely.

Let's Get Building!

Now that we know what user stories we need to build, it's time to start actually building something! Complete each required user story below by clicking on its walkthrough video and following along.

Required User Stories

1. Parstagram Overview

Introduction Video


2. Setup Parse Server

Setup Cocoapods and follow the guide below to setup your own Parse Server on Back4app, and configure your iOS app to communicate with your server.

  1. Set up dependencies –-> Setting up Cocoapods
    • Before you move on, make sure your Podfile looks something like this:

       target 'MyApp' do
       	...
       	# Add Parse pods and install
       	pod 'Parse'
       	pod 'AlamofireImage'
       end
      
    • Next, you will no longer be working on same project file. You will be working on the .xcworkspace file from now on:

  2. Set up Parse Server --> Parse Setup Guide

3. Signing up and Logging In

Follow the video below to learn how to authenticate with Parse.

Walkthrough Video

Reference links


4. Posting a Photo

Follow the videos below to launch the camera on the simulator or phone, and allow the user to create a new post with the picture and a caption.

Walkthrough Videos

Launching Camera

Saving the Post

☝️ at 8:35 - 9:20 in this video, you'll need to replace the instructor's Line 30 with the following updated line of code: let file = PFFileObject(name: "image.png", data: imageData!)


5. Loading the feed

Follow the video below to query Parse for posts, and display them in a table view. Note, for the final step, you'll have to configure your iOS app to allow downloading of non-secure (http) images. The relevant reference link is included below.

Walkthrough Video

⚠ NOTE: On 19:00 in the video, it won't be necessary to update your App Transport Security (ATS) settings anymore due to recent updates πŸ˜€. Also, cell.posterView.af_setImage is deprecated (old syntax). To fix this warning, make sure to change it to cell.posterView.af.setImage


1. Push your project to GitHub

Congratulations πŸ™Œ, you've completed all the required user stories for this project! Check out the following walkthrough videos in order to push your project to GitHub and prepare it for submission.

  1. Push your project to GitHub ☝️ Use this Unit 5 Assignment - README Template in the above Adding a README step.

πŸ’‘ Stuck using Xcode Git Tools? Check out our new tutorials for using tools like GitHub Desktop or through Good'ol terminal + Git commands!


7. Submit your assignment

Now that your project is pushed to GitHub with a README and GIF, the last step is to submit your project to us for review. Here's how to submit your assignment:

  1. Scroll up to the top of this page and click the Submit button at the upper right.

  2. Complete the submission form as follows and click Submit.

πŸ™Œ WHOOP WHOOP!!! At this point your submission is complete! πŸ†


Bonus User Stories

Click to see!

1. User can pull to refresh

2. User can load past posts infinitely

When the user scrolls down and reaches the bottom of the feed, the app should fetch older posts. The user should be able to scroll through all past posts.

Some other ideas for your app

These following is just for inspiration and to explore some additional feature possibilities. Please note that we don't have explicit resources or instructions for these features.

  1. Style the login page to look like the real Instagram login page.
  2. Style the feed to look like the real Instagram feed.
  3. User can use a tab bar to switch between all "Instagram" posts and posts published only by the user. AKA, tabs for Home Feed and Profile
  4. Add a custom camera using the CameraManager library.
  5. Show the username and creation time for each post
    • Hint: If you use TableView Section Headers to display the the username and creation time, you'll get "sticky headers" similar to the actual Instagram app.
  6. After the user submits a new post, show a progress HUD while the post is being uploaded to Parse
  7. User Profiles:
    • Allow the logged in user to add a profile photo
    • Display the profile photo with each post
    • Tapping on a post's username or profile photo goes to that user's profile page
  8. Run your app on your phone and use the camera to take the photo
  9. Add push notifications to your app!

Helpful Pods

  • Custom Camera
    • Allows for incorporating camera functionality into any view. This would allow you to create a custom camera experience you can style like the the Instagram camera or any way you want!
  • TextView with Placeholder
    • The UITextView allows for multi line input but lacks the ability to add placeholder text. After adding this pod, you can select any regular UITextView in the storyboard and change class to RSKPlaceholderTextView. You will then have the ability to add text placeholder text to the text field in Interface Builder.
☝️ NO submission is required for labs

Lab 5 Yelp Chat

Parse Chat

In this lab you will build a chat client using Parse to explore the features of its ORM and backend service. We'll explore how to authenticate a user, design schema, and save and retrieve data from a Parse server.

At the end of the exercise your app will look like this:

Chat

Getting Started

  • The checkpoints below should be implemented using the Pair Programming method

Milestone 1. Project Setup and Initialize Parse πŸ‘·β€

  1. Use the Yelp Project Starter.
  • If you want to build off your old project you will need to implement a Tab Bar, Login View, and a Chat View along with their associated files to use them.
The storyboard and files are already updated and ready for you to implement your code. Note: The files we will use are
  • AppDelegate
  • SceneDelegate
  • LoginVC
  • ChatVC

  1. In this lab, we'll be sharing a Parse Server that has already been created for us. To use this account, the applicationId and server are provided in the code snipped below:
    • In any Swift file that you're using Parse, add import Parse to the top of the file.

    • In the AppDelegate, register Parse in the application:didFinishLaunchingWithOptions: method:

      Parse.initialize(with: ParseClientConfiguration(block: { (configuration: ParseMutableClientConfiguration) in
          configuration.applicationId = "CodePath-Parse"
          configuration.server = "http://45.79.67.127:1337/parse"
      }))
      

Milestone 2: Login and Sign Up ✍️

  1. New user can tap "Sign Up" button to sign up

Sign Up

In the sign up function we need to check to see that is the username and password is not empty. Once this is verified we need to store the user info to the PFUser() by setting the username and password attributes. Next we can pass the user info to the newUser.signUpInBackground

Sign Up

Log In

Existing user can tap "Login" button to login this function will follow a similar format to the sign up function. First we will set the user info and pass it in to PFUser.logInWithUsername

User sees an alert if either username or password field is empty when trying to sign up

  • πŸ’‘ Use the isEmpty property of a text field's text to check if it's empty. Use the || operator to require one condition or the other.

User sees an alert with error description if there is a problem during sign up or login

Log In

Milestone 3: Display the chatView πŸ–Ό

Because we only want to display the login screen when the user first signs in and we dont want to display a back button on all the views we will go into the SceneDelegate.swift and control all the scenes.

  1. Create a listener

In the scene function lets add a listener for when the user logs-in and lets have it call a function called login() when we receive a notification

ChatView



We will also need a listener for when the user logs out
  1. Change the view

After a successful sign up or login from the Login View, we need to change the view programmatically.



Milestone 4: Send a Chat Message πŸ’¬

Compose Chat

The Chat Screen will allow the user to compose and send a message.

  1. We will need an array to store our messages and a chat message object
var messages: [PFObject] = []
  1. When the user taps the "Send" button, create a new Message of type PFObject and save it to Parse
    • Use the class name: Message (this is case sensitive).

      let chatMessage = PFObject(className: "Message")
      
    • Store the text of the text field in a key called text. (Provide a default empty string so message text is never nil)

      chatMessage["text"] = chatMessageField.text ?? ""
      
    • Call saveInBackground(block:) and print when the message successfully saves or any errors.

      chatMessage.saveInBackground { (success, error) in
         if success {
            print("The message was saved!")
         } else if let error = error {
            print("Problem saving message: \(error.localizedDescription)")
         }
      }
      
    • On successful message save, clear the text from the text chat field.

Milestone 4: View a List of Chat Messages

  1. Setup the a TableView to display the Chat Messages
    1. Add a tableView to the Chat View Controller and a custom cell that will contain each message.
      • For now, the cell will only contain a UILabel (multi-line) for the message.
        Table View Cell
    2. Create a new file for the custom cell, "ChatCell" as a subclass of UITableViewCell and associate it with the Chat Cell in storyboard.
    3. Set the "Reuse Identifier" to "ChatCell".
    4. Create an outlet for the table view and set it's delegate property.
    5. Declare the Chat View Controller to be a UITableViewDataSource and conform to the data source protocol by implementing the required methods.
  2. Pull down all the messages from Parse:
    1. Create a refresh function that is run every second.

    2. Query Parse for all messages using the Message class.

    3. You can sort the results in descending order with the createdAt field.

      query.addDescendingOrder("createdAt")
      
    4. Once you have a successful response, save the resulting array, [PFObject] in a property (instance variable) of the Chat View Controller and reload the table view data.

Milestone 5: Associating Users with Messages

  1. When creating a new message, add a key called user and set it to PFUser.current()

  2. Add a username label to the Chat cell to display the chat message author's username.
    Username Label

    • Note: You will need to adjust the autolayout constraints and cell layout to accommodate the username label. Try removing the chatTextLabel's top constraint to the cell content view and then creating a new top constraint to the username label. You can then pin the username label's leading, top and trailing constraints to the cell's content view.
  3. When querying for messages, add an additional query parameter, includeKey(_:) on the query to instruct Parse to fetch the related user.

    query.includeKey("user")
    
  4. In cellForRow(atIndexPath:), if a chat message has the user property set, set the username label to the user's username. Otherwise

    if let user = chatMessage["user"] as? PFUser {
       // User found! update username label with username
       cell.usernameLabel.text = user.username
    } else {
       // No user found, set default username
       cell.usernameLabel.text = "πŸ€–"
    }
    

Milestone 6: Persist Logged in User

  1. On app launch, if current user is found in cache, user is taken directly to Chat Screen

    1. In the SceneDelegate, check if there is a current logged in user in the scene function .
      • Parse automatically caches the current user on sign up or login. The current user can be accessed using, PFUser.current()
if PFUser.current() != nil {
    login()
}
  1. Programmatically load the Chat View Controller and set as root view controller.

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let chatViewController = storyboard.instantiateViewController(withIdentifier: "ChatViewController")
    window?.rootViewController = chatViewController
    
πŸŽ‰ Congrats! πŸ₯³ You have finished all the required user stories.

Optional Stories

  1. Create a Setting page where a user can logout

  2. User sees an activity indicator while waiting for authentication.

  3. User can pull to refresh Chat feed

  4. Add an "Adorable Avatar" for each user by requesting an avatar from the Adorable Avatars API.

    • Pass in the username in the url
    • Install the AlamofireImage Pod and use the af_setImage(withURL:) UIImageView instance method to fetch and set the image at the specified url.
  5. Chat Bubble Style Design

    • Remove table view row outlines in viewDidLoad()

      tableView.separatorStyle = .none
      
    • Add a view to serve as your speech bubble. Move the label as a subview of the bubble view and re-do autolayout constraints

      • Set desired color (In code or IB)

      • Configure rounded edges in code.

        bubbleView.layer.cornerRadius = 16
        bubbleView.clipsToBounds = true
        

    Speech Bubble