It's now easier than ever to deliver academic tests on the Mac. Learn how education developers can leverage the Automatic Assessment Configuration framework for iPhone, iPad, and Mac to deliver tests and assess students across all devices. And discover how developers can enable restricted features within tests and exams on iOS to accommodate student needs or suit the test content.
Hey, everyone. My name is Josh, and I'm an engineer on Apple's Education and Enterprise Team. Today I'm excited to share with you what Apple's been up to the past year in the assessment space. Education is deep in Apple's DNA. Whether Apple's striving to put Apple II's in every classroom, or iPad and Apple Books is transforming textbooks, Apple products have been hailed as revolutionary educational tools. Our introduction to assessment was in 2013 with autonomous single app mode on the iPad. This system piggybacked off MDM to restrict devices during exams, but was soon replaced with an entitlement-based system known as Automatic Assessment Configuration, or AAC for short. This next step made deployment of assessment apps easier and expanded their use to non-supervised devices.
We work closely with developers to make iPad a modern assessment platform. It helps prevent unfair advantages like switching apps, using auto-text-complete, and looking up words in the dictionary. And as a result, assessment mode on iPad has been adopted by a majority of standardized digital test vendors. And now we're going to push things forward again by bringing standardized testing to the Mac with a new framework called Automatic Assessment Configuration.
I'd love to give you a tour of what this new framework has to offer. Assessment mode on the Mac is not identical to iPad because it runs on, well, not an iPad. The goal is to preserve the same testing environment on each platform.
Typically with a new feature, I'd explain what new things a user can do, but with assessment mode, the magic's in what a user is prevented from doing. During assessment mode, only your app is visible, and things like the Dock, Mission Control and Notification Center are all unavailable. You can't record or capture your screen. While other apps can be opened, their windows are hidden, and for all other processes, network access is prevented.
Playing media gets paused, and your pasteboard is cleared when the session begins and ends.
This list is a subset. You can always look to the developer docs to answer any specific questions about what system services are affected during this mode.
An important thing to note is that this new feature is guarded by an entitlement. Information about how to apply this entitlement and how to integrate it into your app are also available in the developer docs.
Now that we've learned about what the new AAC framework does, let's take a closer look at how it works. But before we hop into any code, I wanna talk about the assessment mode life cycle and how it relates to your app.
When your app begins running, assessment mode will be inactive. It's up to you to decide when the appropriate time to restrict the device is.
When that time comes, your app will request for assessment mode to begin, at which point the AAC framework will start modifying and restricting system services to create the safe testing environment. This can take some time, so it's a good idea for your app to present some kind of transition UI, maybe a spinner.
Once all services are in the right state, your app will be informed, and you can begin your exam.
After the exam is complete, your app should request for assessment mode to end. Just like before, this might take some time, so presenting transition UI will make for a better user experience.
Once the OS is restored to its previous state, your app will be notified, and you will have completed the assessment mode life cycle. This is the happy path through AAC, but in the real world, there's always the possibility for errors to pop up, and it's important that your app knows how to deal with them. The first place an error might bubble up is right after requesting to begin the mode. It's possible the service couldn't be restricted, or maybe you just forgot to entitle your app to use this feature. Either way, your app will be informed and assessment mode will return to the inactive state. The next place an error could occur is while the exam is running. Although very unlikely, it's possible that a service stops respecting assessment mode, and we can no longer make the same safety guarantees as before. If this happens, we do not tear down assessment mode. Instead, we inform your app that something has gone wrong and that you should stop your exam. Your app should hide all sensitive content immediately, and then release the remaining system services by ending the mode. Now let's take a look at how this cycle actually looks in code.
To get started, I'm gonna walk you through implementing your own AAC client. First, let's create a new class called the AssessmentManager. This class's job is to bridge your app's UI and the assessment mode life cycle.
We'll give it two functions: beginAssessmentMode and endAssessmentMode.
To actually begin and end the mode, our manager needs an AEAssessmentSession provided by the framework.
The assessment session reports all of its life cycle events via delegation, so we need to implement the AEAssessment SessionDelegate protocol in our manager. Now let's focus on what happens in the begin function.
First, you construct an AEAssessmentConfiguration. This object defines your customized assessment experience and by default, is the most restrictive. You'll use that to construct your AEAssessmentSession.
After construction, you'll wanna set its delegate in order to receive life cycle events. It's also important you hold on to the session to ensure it doesn't deallocate prematurely, ending assessment mode. I mentioned earlier that entering assessment mode might take some time, so you'll present some transition UI so your users understand something's going on. Finally, you'll call "begin" on the session and wait for the OS to enter assessment mode. The session will delegate back to the manager, either through the DidBegin or failedToBegin delegate functions.
In DidBegin, you'll have completely entered assessment mode. You can tear down the transition UI...
and present your testing material to the student.
The other possibility is the failedToBegin function is called.
In failedToBegin, you will start by tearing down your transition UI just like in DidBegin...
and since something went wrong, you'll probably present some kind of error to your users, and then finally, since you weren't able to get into the mode, your session is now invalid, and its reference can be discarded.
Now, assuming everything went okay and you received the DidBegin delegate call, the student can begin their exam.
Once the student signals they're all done, you'll end up calling endAssessmentMode on your assessment manager.
Now, first, your stored assessment session is an optional, so you'll have to unwrap it. Just like entering assessment mode, exiting may take some time, so you'll also present some kind of transition UI to your users.
Finally, you can ask your unwrapped session to end and take the OS out of assessment mode. Once the OS is restored to its original state, the assessment session will inform the manager through the DidEnd delegate function.
In our DidEnd function, we can tear down the transition UI, and we can present our post-test content, maybe something like a result page or a success page, and you can finish by discarding your reference to the assessment session.
The last part of this protocol is the wasInterrupted function. This will be called when something goes wrong during an active assessment session.
In this function, you should immediately hide all sensitive content. You could also use it as an opportunity to perform necessary cleanup or save test progress. After that, you can present an error message to your users.
Next, you'll present your exit transition UI and bring the OS out of assessment mode by asking the session to end. You'll know this has been completed once you receive the DidEnd delegate function. And that's it. You have your own AAC client that's nicely integrated with your assessment application. Now that we've covered the assessment mode life cycle and how it looks in code, it's important we go over some strategies for adopting this new framework in your projects. But first, let's talk about vegetables.
When I was much younger, I always hated when my vegetables got mixed up. I did not like when my peas touched my carrots. I would always divide them up on my plate with clear boundaries. Today as a developer, this really hasn't changed. But now instead of peas and carrots, I'm drawing clear boundaries between my logic and effects.
When I say logic and effects, I'm drawing the line between the parts of my code that decide to do things, and the parts that actually do things.
Examples of this idea are things like deciding to write a string to a plist versus actually writing it, or deciding to make a network request versus actually making that request. Or in your case, deciding to enter assessment mode versus actually entering the mode. In all these cases, an important pattern emerges. What if we look at all of these pieces in terms of who owns them? Your app owns all the logic. Your app's the star of the show. It's the thing that creates the cool new experience, and everything on the right side of the fence is just a detail. Now, you might be thinking, "Neat. What does this have to do with assessment mode?" Well, like other side effects, AAC can make writing tests difficult, and in your case, even make debugging in Xcode difficult.
So what do you do? You should establish a good boundary between your logic and effects provided by AAC. One way to do that is with protocols, often referred to as protocol-oriented programming. With protocols, you can define a contract detailing what work you need to be done without having to worry about who does that work. Why is this valuable? Let's take a look at some sample code just to see why. Let's pretend you've defined a protocol that encapsulates the entirety of assessment mode. It's got begin, end, and everything in between. We'll call it AssessmentManaging.
One implementation of this protocol will depend on a real AEAssessmentSession. This implementation will do the work in a production setting. In a test setting, however, you don't want your machine to get locked down.
For this case, you can replace the real one with an implementation that just logs when asking to enter assessment mode. Or even better, you could write an implementation specifically for testing that's loaded up with test expectations. That way you can be sure you're invoking your dependency correctly as well.
Depending on a protocol makes it easier to exercise all the logic surrounding assessment mode. If this seems a bit high-level or confusing, you can always look to the presentation companion sample app to see functioning examples of all of these ideas.
This has been a more lightweight explanation of protocol-oriented programming, so I recommend checking out these previous sessions that dive deeper into the topic. It's a valuable tool that will make writing tests for your assessment apps much easier, and as a result, make the apps themselves better. Since assessment developers are distributing tests for students, I think it only makes sense that their apps are tested as well.
Besides the testing context, establishing boundaries will be particularly helpful when debugging your assessment app in Xcode. Assessment mode on the Mac restricts which apps can receive user input events. If you're debugging your app in Xcode and you hit a breakpoint, you will have no way to proceed. The app will hang, waiting for the breakpoint, and you will be stuck, unable to interact with Xcode.
Fortunately, there's a solution. If you restart your Mac, assessment mode will stop running. In fact, all system services are guaranteed to be restored on reboot. This is both a feature and a great way to give students some agency over their own Mac. If you manage to deadlock Xcode and your assessment app, make sure to remember rebooting is your friend. Now let's talk about what we've done this year on iOS and iPadOS.
Along with the Mac, the AAC framework is also available on iOS and iPadOS. This will make for a unified developer experience when building on any platform. On iOS and iPadOS, the AAC framework actually improves upon the previous assessment experience. Let me show you how.
This is the original API from UIKit that developers have been using to enter assessment mode on iPad.
I brushed past this a little earlier, but during the sample code segment, I'm sure some assessment veterans noticed something a bit different about the AEAssessmentSession.
It's the config. The assessment session is designed to be configurable. We've heard loud and clear that developers want ways to make more customizable assessment experiences, so we've made it possible with this new framework. In iOS 14, you'll notice AEAssessmentConfiguration includes options for enabling system services like dictation, predictive keyboard and spell check.
These capabilities are critical for a great user experience, especially when you consider the many different kinds of exams, the different countries students might be taking them, and different needs students might have. For example, allowing spell check might make more sense on a math test where spelling isn't really being tested. Or continuous path keyboard might be beneficial for tests in languages where it makes inputting answers easier. This list of capabilities we're releasing is pretty cool, but actually, the idea of the list is cooler than the list. What I mean to say is that assessment mode configurability is now a first-class citizen. The AEAssessmentConfiguration is an expandable value designed to evolve with the landscape of the operating system and more importantly, with the needs of developers. I think it's pretty cool.
These new points of customization will only be available in the new AAC framework, so you'll want to migrate away from the existing assessment mode API in UIKit.
I have one more exciting piece of AAC news to give you. Now that we have a new assessment framework for iOS, iPadOS and macOS, and we expose the exact same API across all of them, it's only natural that we make this functionality available for Catalyst apps.
Beginning in iOS 14 and macOS Big Sur, your iOS apps will have complete assessment mode support when running on the Mac. No matter the platform, your app will initiate the contextually correct assessment mode. In summary, we brought assessment mode to the Mac with a new dedicated framework. We made that framework available on iOS and iPadOS and expanded upon the experience, making it more customizable.
And finally, we shipped a friendly, cross-platform API that makes bringing your iOS and iPadOS apps to the Mac even easier.
Thank you for listening to what Apple's been working on in the assessment space. Have fun building amazing apps
with these powerful new tools.