StudApp

April 7, 2018 Stud.IP to Go

StudApp is an iOS application for the Stud.IP learning platform, which is used by more than half a million students and lecturers at over 40 German universities and 30 other organizations like the German Football Association or a state police.

This project aims to take this platform to the next level by leveraging native capabilities of iOS. With StudApp, it easier than ever to browse your courses, documents, and announcements! Being officially certified by Stud.IP e.V., it provides excellent ways to stay up-to-date.

And—just like Stud.IP itself—StudApp is completely open source and free to be used by anyone as an no-cost app on the App Store.

If you know German check out the official StudApp website!

Screenshot of StudApp

Screenshot: Course Overview

Motivation

Being a student at a university that employs Stud.IP, it has always bugged me how complicated it has been to learn with your professors’ slides on iPhone and iPad: You either had to use the mobile site: sign in, find the document you are looking for, and download. Or—to access your files when offline—download every single one onto your computer and then sync them with iCloud Drive. As you might imagine, both options are quite tedious.

This is why I started development of Stud.App pretty much a few weeks after starting university together with Julian Lobe, who I got know in a math course. Stud.App served as a document downloader for Stud.IP. We later added support for messaging and schedules.

Progression

Due to time constraints, unfortunately, we realized that we had to pause this project.

But half a year later—inspired by iOS 11’s new Files app, which completely changed file providers for good—I thought I’d give it another shot: I started Stud.Sync as a very minimal app with a Stud.IP file provider. Because file providers are implemented as app extensions, StudKit was born: A cross-platform Swift wrapper for Stud.IP’s APIs. It also takes care of persisting and organizing data using Core Data. I couldn’t reuse much of Stud.App because Stud.IP 4 features significant API changes.

As Stud.Sync grew I came to the conclusion that it would be cool to share this handy tool with my fellow students and lecturers. Since it started to become more than just a file provider, I rebranded it as StudApp.

Making It to the App Store

After many months of coding and continuous feedback from Julian, the time had come when I thought it was ready for release!

I turned to Cornelis Kater, chairperson of Stud.IP e.V., which is a public interest society dedicated accelerating Stud.IP development and external representation. Luckily, he was immediately excited about Stud.IP getting an iOS app and kindly offered all kinds of help!

Following that, I came to know the development community behind Stud.IP, who help me by fixing API bugs and even programming new API routes for me! Notably, Rasmus Fuhse always supports me with feedback, ideas, and API assistance.

Having followed necessary guidelines and presented StudApp at the Stud.IP Developer Conference 2018 in Bremen, my app is now officially certified and, thus, ready for release!

Features

Having told you all about how it came to be, I’d like to finally introduce you to StudApp’s features. As this is a developer blog, I’m also going to illustrate some technical background.

Please note that StudApp requires iOS 10 or higher and Stud.IP 4 or newer. However, a few feature—most notably the file provider but also little things like table cell swiping—need a more recent system version. Similarly, some APIs are unavailable on prior Stud.IP releases.

Dynamic Organizations

First of all, StudApp isn’t bound to one university: It is designed to be compatible with any Stud.IP!

When signing in, users can select their organization and authenticate against it. This organization picker is backed by CloudKit, which makes it pretty easy to add and remove organizations without the need for an app update.

StudApp automatically adapts to the chosen organization by adapting the the tint color and disabling features that are unavailable.

Offline Availability

Using Core Data, I’m able to achieve full offline availability while retaining great performance throughout the app.

I’ve built an efficient mechanism that automatically updates stale data and removes deleted records locally. It respects whether the user is in “Low Power Mode” and doesn’t repeatedly update the same data in a short amount of time in order to save mobile data. By bundling requests, StudApp also tries to preserve battery life.

Of course, you can also download documents. Learn more about that in File Management.

Courses

Users can select their semesters of interest. These semesters are then available in the main view and can be expanded or collapsed, making navigation a breeze. Courses that span multiple semesters correctly appear in all of them. And if a certain course isn’t relevant, you can easily hide it away.

With just a swipe, one can change a course’s color and affect how they are sorted. This is pretty useful if you want to keep similar courses together and automatically synchronized with the website.

This feature requires Stud.IP 4.2 or the CourseGroupPatchRoute plugin.

Apart from announcements and documents, course details views provide additional details, e.g. lecturers, locations, the next event, and description with data detection and easy copying. The action button shows a share sheet with a custom activity that opens the course site inline in an SFSafariViewController.

You can also swipe-to-refresh manually.

Screenshot of StudApp

Screenshot: Course Overview

Announcements

One of the most-used features of Stud.IP is announcements: An easy way for lecturers to share news with their students.

This is why they are also implemented in StudApp and provide almost all formatting options, leveraging WKWebViews rendering powers. Nevertheless, fonts adapt to users’ type size settings!

New announcements are highlighted automatically.

Events

It is always important to know where to go next. This is why—since version 1.1—StudApp supports events by providing a dedicated tab, which shows a user’s next two weeks. Events not only include course, time, and location but also the topic of a lecture and a customizable subtitle. A custom date tab bar at the top lets one easily jump to specific dates.

