Happy WWDC 2017! Today we're beginning our look at the incredibly large list of updates and improvements announced this week with UIFontMetrics. Let's jump in.
We'll start with the problem we're trying to solve. It's all about Dynamic Type.
Our users can adjust their preferred Dynamic Type value in Settings.app to display the text in our apps larger and more prominently.
This works great when we want to use the system default font, since we can simply write some code like this:
There's always one more fun trick tucked away in UIFontMetrics, and that is scaling arbitrary values. This is great for helping us size our UI elements (for example buttons or headers) to accomodate dynamically sized fonts that live inside:
Today we'll continue looking at UICollectionView's more advanced capabilities by checking out a little-known feature hiding inside UICollectionViewController.
It allows us to automatically animate the transition between layouts when pushing on to a navigation controller stack. Neat!
Let's give it a try.
We'll start with the same simple baseline collection view controller we used in Bite #306, and Bite #307, SquaresViewController.
That's it. UIKit will notice that we've set our BigViewController's useLayoutToLayoutNavigationTransitions to true, and will automatically animate the transition between the two layouts.
Note that the automatic transition animation that UIKit renders is smart enough to make sure the selected cell is still visible after we push in. A nice touch.
First, the same UICollectionView is actually reused when all of this magic happens. The pushed on view controller will not create its own. This may or may not matter for any given app, but good to know.
Second, the root view controller (SmallViewController in our case) will still be set as the delegate and dataSource when the new view controller is pushed on.
If we needed to change this behavior, we could conform to the UINavigationControllerDelegate protocol and change these values each time a different view controller is about to be be shown. The code might look something like this:
We're welcoming back one of our favorite sponsors this week, it's PSPDFKit! PSPDFKit delivers an intuitive & seamless SDK for integrating PDF functionality into apps on iOS, Android, and the Web.
PDF files have been around a long time. Over that time they evolved to become an incredibly versatile and functional format. They're also wide-ranging in terms of how they're used. Comic books, Apartment leases, flight manuals, etc. All powered by PDFs.
Being able to take advantage of all this great functionality in our apps would be huge for our users.
With it, we can beautifully display PDFs, and allow our users to intuitively annotate documents, and much, much more.
Let's get started.
We'll head over to PSPDFKit's wonderful documentation area and follow the Getting Started steps to integrate the Framework directly, or through a system like CocoaPods.
Once we've got PSPDFKit in our app, we can start playing around.
PSPDFKit provides tons of great APIs for programmtically interacting with PDF files, as well as a bunch of polished, (and incredibly customizable) user interfaces to allow our users to read and manipulate PDF files themselves.
We create a new PSPDFDocument, then a new view controller to show it. We use PSPDFKit's awesome PSPDFConfiguration type to neatly build up our settings.
From here we can simply present it like any other view controller. Neat!
PSPDFKit stands out with an awesome, well thought-out API. It's clear that they care deeply about API design, and developer experience.
Before we go, let's try out another couple features. First up, Annotations:
// Create a new PSPDFDocumentletdocument=PSPDFDocument(url:documentURL)// Create a link annotation, and set its URLletlinkAnnotation=PSPDFLinkAnnotation(url:URL(string:"https://pspdfkit.com")!)
// Position the annotation in the documentletboundingBox=CGRect(x:200,y:400,width:50,height:300)linkAnnotation.boundingBox=boundingBox// Customize the link annotation's appearancePSPDFLinkAnnotationView.appearance().borderColor=.blue// Add the newly created annotation to the documentdocument.add([linkAnnotation])
Very cool, Next up, Forms. Our users can of course fill out any form fields in documents they open, but we can actually fill them out programmtically too:
Now we can toggle back and forth between our two layouts with a nice looking animation. Very cool.
It's super handy how the setCollectionViewLayoutfunction is smart enough to alter the animtion so the cell we selected is still in view once the animation completes.
We can see this effect exaggerated when we bump up the itemSize of our "big"layout:
One final note here: This just one approach. There are tons of different ways to achieve this (and similar) behavior. We'll take a look at more as we dive deeper into collection views in upcoming Bites.
Have a specific UICollectionView question you'd like answered? Send it along!.
UICollectionView has always been a powerhouse. Its variety and versatility are tough to understate.
We've covered it a bit here on LBOC, but we've still only just scratched the surface. Today we'll begin to dive deeper in what all it can do by customizing how new collection view cells animate when they're being inserted. Let's begin!
We'll start by creating a new single viewapp in Xcode.
We'll drag out a UICollectionViewController in Interface Builder, set its class to be the ViewController one that comes with the Xcode template, then update ViewController.swift to have some basics:
With this, we have a nice mostly-"boilerplate" setup. Just some square, randomly-colored, cells that fade in when they're inserted:
Not bad. Now let's customize the behavior of those cells as they're being inserted. For this, we'll need our own custom UICollectionViewLayout subclass.
Specifically we'll subclass UICollectionViewFlowLayout and override a few functions to customize the behavior of inserted cells.
What we've done here is to grab the layout attributes our collection view was going to use for the newly inserted item, and modify them slightly, before passing them along back to the system.
Here we've added a transform to scale the item down when it is first added, this will give us a nice "zoom up" effect as each item is added:
That looks neat, but let's try for something even funkier. We can change our transform line to:
The iPhone and iPad are awesome devices with beautiful displays. Sometimes though, we might want to show parts of our app on a bigger, externalscreen.
Today we'll look at how we can do just that on iOS, let's dive in.
Before we begin let's break down what exactly we're talking about here:
UIKit exposes any external display we connect to our iPhone or iPadwith an adapter as a UIScreen. The same is also true when we turn-on Airplay Mirroring to an Apple TV.
Now, let's write some code.
We'll eventually use Notifications to learn when a screen is connected/disconnected, but many users may launch our app with a screenalready connected, so let's start by checking for that.
We'll create a couple instance properties to hold our the UIWindow and UIViewController we'll be displaying externally:
We're welcoming back one of our favorite sponsors this week, it's Zendesk!
None of us have ever built a flawless app.
Chances are, no matter how good we think our app's user experience is, there's probably something users will need help with while they're in our app.
Yet in many apps, getting help is reduced to a "contact us" button that launches an compose email screen, or a just drops the user on a web page.
By forcing folks out of the app to get help, small problems can turn into big annoyances, and those will almost certainly turn into negative App Store reviews and poor ratings.
They offer a wealth of great functionality, but also a fair amount of complexity.
Often we don't need all that power. Perhaps we're adding sound effects or audio feedback to one of our user interfaces, or maybe we just need to loop some background music in the menu of our video game.
Today we'll check out a new library from Adam Cichy called SwiftySound that can help us simplify our audio playback code. Let's take a look.
We could pass in any Int here to loop the music, but we've passed -1 to indicate we want to loop forever.
One of the most useful features of SwiftySound is the inclusion of a UserDefaults-persisted flag for persisting the user's preference of sound playback being enabled or disabled.
We can use this on our app's Settings screen to allow users to easily enable/disable sound effects globally.
Sound.enabled=soundsSwitch.on
The value is then automatically persisted and respected across app launches. A nice touch by SwiftySound's author, Adam Cichy.
We're not required to use this singletonSound instance by the way, we can always create a Sound instance and pass it around:
It's a cousin to UIImagePickerViewController that exposes just the basic video editing functionality from that class in a standalone, dedicated video editing view controller.
We'll download the video, rename it to something simple, and drag it into Xcode. We'll check the box next to our app in the dialog that appears, so it gets copied to our app target.
Here we've told it our path, and given it a 10 second max duration. (Pro Tip: Default is 10 minutes, set to 0 for no max).
From here we can simply present it like any other view controller:
present(editor,animated:true,completion:nil)
Neat!
The best part is all the functionality is self-contained inside the view controller.
The user can scrub through:
Trim the edges:
Then save the video back to the videoPath we set earlier:
Note:The documentation mentions UIVideoEditorController"only supporting Portrait"orientations, but it seems to work fine in all orientations.
Last but not least, we can (optionally) set a delegate on our UIVideoEditorController to get notified when the user saves or cancels (or a save fails):
This week, we're welcoming back an awesome sponsor to LBOC, it's PSPDFKit! PSPDFKit delivers an intuitive & seamless SDK for integrating PDF functionality into apps on iOS, Android, and the Web.
PDF files have been around a long time. Over that time they evolved to become an incredibly versatile and functional format. They're also wide-ranging in terms of how they're used. Comic books, Apartment leases, flight manuals, etc. All powered by PDFs.
Being able to take advantage of all this great functionality in our apps would be huge for our users.
With it, we can beautifully display PDFs, and allow our users to intuitively annotate documents, and much, much more.
Let's get started.
We'll head over to PSPDFKit's wonderful documentation area and follow the Getting Started steps to integrate the Framework directly, or through a system like CocoaPods.
Once we've got PSPDFKit in our app, we can start playing around.
PSPDFKit provides tons of great APIs for programmtically interacting with PDF files, as well as a bunch of polished, (and incredibly customizable) user interfaces to allow our users to read and manipulate PDF files themselves.
We create a new PSPDFDocument, then a new view controller to show it. We use PSPDFKit's awesome PSPDFConfiguration type to neatly build up our settings.
From here we can simply present it like any other view controller. Neat!
PSPDFKit stands out with an awesome, well thought-out API. It's clear that they care deeply about API design, and developer experience.
Before we go, let's try out another couple features. First up, Annotations:
// Create a new PSPDFDocumentletdocument=PSPDFDocument(url:documentURL)// Create a link annotation, and set its URLletlinkAnnotation=PSPDFLinkAnnotation(url:URL(string:"https://pspdfkit.com")!)// Position the annotation in the documentletboundingBox=CGRect(x:200,y:400,width:50,height:300)linkAnnotation.boundingBox=boundingBox// Customize the link annotation's appearancePSPDFLinkAnnotationView.appearance().borderColor=.blue// Add the newly created annotation to the documentdocument.add([linkAnnotation])
Very cool, Next up, Forms. Our users can of course fill out any form fields in documents they open, but we can actually fill them out programmtically too: