App Frameworks • macOS • 39:40
Cocoa is a powerful set of frameworks on which OS X is built. Gain an overview of the advances in AppKit, Foundation, and related frameworks. Find out what technologies you need to focus on and what techniques you should adopt to develop state of the art apps for OS X. Start here for a high level view of what's changed, and get pointers to relevant sessions for more depth.
Speaker: Ali Ozer
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
[Ali Ozer]
Good afternoon. Welcome to What's New in Cocoa. My name is Ali Ozer. I'll be talking to you about what's new in Cocoa this year. Three areas: Swiftificaiton, AppKit, and Foundation. We have a lot of material, so let's dive in. Swiftification refers to the API enhancements we have done across our frameworks in support of Swift. The changes also improve our Objective-C APIs as well.
As you know, Swift provides features to express APIs more precisely. For instance, you can indicate this is an array. The Subviews property is an array of NSView, not just an array. You can indicate that a method such as System Font Of Size returns an NSFont and will never return nil. In methods such as Image For Resource, an NSBundle may return nil because it is declared as an optional NSImage.
We enable these features in Objective-C as well with nullability in generics. So I'm going to talk about these two areas briefly, and then also a few other changes we made to make our Objective-C and Swift APIs better. We applied these in APIs of many our frameworks, not just AppKit and Foundation. By doing this we not only do better exposure of the APIs in Swift but also make the APIs clearer and also provide compile time type-checking which is very important, of course.
Nullability is whether values can or cannot be nil. If you use Swift with X v10 or iOS 8 SDKs, you know the Swift APIs already have the proper nullability and optional declarations on them. We have managed that with handcrafted side data, side files. In X v11 and iOS 9, we bring this ability to Objective-C, and we have several new keywords we've added to Objective-C.
Nonnull indicates never nil, Nullable indicates can be nil, Null Resettable indicates that a property can be set to nil but won't ever return nil. We'll have an example in a second. Last and least, we have Null Unspecified, meaning not specified. This is used for deprecated stuff or stuff that has not yet been audited.
Since nonnull is the majority of cases in our API, we also have these two declarations: Assume Nonnull Begin and End, which we wrap our header files with. With this, the nonnull declarations are no longer needed. Nonnull is unnecessary and we have the other declarators on our APIs. We recommend you use these in your header files if you have a lot of header files of your own.
Let's look at some examples of how these affect our APIs. You can see the Color property on NSColorWell. We have not put any declaration on it, which means it is nonnull and comes across in Swift as a non-optional value. The Color property. The Image property of NSImageView, on the other hand, is nullable which means that it can be set to nil and comes across in Swift as an optional value.
And finally the Font property of NSMenu is declarated as null resettable, and this comes as implicitly unwrapped optional. In this case what this means is we can set this value to nil, but it will never return nil. What NSMenu does is if you ever set it to nil, it goes back to the default font that it would have had for the system. So it never will return nil.
With nullability, you may see some build time warnings. Let me show you an example. If you have code like this that was setting the Color property of a ColorWell to nil, the compiler will now warn because we declared this to be nonnull. This is a good thing because it turns out if you had the code and it was being run, it would have raised a parameter assertion anyway. This is kind of things that now you'll get warnings about from the compiler. That's great.
As you probably know, in general nil is not a valid object value in our APIs. NSString, NSArray, NSDictionary, et cetera have easy to express empty values and APIs that accept or return nils should document what nil means as an exceptional case. I'll give you several examples from our APIs. If you set the background color of an NSTextView object to nil, it means don't draw the background. A nil locale in many of our APIs that take locale means nonlocalized. So you can specify a locale, but if you specify nil it means nonlocalized.
Let's talk about generics. Generics as you have heard is lightweight type parameterization that we added to Objective-C and great for specifying types of elements in collections. Here is an example of NSSearchField. The Recent Search property of NSSearchField is declared like this in X v10. The name Recent Searches is not superclear. What does this contain? Strings? URLs? Some search objects? In X v11 SDK, we can clarify this. It is an array of NSString. And the Swift declaration goes from an array of any object to an array of string as well.
The way we have done this, we have taken NSArray in Foundation and added the Object Type parameter to it, like so. We have applied this object type to all of the APIs, appropriate APIs, which used to take or return ID, such as object at index, contains object, and so on.
There is many other APIs this applies to in NSArray. With this, the code we had with Recent Searches, let's say you had a code like this, Recent Searches contains object, some URL, we are passing in NSURL. The compiler now will warn you that you're passing URL into a method that expects an array of strings.
The great thing here is this code would have never failed or crashed because that URL never would have been found before. The compiler is telling you of a potential bug in the code. We have added generic support in Foundation not only to NSArray but to all the other collections as well, including NSEnumerator, which strictly speaking is not even a collection, of course. You can apply this to non-collections as well.
Now with generics you can use them as well, you can use them in variable declarations in your own classes. If you are taking the result of Recent Searches and assigning it to a property of your own, you can go ahead and declarate that to be NSArray of NSString, and that will allow the type to propagate through your own code.
You can declarate your own properties in APIs. Here is an array of files. What are they? Strings or URLs? You can be clear. You can apply generics to your custom collections if you have any or even to your custom categories on foundation collections. For instance, here is a category on NSArray. You can go in and add it, just right there in your own code. These generics work with categories as well.
Now kindof is another feature we have added to Objective-C. Let's give you motivation as to why we need this. Here's what the subviews declaration looked like in X v10. Here is what we did our first attempt in applying generics. Subviews was changed to NSArray of NSView. Then we had code like this, where we assign an element out of this array into NSButton.
Turns out that this concerns the compiler, the compiler is always looking out for us, always concerned. It generates a warning. Why? Because we're assigning something that's explicitly declared to be an NSView to a subclass of NSView, and the compiler is right in being concerned. However, this is a kind of code we use a lot, and it is often valid. So we added this kindof keyword and changed the declaration of the subviews property to be NSArray of kindof NSViews. What this says is -- [Applause]
[Ali Ozer]
Thank you. Thank you for overlooking the under bars there! What this says, it is okay for the caller to be able to access the elements of the array as instances of the specified class or instances of a subclass as well. So this is now -- this works.
Note that kindof is a compile time facility like most of the things I have talked about here. There is no runtime code changes, there is no runtime check for the type, for instance. There are cases where we want the caller to think about what the elements are before accessing them.
So we're going to use these sparingly in our APIs and we recommend you do the same. They should be used when it is safe for the caller to make that assumption. If you want the caller to think twice or maybe do some runtime query, don't use the kindof. An example is this Representations method on NSImage.
It returns an array of NSImage reps, which are often subclassed, almost always subclassed. However, we have not used kindof here because the kindof representations you get back isn't always predictable and it might, in fact, change during the runtime of an application or in fact between releases of the OS. It is better for the caller to be more alert here and do some runtime checks.
Let me talk about error handling. As you heard yesterday, Swift 2 brings an amazing error handling facility. What that means is for a method like this on NSData write to URL options error, it now looks like this in Swift. The Boolean return value goes away, it is now implicit.
And the error, the by reference NSError parameter, also goes away because it is captured in the throw statement. Here is a kindof code you write to deal with this. As you can see in the catch phrase, you can capture the error, it is either available for you automatically or you can declare it. And you can declare different catch statements, of course, as well.
It is great, straightforward. Now, one thing. Note that despite the terminology here, throw, try, catch, et cetera, these are not exceptions in the Objective-C sense. We're not raising exceptions here. We're actually returning errors and unwinding properly through the stack just like, you know, what we do with NSErrors.
In fact, NSError guidelines apply to the Swift error handling. Use NSErrors and Swift error handling for runtime errors, errors that you expect to present to the user or handle at runtime, such as file not found and so forth. We continue to use exceptions or Swift assertions for programming errors such as array index out of bounds.
The last category, of course, are the kind of errors that are not expected to be captured. One more Swiftification item is naming cleanup. As you might be away, we still have a lot of enum names from a long time ago where we use a common suffix rather than common prefix, and we have renamed them in some cases, not all, to have a common prefix, which means that they come across in Swift with a better name.
Instead of dot left text alignment it comes across as dot.left. There are many more examples of this. Note that in many cases we haven't actually deprecated the old names, so your sources will continue to compile, but you can switch to the new names as you rewrite your code.
And there is many more of these. With that, let's switch to AppKit. There are many AppKit topics I would love to talk about, I'll talk about some. One note here: from this point on i'm going to show APIs and code samples mostly in Swift. Even if you're not comfortable yet in Swift, don't worry because no code I show will be all that complicated. After all, I'm just a manager. It is important to note -- [Laughter]
[Ali Ozer]
It is important to note that these APIs are all available in Objective-C and Swift. So we're not showing you anything that works only for Objective-C or Swift. It is available for whatever language you're using. As you know, the new Force Touch trackpad brings pressure sensitivity as well as haptic feedback.
opening up interesting possibilities for applications. Let's look at some use cases. Here, for instance, by applying Force Click on some text, you can do lookup or you can automatically create a calendar event. In this case, by applying a pressure to the fast-forward button, you can cause the movie to fast-forward even faster.
Here you can apply pressure to draw thin or thick strokes when you're signing your name or doing drawing in markup. Finally, in this case, as you move objects around in a program like Xcode's Interface Builder or in a drawing program as objects go into alignment you will get haptic feedback.
Now some of the Force Touch APIs made an appearance in X v10.3, some of you may have seen those. First, we have accelerator controls APIs. These APIs interpret variable pressure and are useful for creating the likes of the fast-forward buttons or zoom buttons in an application like Maps.
You can set accelerator controls on NSButton in NSSegmentedControl. If you want to do more sophisticated things with pressure, we give you an event, a new event type for pressure with the corresponding methods on NSResponder and gesture recognizer as well, Pressure Change With event. You can interpreter pressure events yourself.
In X v11, we introduced several new classes. One is pressure configuration class. You set the pressure configuration of a view or gesture recognizer to indicate how the trackpad should react. In general, the haptic feedback provided to the user will be dependent on the pressure configuration you specified. We have two other classes, haptic feedback manager and alignment feedback filter, allowing you to customize the kind of haptic feedback you give to the user.
Many of you may have used spring loading. That's when you start a drag, and when you hover over a destination the destination opens up for you. You probably use this in Finder. With Force Click, we now have it such that you can also do spring loading immediately just by force clicking on the destination.
We have a new API for making spring loading even easier. This is just a simple Boolean property, spring loaded on NSButton and NSSegmentedControl, and the action will be sent on hover or on Force Click. Very straightforward. If this doesn't quite meet your needs, we have a new protocol, NSSpringLoadingDestination, which allows you to do spring loading on arbitrary destinations. For example, the Finder example would be appropriate for this.
Swipe to delete, you're familiar with this, you saw it yesterday likely in the keynote and you may be familiar with it from iOS, you can swipe left or right in a table view such as the messages list in Mail to mark messages as unread, or delete them, and so on. We now have API for this also in El Capitan.
It is a delegate method on NSTableView, Row Actions for Row. You simply return an array of NSTableView row action, and these instances of the class simply declares how the items, the row should be drawn and what should happen when the user selects that action via this block, this handler block at the end. I sort of breezed through the topics. There is a talk, Adopting New Rrackpad Features, Thursday morning at 10:00 a.m. that you can catch that will give you more detail on these topics.
Full screen, you heard about this yesterday. Full screen enables you to remove distractions and focus on one task, as you can see here. Now with split view full screen, you can focus on one task but possibily bring in another window. For instance, here you are using Xcode and you brought up Safari to look at some documentation or some forums. You can imagine bringing up messages next to Xcode because you want to chat with a buddy about a piece of code you're writing. This is called tiling, when the windows are brought into split view. Tiling is automatic for many windows.
Resizable windows are automatically eligible for tiling. This means your applications, the windows in your applications, will automatically be candidates for being tiled in full screen without any changes on your part. Whether they're full screen-capable or not already. However, there is API for opting windows in and out of tiling, and it's part of this NSWindow collection behavior options on NSWindow.
For instance, you may have a nonresizable window that you think should be tillable. You can use the Allowd Tiling option. Or you have an antisocial window that just doesn't want to be tiled. You can set Disallows Tiling. I don't know an example of that, but it is there.
These joined full screen primary settings that we had here already in X v7. It is important to note that the full-screen primary is the way that you specify a window should go into full screen. Note that this is still very much an opt-in setting because we want you to think about how your windows behave in the vast screen space of full screen, so that is still an opt-in thing where you think about how your window should act in full screen. That one you still opt into.
You can also set these of course in Xcode's attributes inspector as well, both the tiling and whether a window becomes full screen or not. I said that tiling is automatic for many windows, but AppKit does check to see, make sure that windows can coexist in the same screen.
Imagine you have a relatively small screen and two fairly large windows, when you try to tile them, if the windows cannot be resized small enough, AppKit will not allow them to be tiled. I want you to think about how your windows can resize small enough, how they can be flexible enough to fit into the smaller area of tiled split view. To help achieve this, we have some APIs.
For instance, split view item now has sidebar behavior, where the sidebar gets smaller and collapses and can be brought back up as an overlay, and also has proper vibrancy. NSStackView automatic detaching of hidden views allows you to create NSToolbar-like experiences for your custom views where the items, as they're dropped off the edge, can be put into a menu, and so on. And many more. You can hear about these in Improving the Full-Screen Window Experience, which is Thursday afternoon.
Auto Layout, as you know, this is very important, we have made some significant changes, significant improvements in Auto Layout as well. First is stack view. Stack view is a very important class. It should be the first-stop shop for your Auto Layout needs. If you can get done what you have to get done within a stack view rather than using constraints directly, do it. It is a high level of abstraction, very powerful.
First good news about stack view is it is now on iOS as well, as UI stack view, with equal pretty much APIs. This goes along with our constant attempt of bringing parity between our platforms, and this is one of those examples. Secondly, it is now even better than ever. I already mentioned the detaching functionality. There is also new options for view distribution with this property called distribution.
One value in here is gravity areas, which is the option you had in stack view from day one when we introduced it in X v9. We have added other settings, and rather than explaining these, I will show you a quick video. There are six stack views here configured with these settings. I will resize the window, larger, smaller, back larger again.
As you can see, you get some powerful functionality, such as ability to have equal sizes, equal spacing, and so on that hopefully will fit your needs. The stack views can be nested in arbitrary ways to give you powerful layouts. NSLayoutAnchor is a new class providing a concise representation of an edge or dimension. Let's say you have two views and you want to create a constraint between them.
This is code that you would have had to have write. With layout anchors, here is the code that you can write. Note that these two items here are basically layout anchors referring to those edges of those views, and this is not only shorter, sweeter, it is also giving you more compile time type-checking. It is great. [Applause]
[Ali Ozer]
NSLayoutGuide is another new class. If you ever find yourself doing this sort of stuff, creating dummy views to do things like equal spacing between views, you can now instead create layout guides. It's a lightweight object that takes the place of a view, but it is much lighter weight so it can participate in Auto Layout without creating views.
Collection view has been with us for a while. As you know, UICollectionView was also introduced a few releases ago. With X v11, we brought NSCollectionView to parity with the iOS version while still maintaining important features for the desktop, such as drag and drop and bulk selection. So here are some of the features in the new collection view.
Features such as heterogeneous items, optional grouping, customizable layout. Let me show you a quick video of a sample application here. There is a bunch of images being displayed. I will first group by group with headers and footers and use some of the custom layouts provided by the app. You see this app in action and learn about the features and how to apply them in your own applications in What's New in Collection View, that's Thursday afternoon at 4:30.
We have some great changes in text. First is the new system UI font. Here is what the new system font looks like, San Francisco. As you know, it is the same font on iOS and watchOS as well. This font is automatic for applications. When you run your application in X v11 on El Capitan, you will get this font. But it's possible that you are doing something that prevents this.
If you see this font, it was introduced in X v10, there is something going on, check it to see what you need to do to make sure you're using San Francisco. If you're using this font, this is one we introduced in X v0, more of that is going on. Finally, if you're using this font -- [Laughter]
[Ali Ozer]
You have a lot of work to do. Hang in there. This was the font we stopped using in Mac OS 9. Here are the APIs in NSFont that you can use to make sure you're using the latest system font, system font of size and so on. These fonts, these APIs, they have been with us for a long time. You can set the system fonts via the Xcode attributes inspector. Fairly straightforward There is a pop-up, you choose the appropriate system font for your application.
We do have new API for a system font at different weights. If your designers are asking you to use different weights, you can now do that with a system font with this API, system font of size and weight. There is nine different weights predefined, I'm showing you only three of them, ranging from ultralight to black. The regular setting is what you get by default for system font of size. We have another API, mono space system font of size weight. Let me show you why you need this.
If you call the system font of size API in an application that is linked against X v11 SDK and you draw some digits, here is what you see. Those of you with eagle eyes for fonts may note, wow, those digits are not fixed pitched, they're different widths. This is shocking because traditionally system fonts have always had digits that are the same width. That's to make sure that tabular data appears organized or UIs with changing numbers in text doesn't jiggle as the numbers are changing.
But now, if your app is linked against X v11 you will get this system font with the fonts. If you have to have fixed pitched fonts, that's when you use this API, this will give up digits that are equal widths. Typographically not as pleasing, but it will get the job done. The changes are drastic. Here is the proportional, and here is the fixed widths ones. It is a tool for you. You can hear more about this and more about the APIs in Introducing New System Fonts, which is Friday afternoon at 2:30.
I also mentioned new APIs, there is new APIs in the tech system. These bring new functionality and parity with TextKit and iOS, there is a lot of items here. I'm just going to cover two, three of them. First is exclusion paths. This is the ability to easily put paths so you can to wrap text around objects such as this butterfly, it is straightforward.
Another one is two properties on text field: maximum number of lines, which is great especially with Auto Layout, or allows default tightening for truncation, which allows you to specify if the contents of the text field should be tightened before it actually gets truncated. There was a way to control this, before but now it is controlled with this one Boolean property.
There are many more changes, these are some highlights. So last thing I want to talk about in the AppKit section is visual atomicity. You may wonder, what is visual atomicity? A mountain? What does it have to do with Half Dome? I'll show you a short clip demonstrating what I mean by visual atomicity or lack of visual atomicity.
You see the Open panel come up twice. First time, okay, not great. Second time, judge for yourself. Unless you blinked, you saw what I'm talking about. Let's show you in slow motion. Shadow. Parts of the panel. Rest of the panel. This is the Open panel running in Yosemite.
Open panel is a rough case because it is drawn by multiple processes, but that's not an excuse. A UI like this should appear to the user as coming up in one step, one frame, it shouldn't go through a few visual steps like that. That's what we mean by visual atomicity, achieving that one single-step drawing when needed. Those of you who had to [undecipherable] windows, views, also Core Animation layers explicitly, you know that achieving visual atomicity is not always that straightforward.
There are a number of APIs, you don't have to read through the list, there is no quiz. There are a number of APIs that do the job, but they don't necessarily work well together. In X v11, we fixed it up so that you can achieve visual atomicity with NSAnimationContext.
You can call Begin Grouping or End Grouping or its equivalent, Run Animation Group, around a bunch of independent drawing you're doing, such as you see here. This should give you visual atomicity. Beyond this, we discourage the use of Disable Screen Updates and Enable Screen Updates and Disable Screen Updates until Flush. They're not deprecated, but they are not recommended anymore and should not be necessary. With that, we can move on to Foundation. There is a lot of things to talk about in Foundation as well.
First one is undo manager. Those of you who used undo manager from Swift know that undo manager APIs is not a perfect fit in Swift. This is what the APIs look like. The first has a selector, and it only works in some cases. The second one has an indication.
NSIndication in Objective-C is of course awesome, but it doesn't know about all of the fancier types in Swift. So we're adding block-based undo. This is how it looks in Objective-C, and this is how it looks in Swift. As you will see, there is a target argument and also a block, which is basically the code to be executed to undo the action you just did.
Separate argument for the target means you don't have to reference the target in the block, which avoids retain cycles. And there is also a use of generic type in the Swift declaration, and I'll tell you how it works. Here is an example. You have a class named Colorful Shape, it's got a property named Color, we add a Did Set property observer to this property.
This is just one of the ways you can do undo, you can undo in other ways as well, but here we're doing it in the Did Set property. This is the call to register undo with target, and here is actually the code to be executed to undo the action that I might be doing. Note that thanks to the use of generics in the register undo at target, this all works and the target is automatically recognized as a colorful shape thanks to the reference to self there in the register undo column. You don't have to cast the target to colorful shape.
NSCoder now has error handling. Those of you who have used NSCoders like NSKeyedArchiver or so on, you know there is no error arguments to those things. We have added explicit error handling. Methods such as these, Decode Object for Key and Decode Object of Classes for Key, now have versions that actually return errors, throw errors in Swift.
They're named Decode Top Level Object for Key and Decode Top Level Object of Classes for Key. Note that they have throws declaration, which means that they return an error. And note that they return an optional object because a nil return is actually a valid return out of these, it just indicates that the object was not in the archive.
Note that these are named Decode Top Level Object for Key, and we intend for this to be used at the top levels when you're unarchiving your root objects. We don't intend these to be called in your implementations of [unintelligible] coder. Also note that these are not the only the two methods we have here; we have another two or three to go along with all of the decode object type methods we have currently.
NSError now has a value provider, let me model this. This is a simple way you may be creating an NSError object. It's pretty simple, straightforward, however, note that it's not user presentable. If this were ever to be shown to the user, this is what they'll see. Not good. This is really what you would like them to see if this was ever presented to the user. Even if you don't ever present this to the user, you know, in the debugger something like this would be helpful too, as opposed to getting error 42. So the code that you write for this looks like this.
So you specify the values for various keys, and if you want it to be user presentable you would also localize them. So you know, it is a bunch of code, you can create methods here forever. The code isn't the problem, writing code, it is our job, right, we're paid for it, that's not the problem. The problem is that all this is happening at the time that errors are being created even if the consumer of the error does nothing with the error. So it is, performance-wise, wasteful. So we've added this ability to create and return desired values on demand.
We have this method, set user info value provider for domain provider. You basically specify a domain you created for NSError in your application and provide a provider, which is a block that returns values for any keys missing in the user info dictionary. So it will be invoked on demand lazily.
You can go back to using this nice, shortened piece of code for generating errors, and the user information will be filled dynamically. You may be familiar with NSProgress. It is an object for reporting progress and it has a great feature where it will implicitly compose progress from across a hierarchy of operations and it will present that to the user as one single number. It is pretty good, but it is implicit. As being implicit, it has some issues that you may have run into. We're introducing an explicit mode for managing progress reporting.
This has two pieces: one is APIs to add and remove child progress objects directly to a hierarchy of progress objects and the second is this protocol which lets you declare the progress on an object directly. For instance, if you have a subclass of NSOperation, which does some one-shot operation, you know, it starts and ends, it is a good candidate for this progress property. It allows it to opt in to explicit progress reporting. NSProgress now also has the ability to resume. It had the ability to pause, we have added the second part. NSNotificationCenter now has the ability to automatically unregister the allocated observers. [Applause]
[Ali Ozer]
Here is the kind of code you would have had to have write to add yourself as an observer, and here is the code you write to remove yourself as an observer. You can call this code if you want to remove yourself as an observer. If you don't, and freed, you'll automatically be unregistered. That's pretty great.
So here is the class whose name Toby did not dare say yesterday in the State of the Union, NSFirstNameComponentsFormatter. The rule is, if it is not long enough to be wrapped on a slide title, it is not too long. So, NSFirstNameComponentsFomatter. It allows proper localized formatting of names.
This joins other formatters we have added over the last few years such as date components formatter, byte count formatter, length formatter, and so on. It also provides styles for a number of different forms. Let me give you a quick example. You create a person named Components Object, it has parts of name, you specify the parts of name you have, there is many more, let's say here we're specifying three of them.
Then you create a person in componenst formatter and ask for it to be formatted. Depending on the kind of style that you give, you get different forms of the name, like long, default, short, and so on. Note that if you ask for short, but in some other language, you may get a totally different form of the name depending on rules of localization for that language. Don't make assumptions about the kind of names you will get back from this API. The purpose of this API, one of the main purposes is to isolate you from complexities of writing world-ready applications. NSString has new APIs to help you write world-ready internationalizable applications.
There is facility for conditional quotation, whether a technical term, for instance, should be surrounded by quotes, for which rules change in different languages. Simpler localized case changing and searching APIs, transliteration APIs, which previously were in CFString, now they're in NSString, and also facilities for adaptive strings for UI presentation. You can provide multiple forms, multiple lengths of the string in your strings files and have the right one chosen depending on how much space you have in your UI to display it.
You can hear about the person name components formatter and all of these facilities and more in What's New in Internationalization, which is Friday morning at 9:00 a.m. Let me talk about thermal state. These are APIs introduced in X v10.3, which was the same time as our sexy new MacBook which, of course, as you may know doesn't have any fans and in fact is a good case study for this API.
Note that although this API was introduced at the same time, it works on our other machines and is generally available and functional. It's not just for the MacBook only. This API is captured with a property, a thermal state property on NSProcessInfo. It has four values: nominal, fair, serious, critical. There is a notification you can get whenever the value changes.
Note that serious, that's when the fans are going at maximum speed if your machine had fans, imagine what's happening if you don't have fans. Serious is typically when you want to take some action. For instance, let's say you're doing custom animation at 60 FIPS, this a time to think about reducing your animation to 30 FIPS. That's what NSScrollView will do for you automatically so you don't have to worry about NSScrollView case. Let's say you're using high-quality textures in the application and you get a serious thermal state, time to drop to maybe lower-quality textures.
This API is great for cases when you need it, but it is important to note that this API is reactive and not proactive. It is the kind of API where the system calls you to tell you of trouble and you have to take action, and, of course, the action you take is not adding more to the load on the system.
We have a lot of other APIs which are proactive that we have introduced over the last few releases. These are the kind of APIs where you tell the system about what you're doing, and the system optimizes your activities and tasks based on whatever happens to be going on.
For instance, tolerance on timers, process info activity APIs, doing downloads in the background with NSURLSession, setting quality service, so on. These APIs allow not only energy efficient behavior, but they also enable proper thermal behavior. They enable longer battery life and make your system coo, figuratively and literally as well.
Last, core data, quick mention here since I'm short on time. A lot of great features in core data, unique constraints and batch deletion and many other API enhancements, that's all I'll say. Of course, it wouldn't be a what's new talk if I don't leave a lot of things on the floor. These are many other topics I just didn't get around to, you can read about them hopefully in the release notes. This is not even including amazing new technologies such as Metal or GameplayKit as well.
In summary, we have a lot of general API improvements across the board for Swiftification. In addition, we have a lot of great features and enhancements. Look at the material, think about how to adopt them, and come see us at the labs if you have any questions. For more information, here are the pointers. The AppKit and Foundation release notes are available at developer.apple.com.osx. The release notes are for the seed, so it's a good source. Thank you for joining me today. Have a great rest of the conference. [Applause]