Similarly, you can view a list of all events by course.

Screenshot of StudApp

Screenshot: Events

File Management

Browsing, downloading, and viewing documents is StudApp’s main purpose. Each course has associated with it a root folder that can contain nested folders and documents. Once uploaded by a lecturer, students can access their slides, exercise sheets, solutions, or other learning materials with just the tap of a finger. Previewing files makes use of the native QuickLook capabilities.

Downloaded documents automatically appear in the corresponding tab, grouped by courses. You can also search documents by title, owner, and course.

To make availability obvious, inaccessible documents or folders are greyed out automatically, e.g. when a user’s device is offline and a document is not downloaded.

StudApp also highlights new files as well as those that have recently changed. User can also (un-)highlight manually.

Apart from regular files hosted by Stud.IP, the app supports downloading or linking to documents hosted by third parties and web links. It also guesses an appropriate file extension if none is given.

Screenshot of StudApp

Screenshot: Downloads

Privacy

Yes, privacy is a feature.

It is important to me to follow Apple’s lead and respect user privacy. I don’t collect data and user data never leaves the device. Thus, StudApp is completely independent from my server. Every synchronization feature is realized either via Stud.IP or CloudKit. I have no way to access personal data. Additionally, the local database enjoys all of iOS’s default security mechanisms.

Sign-in utilizes OAuth1 so that there is no way for me to get near a password. All authentication tokens are, of course, stored securely in Apple’s Keychain. Furthermore, organizations can use their preferred authentication method in SFAuthenticatedSession or SFSafariViewController on iOS 10.

Due to a limitation in Stud.IP 4.0, the app has to spin up a local redirect server during the authorization process. There is no third-party server involved.

System Integration

Native apps are only useful if they make use of the operating systems power instead of trying to mimic their web counterparts. Learn how StudApp integrates with iOS!

Native Design

There is only one way to make an app feel natural: Use the native UI framework instead of a custom solution or a cross-platform lowest-common-denominator library.

That’s why I use UIKit and adapt the overall design language of the system, following Apple’s Human Interface Guidelines.

StudApp also includes many optimizations for small screens like the iPhone SE’s as well as large ones like from the iPad Pro. Naturally, I utilize UISplitViewController and readable content guides.

File Provider

The app also includes a file provider, which makes course files available in the native Files app—just like iCloud Drive!

I’ve made sure to support all convenience like tagging and marking something as favorite. And—like the main app—the file provider automatically refreshes contents and synchronizes with other targets using NSPersistentHistory.

Spotlight Indexing

Often, you need a specific document right away. You might remember part of its name but don’t exactly know where to find it.

Thanks to Spotlight, this is not a problem with StudApp! Courses and documents are automatically indexed and removed from the index when appropriate. Even if a document isn’t currently on the device, you can search from your home screen and view it. The app will take care of downloading it if needed.

Drag’n’Drop

Supporting Drag’n’Drop for documents, folders, and textual data was a no-brainer because UIKit made it very easy to implement. You can drag take a document and drop it on your iCloud Drive desktop!

Handoff

My app supports handoff for both documents and courses. A user can seamlessly continue his activity on another iOS device. If a document is not yet downloaded, StudApp does it for you.

All activity eligable for handoff include a fallback URL that can be opened in Safari. Navigating to a course or downloading a document on your Mac becomes as easy as a single click!

State Restoration

A more subtle feature is perhaps state restoration: When launching StudApp after it has been terminated by the operating system, it tries to restore previous state so a user can continue what he was doing when he left the app.

3D Touch

StudApp supports 3D Touch (almost) everywhere—previewing folders, announcements, and documents is a breeze! It also has home screen and other quick actions that make navigation easier.

Haptic Feedback

When completing a task like downloading a document, StudApp gives subtle haptic feedback to let a user know that he can now continue with his task.

Accessibility

Accessibility doesn’t just comprise optimizations for people who are visually impaired or have difficulties hearing: It means making your app usable by everybody. In the case of Stud.IP, this means supporting all kinds of organizations instead of making the app specific to just one university.

It is also important to ensure backwards compatibility for people with older devices and optimizations for all screen sizes. StudApp requires at least iOS 10 and makes certain features available by providing them via menus instead of just gestures that only work on iOS 11 and higher or devices with 3D Touch.

Full Internationalization

As there are many international students in Germany, providing multiple languages makes a significant difference. StudApp supports German—my native language—as well as English. I’d be happy to find others who are willing to help with translating to other languages!

Another part of full internationalization is using the correct data formatters, which adapt to the user’s preferred units and formats. I also took care of correct pluralization forms.

Dynamic Type

This is an iOS system feature that lets users change their preferred font size. My app automatically adapts to the user’s settings and even adjusts its layout for large accessibility fonts!

VoiceOver

VoiceOver enables navigation using simple gestures or switch controls without needing to see the device’s display. StudApp is heavily optimized for it—it even correctly speaks colors in the color picker!

