Today, MyState got a new feature, one that's been requested for years - Classes.
Students are now able to view their class schedule on their phones, and no longer have to carry around a screenshot of the non-mobile-formatted AccessPlus schedule:
Steps
The feature has been worked on since Spring 2015, but most of the front-end work was done in the past 4 months. The first order of business was getting APIs created.
- An API had to be created so the app could securely access student data from the 30+ year-old system that Iowa State uses for course management.
- We also needed to access the public database containing course descriptions, meeting times, and instructors.
- And finally, we needed to access yet another database that contained readable titles of courses, so something like INTR DATABS MGT SYS would look more like Introduction to Database Management Systems.
Once we worked with the web developers to obtain secure access to those databases, then my job really began.
Authentication
The first thing about this feature is that it requires you to sign in with your ISU credentials to pull your class schedule. Up to this point, MyState has been completely anonymous, in that there was never a need to sign in with your credentials.
Because of security requirements, we were not allowed to accept passwords within the app. My team and I worked with the web developers to create an authentication service, which signs you in on an official login page in your browser, creates an auth token, and sends it to the app via a custom URL scheme. This worked, but was a bad experience, having to switch between the app, Safari, and back again. Thankfully, the Safari View Controller in iOS 9 came to the rescue, allowing me to keep the user in the flow of the app, while not allowing the app access to anything that was entered into the password field.
Design
The first issue I had to tackle: The class schedule above is not formatted at all for mobile devices. How do I display all these classes to a user in a clean and concise way?
I began with the top half: the grid. The class schedule grid on AccessPlus is aligned with days of the week on the Y axis, and times of day on the X. This means that the grid is usually wider than it is tall. For a mobile device, where screen real estate is scarce, I thought it would be better to flip the axes, so days of the week went across the top.
I created a UICollectionView and subclassed a UICollectionViewLayout, overriding the layoutAttributesForItemAtIndexPath:
and other methods to create a similar grid view. I added some UICollectionReusableView
s as grid lines, and added more UICollectionReusableView
s as headers and time indicators.
The other issue I had to tackle was the white space. In the grid on AccessPlus, there is a bunch of white space, which would be filled in if I would ever take an early morning class, night class, or Saturday class (haha never). I wrote a quick algorithm that scans through a class schedule and finds the person's earliest and latest class times, and used the distance between those times to calculate the height of the UICollectionViewCell
s, so they would all fit on one page and not overflow. This removed the unnecessary white space and allowed me to not hard-code in a 6am - 10pm window for classes. I also removed Saturday from the grid unless the user has a Saturday class.
I ended up with something like this:
Next, was the table below the grid. I originally planned to have only the schedule grid show, and display necessary information about classes inside the colored boxes or on the detailed page. However, I discovered that a student can be taking classes that are not scheduled (i.e. online classes or independent study). I wanted to still allow the person to see these, so I ended up having to implement a table below the grid.
There was no way that I could fit all the information in the table on the website into a UITableView
row, but I didn't have to. We have a detail page for that! I only needed to show:
- The course DEPT/Code (i.e. COM S 311)
- The course title (i.e. Design and Analysis of Algorithms)
- The meeting time(s) (i.e. TR 11:00 AM - 12:20 PM)
So I created a basic UITableView
with custom rows, which did just that.
The next issue was that the UICollectionView
and UITableView
contained very similar data, but were not tied together in any visual way. To fix this, I opted to assign colors to each class, and display the colors on both views. Also, when tapping a cell in the collection view, it would highlight the corresponding UITableViewCell
, as well as all the other meeting times of the class.
The UICollectionView
and UITableView
were then arranged in a half-and-half vertical stack.
The end result:
Implementation
This module of the MyState app was the first module to be written in Swift. It lives within an app consisting of hundreds of Objective-C classes. I had no real issue with inter-operability between the two languages, except for a few minor glitches with Realm, the database that MyState uses for storing objects.
Features
The Classes module of the MyState app has 4 main features: the ability to view your classes, share them, save them to your iOS calendar, and calculate your potential GPA at the end of the semester.
Sharing your schedule
When tapping the share button at the top right of your class schedule, a share sheet comes up, and you are able to share a 1000px x 650px photo of your schedule with your friends.
How was this done, you ask? Well, it was actually really easy. I created a new UICollectionView
, set it's layout to be the same as the schedule grid's, set it's frame
to be CGRectMake(0, 0, 1000, 650)
, and set it's dataSource
and delegate
to the schedule grid's data source and delegate. I then did the following:
- Created a new
UIGraphicsImageContext
with the CGSize ofcollectionView.frame
- Called
collectionView.drawViewHeirarchyInRect(frame, afterScreenUpdates: true)
- Passed the image drawn into a
UIActivityViewController
Saving your schedule to the iOS calendar
This feature relied a lot on EventKit
, Apple's framework for manipulating the iOS calendar. All I had to do was add methods to each ISUClassSection
data model, which returned an EKEvent
object that details the calendar event for the class. Each EKEvent
object contains information about:
- The event's title
- Location
- Start and end times
- Repetition rules (i.e. all semester, half semester, etc)
Each EKEvent
was then added to an EKEventStore
for the calendar the user chooses to put events into.
GPA Calculator
This feature mirrors ISU's online GPA calculator. It allows you to optionally enter in your GPA up to this point, then shows you the classes you are taking. You enter what grades you think you will receive, and it will display the GPA you would have at the end of the semester.
This was fairly simple to create. The base logic was adapted from the Javascript code on the website, and then the current classes you are taking are pulled from the local Realm database.