I also made sure to speak all information that is normally conveyed using visuals and implement custom accessibility actions where needed.

Using StudApp

Do you want to add support for StudApp at your university, school, club, or other kind of organization? Glad to hear that!

I’ve made it very easy for you:

  1. Be administrator of a Stud.IP instance of version 4 or higher
  2. Activate the REST API
  3. Generate OAuth credentials
  4. Give them to me in a secure way and I’ll add your organization to StudApp organization picker
Supporting StudApp at your organization doesn’t cost a cent—how cool is that?

If you want to support development, feel free to give a tip using the button in the in the app’s about section. Thank you!

Future

Cornelis Kater, Rasmus Fuhse, Florian Herzog, and I aim to make native apps an integral part of the Stud.IP experience. I don’t want to spoil to much but planned features include an instant messenger and push notifications.

There is more to come—be tuned for future updates!

Architecture

If you want to know more about how StudApp works, you’ve come to the right place! I’ll give a general perspective on how things work.

There are many topics that I’ve discussed in detail in other blog posts or will do so in the future. Give them a read if you like!

You can also find more elaborate information as documentation comments in the source code. I encourage you to check it out!

Patterns

This section gives a broad overview over design patterns used in StudApp with the goal to make its code easy to understand and maintain.

Layout

StudApp is divided into five distinct targets (and—where useful—accompanying testing targets):

StudApp is the actual iOS application with all view controllers and storyboards except those shared by multiple targets.

StudKit is a common framework containing all models, view models, and services. It is meant to be a common foundations for all targets, including potential macOS apps.

StudKitUI, also a common framework, contains UI-related constants, views, and shared view controllers and storyboards.

StudFileProvider integrates with Files, which is iOS’s native file browser.

StudFileProviderUI displays user interfaces inside Files.

Each targets groups sources files logically instead of by type, sometimes nested. For instance, Api, HttpMethods, and Result+Api are all contained within one group. Extensions that operate on another framework’s objects are grouped by framework.

MVVM

This project utilizes the MVVM “Model-View-ViewModel” pattern, which encourages separation of view and business logic and makes both easier to reuse and test. All models live in StudKit, e.g. in the form of database models and services. View models also reside in StudKit. Views and controllers form the View part of MVVM.

Using this approach as an addition to Apple’s MVC actually makes a lot of sense for this project as I am able to reuse much of my view model logic in both the main app and the file provider. It also makes developing a potential macOS app way easier.

Dependency Injection

Another pattern that StudApp uses is Dependency Injection, which makes unit testing a lot easier. For example, I swap the real API class with a mock subclass that always returns specific responses.

I’ve implement a minimal approach that lets targets register instances for specific types at launch. Later, services can resolve these instances at runtime.

Frameworks and Libraries

To give you a broad overview, here are the frameworks and libraries used in StudApp:

  • CloudKit—Managing and updating organizations
  • CommonCrypto—signing requests
  • CoreData—persisting and organizing data
  • CoreGraphics—drawing custom graphics like confetti or the loading indicator
  • CoreSpotlight—indexing app content
  • FileProvider—providing data to the Files app
  • FileProviderUI—showing UI in the Files app
  • Foundation—performing network requests and much more
  • MessageUI—Showing a mail composer for feedback
  • MobileCoreServices—dealing with file types
  • QuickLook—previewing documents
  • SafariServices—displaying websites inline and authorizing a user
  • StoreKit—handling tipping
  • UIKit—creating the iOS app UI
  • WebKit—rendering web-based content like announcements
  • XCTest—testing my app

Why I Use Apple Frameworks Almost Exclusively

One of my personal goals with StudApp is learning more about the exciting opportunities that Apple frameworks provide. This is why I opted for first-party frameworks or implementing simple stuff myself instead of using a bunch of libraries.

Another concern I have is speed and security: Third-party libraries often come bloated with many features I’ll never use and slow down app launch as discussed in a WWDC16 talk. Moreover, I cannot always verify the integrity and security of such libraries, whereas official Apple frameworks go through more rigorous testing and quality assurance procedures.

Testing

Ensuring quality requires automated testing. I use XCTest to unit-test my models with a focus on parsing API responses as well as updating and fetching data.

I’ve created a way to automatically load mock data into Core Data when running UI tests. Those tests will be automated in the future.

Code and Licensing

As mentioned in the introduction, StudApp is completely open source and licensed under GPL-3.0. You can find everything you need on GitHub!

Why I chose GPL

Since StudApp is a complete software available on the App Store and not a library, I want to encourage sharing improvements and prevent people from releasing their own closed source modified version since it took many months to build.

The thing about GPL is that it requires source disclosure and forbids sublicencing, i.e. using something in a non-GPL-project. To that end, it is a perfect fit. Especially because Stud.IP follows the same approach.

However, I appreciate feedback and contributions of any kind! It would also be great to find people excited about Stud.IP who could help maintain this app in case I’m not able to.