Learn how to work with labels in SpriteKit.
The post Video Tutorial: Beginning SpriteKit Part 9: Labels appeared first on Ray Wenderlich.
Learn how to work with labels in SpriteKit.
The post Video Tutorial: Beginning SpriteKit Part 9: Labels appeared first on Ray Wenderlich.
Learn how to port Zombie Conga to the Apple TV.
The post Video Tutorial: Beginning SpriteKit Part 10: tvOS and the Apple TV appeared first on Ray Wenderlich.
Review what you learned in our Beginning SpriteKit video tutorial series and find out where to go from here.
The post Video Tutorial: Beginning SpriteKit Part 11: Conclusion appeared first on Ray Wenderlich.
View next video: Getting Started
The post Video Tutorial: Beginning Realm on iOS: Series Introduction appeared first on Ray Wenderlich.
Your challenge is to give more substance to your model class by adding convenience initializer and some dynamic properties. See the Challenge PDF in the resources link below for full details.
View previous video: Introduction
The post Video Tutorial: Beginning Realm on iOS Part 1: Getting Started appeared first on Ray Wenderlich.
About six months ago, the author of the iOS Apprentice, Matthijs Hollemans, started an open source project to implement popular algorithms and data structures in Swift: the Swift Algorithm Club.
At first, it was only Matthijs at the helm. But the popularity of the repository grew, and currently it boasts 37 unique contributors and over 5,000 stars, proving to be one of the most popular Swift repositories on GitHub.
Today marks a new chapter of the club’s life. Matthijs and I are pleased to announce that the Swift Algorithm Club is now an official project sponsored by raywenderlich.com!
Specifically, raywenderlich.com team members Chris Pilcher and Kelvin Lau (yours truly!) will be leading the effort to maintain the repository, expand the Swift Algorithm Club even further, and post about Swift algorithm topics regularly here on the site.
Keep reading to find out more what the Swift Algorithm Club is, how you can use it to learn, and how you can contribute!
As a Swift developer, you have access to a plethora of methods in the Swift standard library that implement handy algorithms, like sort()
for example.
But sometimes you need a custom algorithm that goes beyond what the standard library provides. A good developer not only recognizes what a piece of software does, but also how the software accomplishes the task.
That’s where the Swift Algorithm Club comes in. It’s a free, open source collection of implementations of popular algorithms and data structures in Swift, with detailed explanations of how they work.
If you’re a computer science student who needs to learn this stuff for exams — or if you’re a self-taught programmer who wants to brush up on the theory behind your craft — this is for you!
The goal of this project is to explain how algorithms work. The focus is on clarity and readability of the code, not on making a reusable library that you can drop into your own projects. That said, most of the code should be ready for production use but you may need to tweak it to fit into your own codebase.
Now that the Swift Algorithm club is an official part of raywenderlich.com, Chris and I will be publishing monthly articles about the Swift Algorithm Club right here on this site.
As a sneak peek of what’s coming and to get an idea of what the Swift Algorithm Club is all about, here’s an example algorithm that most coders should be familiar with: Linear Search.
The goal of the linear search algorithm is to find a particular value in an array.
Given an array of generic objects, you iterate through the array and compare each object to the object you’re looking for. If the two objects are equal, stop and return the current index. If not, continue to look for the next object as long as there are objects left to compare.
Take the example of an array of numbers: [5, 2, 4, 7]
. You’d like to check if the array contains the number 2
.
You start by comparing the first number in the array —5
— to the number you’re looking for — 2
. They aren’t equivalent, so you continue to the next array element.
You compare the number 2
from the array to our number 2
and — hey! — they’re equal. You can stop iterating and return 1
, which is the index of the number 2
in the array.
Here’s a simple implementation of linear search in Swift:
func linearSearch<T: Equatable>(array: [T], _ object: T) -> Int? { for (index, obj) in array.enumerate() where obj == object { return index } return nil } |
Credit: Patrick Balestra.
Put this code in a playground and test it like so:
let array = [5, 2, 4, 7] linearSearch(array, 2) // This will return 1 |
Linear search runs at O(n); it compares the object you’re looking for with each object in the array. Therefore, the time it takes is directly proportional to the length of the array. In the worst case, you’ll need to look at all elements in the array.
The best-case performance is O(1), but this is pretty rare; in a randomly assigned array, the odds of this are 1:n since the object you’re looking for has to be positioned in the first array index. On average, linear search needs to look at half the objects in the array.
If you’re not familiar with Big O notation, check out our short guide to it here. For more information on this algorithm, check out Linear search on Wikipedia.
That concludes a quick example of the type of thing that’s in the Swift Algorithm Club. Now, let’s take a quick look at how the repository is structured.
The resources in the Swift Algorithm Club repository generally follow a particular pattern, which we’ve found to be essential for capturing the essential information of an algorithm:
The combination of theory, example, code, and performance gives the reader the best opportunity to learn about the algorithm — and how to best apply it to their situation.
Now let’s take a look at how you can enjoy the Swift Algorithm club – both as a learner and as a contributor.
If learning about algorithms like this sounds fun, just check out the official Swift Algorithm Club repository.
It’s a great learning resource for both beginning students and algorithm veterans. Beyond just algorithms, there’s also a new section on popular interview questions — great for priming yourself for your next interview!
Here’s a recommended list of data structures and algorithms to get started with:
Once you’re done with those, feel free to explore the rest of the repository. One thing is for certain — the repository will only continue to grow!
Contributing to open source projects is a great learning experience and a great way to give back to the community. And we could definitely use a lot of help on the Swift Algorithm Club, so why not join us? :]
We’re currently looking for contributors to the club for the following tasks:
For more details, please check out our comprehensive guide for contributors and see how you can help.
No matter how long you’ve been writing code, it’s likely there’s something you can learn from digging into the deeper details of structures and algorithms. We’re excited to help provide this information to Swift community.
Our focus is to lay the groundwork for the standard data structures and algorithms you’d encounter in computer science courses. We’d like to expand our interview questions section to encompass as many brain twisting complex algorithms as we can.
Whether you’re a beginning learner or a seasoned algorithm wrangler, there are lots of ways you can contribute:
Chris and I are excited to see how the Swift Algorithm Club evolves. Your first step (Yes! Go do it right now!) is to check out the Swift Algorithm Club repository and start reading.
Any questions or comments? Join the discussion on the forum — or come see us on GitHub!
The post Join the Swift Algorithm Club! appeared first on Ray Wenderlich.
Have you ever wanted to share a chunk of code between two or more of your apps, or wanted to share a part of your program with other developers?
Maybe you wanted to modularize your code similarly to how the iOS SDK separates its API by functionality, or perhaps you want to distribute your code in the same way as popular 3rd parties do.
In this iOS frameworks tutorial you’ll learn how to do all of the above!
In iOS 8 and Xcode 6, Apple provided a new template, Cocoa Touch Framework. As you’ll see, it makes creating custom frameworks much easier than before.
Frameworks have three major purposes:
You can share your framework with your other apps, team members, or the iOS community. When combined with Swift’s access control, frameworks help define strong, testable interfaces between code modules.
In Swift parlance, a module is a compiled group of code that is distributed together. A framework is one type of module, and an app is another example.
In this iOS frameworks tutorial, you’ll extract a piece of an existing app and set it free, and by doing so, you’ll learn the ins and outs of frameworks by:
By the time you’re done, the app will behave exactly as it did before, but it will use the portable framework you developed! :]
Download the starter project.
Phonercise is a simple application that replicates the Apple Watch Activity app, except it measures your phone’s physical activity. The three rings on the main view represent movement, standing and exercise.
To get the most out of the project, you’ll need to build and run on an actual iOS device, and turn on the volume. Go ahead now, build and run!
Move the phone around to get credit for movement, and “exercise” the phone by shaking it vigorously — that’ll get its heartrate up. To get credit for standing up, just hold the phone upright.
The logic for the app is pretty simple:
The ring controls are pretty sweet. They’ve got an addictive quality and they’re easy to understand. Wouldn’t it be nice to use them in a number of applications beyond this fun, but completely silly app? Frameworks to the rescue!
Frameworks are self-contained, reusable chunks of code and resources that you can import into any number of apps and even share across iOS, tvOS, watchOS, and macOS apps.
If you’ve programmed in other languages, you may have heard of node modules, packages, gems, jars, etc. Frameworks are the Xcode version of these. Some examples of common frameworks in the iOS SDK are: Foundation
, UIKit
, AVFoundation
, CloudKit
, etc.
In Xcode 6, Apple introduced the Cocoa Touch Framework template along with access control, so creating frameworks has never been easier. The first thing to do is to create the project for the framework.
ThreeRingControl
. Use your own Organization Name
and Organization Identifier
. Check Include Unit Tests. That’s right! You’re going to have automated tests ensure your framework is bug free.
Phonercise
project.
Now you have a project (albeit a boring one) that creates a framework!
Your current state is a framework without code, and that is about as appealing as straight chocolate without sugar. In this section, you’ll put the pod in CocoaPods by adding the existing files to the framework.
From the Phonercise source directory, drag the following eight files into the ThreeRingControl project in Xcode:
Make sure to check Copy items if needed, so that the files actually copy into the new project instead of just adding a reference. Frameworks need their own code, not references, to be independent.
Double-check that each of the files has Target Membership in ThreeRingControl to make sure they appear in the final framework. You can see this in the File Inspector for each file.
Build the framework project to make sure that you get Build Succeeded
with no build warnings or errors.
Close the ThreeRingControl project, and go back to the Phonercise project. Delete the six files under the Three Ring View group as well as the two MP3 files in Helper Files. Select Move to Trash in the confirmation dialog.
Build the project, and you’ll see several predictable errors where Xcode complains about not knowing what the heck a ThreeRingView
is. Well, you’ll actually see messages along the lines of “Use of undeclared type 'ThreeRingView'
“, among others.
Adding the Three Ring Control framework project to the workspace is the solution to these problems.
Right-click on the root Phonercise node in the project navigator. Click Add Files to “Phonercise”. In the file chooser, navigate to and select ThreeRingControl.xcodeproj. This will add ThreeRingControl.xcodeproj as a sub-project.
Note: It isn’t strictly necessary to add the framework project to the app project; you could just add the ThreeRingControl.framework
output.
However, combining the projects makes it easier to develop both the framework and app simultaneously. Any changes you make to the framework project are automatically propagated up to the app. It also makes it easier for Xcode to resolve the paths and know when to rebuild the project.
Even though the two projects are now together in the workspace, Phonercise still doesn’t get ThreeRingControl. It’s like they’re sitting in the same room, but Phonercise can’t see the new framework.
Try linking the framework to the app’s target to fix this problem. First, expand the ThreeRingControl project to see the Products folder, and then look for for ThreeRingControl.framework
beneath it. This file is the output of the framework project that packages up the binary code, headers, resources and metadata.
Select the top level Phonercise node to open the project editor. Click the Phonercise target, and then go to the General tab.
Scroll down to the Embedded Binaries section. Drag ThreeRingControl.framework
from the Products folder of ThreeRingControl.xcodeproj onto this section.
You just added an entry for the framework in both Embedded Binaries and Linked Frameworks and Binaries.
Now the app knows about the framework and where to find it, so that should be enough, right?
Build the Phonercise project. More of the same errors.
Your problem is that although the framework is part of the project, the project’s code doesn’t know about it — out of sight, out of mind.
Go to ActionViewController.swift, and add the following line to the list of imports at the top of the file.
import ThreeRingControl |
It’s critical, but this inclusion won’t fix the build errors. This is because Swift uses access control to let you determine whether constructs are visible to other files or modules.
By default, Swift makes everything internal
or visible only within its own module.
To restore functionality to the app, you have to update the access control on two Phonercise classes.
Although it’s a bit tedious, the process of updating access control improves modularity by hiding code not meant to appear outside the framework. You do this by leaving certain functions with no access modifier, or by explicitly declaring them internal
.
Swift has three levels of access control. Use the following rules of thumb when creating your own frameworks:
Ultimately, making frameworks is so much easier than in the past, thanks to the new Cocoa Touch Framework template. Apple provided both of these in Xcode 6 and iOS 8.
When ThreeRingView.swift was part of the Phonercise app, internal access wasn’t a problem. Now that it’s in a separate module, it must be made public
for the app to use it. The same is true of the code in Fanfare.swift.
Open ThreeRingView.swift inside of ThreeRingControlProject
.
Make the class public by adding the public
keyword to the class definition, like so:
public class ThreeRingView : UIView { |
ThreeRingView
will now be visible to any app file that imports the ThreeRingControl
framework.
Add the public
keyword to:
init
functionsRingCompletedNotification
, AllRingsCompletedNotification
, layoutSubviews()
@IBInspectable
— there will be nine of theseNote: You might wonder why you have to declare inits
as public. Apple explains this and other finer points of access control in their Access Control Documentation.
The next step is to do essentially the same thing as you did for ThreeRingView.swift, and add the public
keyword to the appropriate parts of Fanfare.swift. For your convenience, this is already done.
Note that the following variables are public: ringSound
, allRingSound
, and sharedInstance
. The function playSoundsWhenReady()
is public as well.
Now build and run. The good news is that the errors are gone, and the bad news is that you’ve got a big, white square. Not a ring in sight. Oh no! What’s going on?
When using storyboards, references to custom classes need to have both the class name and module set in the Identity Inspector. At the time of this storyboard’s creation, ThreeRingView
was in the app’s module, but now it’s in the framework.
Update the storyboard, as explained below, by telling it where to find the custom view; this will get rid of the white square.
ThreeRingControl
.Once you set the module, Interface Builder should update and show the control in the editor area.
Build and run. Now you’ll get some rings.
There’s one final place to update before you can actually use the framework. It’s the oft-forgotten test suite. :]
This app includes unit tests. However, the tests have a dependency on ThreeRingControl
, so you need to fix that.
Note: Before Swift 2.0, unit testing was difficult, but Swift 2.0 came along with @testable
, making testing far easier. It means you no longer have to make all your project’s items public just to be able to test them.
Simply import the module you want to test using the @testable
keyword, and your test target will have access to all internal routines in the imported module.
The first test is ThreeRingTest.swift, which tests functionality within ThreeRingView.swift and should be part of the ThreeRingControl framework.
From the PhonerciseTests group in the app project, drag ThreeRingTest.swift to the ThreeRingControlTests group in the framework project.
Select Copy items if needed, and make sure you select the ThreeRingControlTests target and not the framework target.
Then delete the ThreeRingTest.swift from the app project. Move it to the trash.
Open the copied test file, and change the import line from:
@testable import Phonercise |
To:
import ThreeRingControl |
Click the run test button in the editor’s gutter, and you’ll see a green checkmark showing that the test succeeded.
This test doesn’t need @testable
in its import since it is only calling public
methods and variables.
The remaining app test doesn’t work this way though. Go back the to the Phonercise target and open PhonerciseTests.swift.
Add the following import to the existing imports at the top:
import ThreeRingControl |
Now run the PhonerciseTests tests. The particular test should execute and pass.
Congratulations. You now have a working stand-alone framework and an app that uses it!
CocoaPods is a popular dependency manager for iOS projects. It’s a tool for managing and versioning dependencies. Similar to a framework, a CocoaPod, or ‘pod’ for short, contains code, resources, etc., as well as metadata, dependencies, and set up for libraries. In fact, CocoaPods are built as frameworks that are included in the main app.
Anyone can contribute libraries and frameworks to the public repository, which is open to other iOS app developers. Almost all of the popular third-party frameworks, such as Alamofire, React native and SDWebImage, distribute their code as a pod.
Here’s why you should care: by making a framework into a pod, you give yourself a mechanism for distributing the code, resolving the dependencies, including and building the framework source, and easily sharing it with your organization or the wider development community.
Perform the following steps to remove the current link to ThreeRingControl
.
ThreeRingControl.xcodeproj
in the project navigator and delete it.If you’ve never used CocoaPods before, you’ll need to follow a brief installation process before going any further. Go to the CocoaPods Installation Guide and come back here when you’re finished. Don’t worry, we’ll wait!
Open Terminal in the ThreeRingControl
directory.
Run the following command:
pod spec create ThreeRingControl |
This creates the file ThreeRingControl.podspec in the current directory. It’s a template that describes the pod and how to build it. Open it in a text editor.
The template contains plenty of comment descriptions and suggestions for the commonly used settings.
Spec Metadata
section with:
s.name = "ThreeRingControl" s.version = "1.0.0" s.summary = "A three-ring control like the Activity status bars" s.description = "The three-ring is a completely customizable widget that can be used in any iOS app. It also plays a little victory fanfare." s.homepage = "http://raywenderlich.com" |
Normally, the description would be a little more descriptive, and the homepage would point to a project page for the framework.
Spec License
section with the below code, as this iOS frameworks tutorial code uses an MIT License:
s.license = "MIT" |
Author Metadata
section as is, or set it u with how you’d lke to be credited and contacted.Platform Specifics
section with the below code, because this is an iOS-only framework.:
s.platform = :ios, "9.0" |
Source Location
, but keep the stub git
link for s.source
. When you’re ready to share the pod, this will be a link to the GitHub repository and the commit tag for this version.Source Code
section with:
s.source_files = "ThreeRingControl", "ThreeRingControl/**/*.{h,m,swift}" |
Resources
section with:
s.resources = "ThreeRingControl/*.mp3" |
This will include the audio resources into the pod’s framework bundle.
Project Linking
and Project Settings
sections. #
.You now have a workable development Podspec.
Note: If you run pod spec lint
to verify the Podspec
in Terminal, it’ll show an error because the source
was not set to a valid URL. If you push the project to GitHub and fix that link, it will pass. However, having the linter pass is not necessary for local pod development. The Publish the Pod section below covers this.
At this point, you’ve got a pod ready to rock and roll. Test it out by implementing it in the Phonercise app.
Back in Terminal, navigate up to the Phonercise
directory, and then run the following command:
pod init |
This steathily creates a new file named Podfile that lists all pods that the app uses, along with their versions and optional configuration information.
Open Podfile in a text editor.
As suggested by the Podfile comments, uncomment the use_frameworks!
line to have the pod build as an iOS framework.
Next, add the following line between target 'Phonercise' do
and end
:
pod 'ThreeRingControl', :path => '../ThreeRingControl' |
Save the file.
Run this in Terminal:
pod install |
With this command, you’re searching the CocoaPods repository and downloading any new or updated pods that match the Podfile criteria. It also resolves any dependencies, updates the Xcode project files so it knows how to build and link the pods, and performs any other required configuration.
Finally, it creates a Phonercise.xcworkspace file. Use this file from now on — instead of the xcodeproj
— because it has the reference to the Pods project and the app project.
Close the Phonercise
and ThreeRingControl
projects if they are open, and then open Phonercise.xcworkspace.
Build and run. Like magic, the app should work exactly the same before. This ease of use is brought to you by these two facts:
ThreeRingControl
files and use them as a framework, e.g. adding import statements.Take a look at the Pods
project, and you’ll notice two targets:
Pods-Phonercise
.Inside the project organizer, you’ll see several groups. ThreeRingControl
is under Development Pods
. This is a development pod because you defined the pod with :path
link in the app’s Podfile. These files are symlinked, so you can edit and develop this code side-by-side with the main app code.
Pods that come from a repository, such as those from a third party, are copied into the Pods
directory and listed in a Pods
group. Any modifications you make are not pushed to the repository and are overwritten whenever you update the pods.
Congratulations! You’ve now created and deployed a CocoaPod — and you’re probably thinking about what to pack into a pod first.
You’re welcome to stop here, congratulate yourself and move on to Where to Go From Here, but if you do, you’ll miss out on learning an advanced maneuver.
This section walks you through the natural next step of publishing the pod to GitHub and using it like a third party framework.
If you don’t already have a GitHub account, create one.
Now create a new repository to host the pod. ThreeRingControl is the obvious best fit for the name, but you can name it whatever you want. Be sure to select Swift as the .gitignore
language and MIT as the license.
Click Create Repository. From the dashboard page that follows, copy the HTTPS
link.
Go back to Terminal and create a new directory. The following commands will create a repo
directory from the project’s folder.
mkdir repo cd repo |
From there, clone the GitHub repository. Replace the URL
below with the HTTPS
link from the GitHub page.
git clone URL |
This will set up a Git folder and go on to copy the pre-created README and LICENSE files.
Next, copy the files from the previous ThreeRingControl directory to the repo/ThreeRingControl directory.
Open the copied version of ThreeRingControl.podspec, and update the s.source
line to:
s.source = { :git => "URL", :tag => "1.0.0" } |
Set the URL
to be the link to your repository.
Now it gets real. In this step, you’ll commit and push the code to GitHub. Your little pod is about to enter the big kid’s pool.
Run the following commands in Terminal to commit those files to the repository and push them back to the server.
cd ThreeRingControl/ git add . git commit -m "initial commit" git push |
Visit the GitHub page and refresh it to see all the files.
You need to tag the repository so it matches the Podspec. Run this command to set the tags:
git tag 1.0.0 git push --tags |
Check your handiwork by running:
pod spec lint |
The response you’re looking for is ThreeRingControl.podspec passed validation.
Change the Podfile in the Phonercise
directory. Replace the existing ThreeRingControl
line with:
pod 'ThreeRingControl', :git => 'URL', :tag => '1.0.0' |
Replace URL
with your GitHub link.
From Terminal, run this in the Phonercise directory:
pod update |
Now the code will pull the framework from the GitHub repository, and it is no longer be a development pod!
In this iOS frameworks tutorial, you’ve made a framework from scratch that contains code and resources, you’ve reimported that framework back into your app, and even turned it into a CocoaPod. Nice work!
You can download the final project here. It doesn’t include the “advanced maneuver” steps, as the steps to set up a GitHub repository depends on your personal account information.
Hats off to Sam Davies for developing the ThreeRingControl
. You might remember him from such videos as Introducing Custom Controls, where you can learn more about custom controls and custom frameworks.
The team here has put together a lot of tutorials about CocoaPods, and now that you’ve gone through a crash course, you’re ready to learn more. Here are a couple that you might like:
Spend some time at CocoaPods.org and be sure to check out how to submit to the public pod repository and the dozens of configuration flags.
What did you learn from this? Any lingering questions? Want to share something that happened along the way? Let’s talk about it in the forums. See you there!
The post Creating and Distributing iOS Frameworks appeared first on Ray Wenderlich.
Your challenge is to polish up the table view and add a whole new Realm model class. See the Challenge PDF in the resources link below for full details.
View previous video: Getting Started
The post Video Tutorial: Beginning Realm on iOS Part 2: Storing and Retrieving Objects appeared first on Ray Wenderlich.
Your challenge is to add a gesture to modify a task row. See the Challenge PDF in the resources link below for full details.
View previous video: Storing and Retrieving Objects
The post Video Tutorial: Beginning Realm on iOS Part 3: Updating Objects appeared first on Ray Wenderlich.
Join Mic, Jake, and Andrew as they kick of the new season with a deep-dive into OS X development, the similarities between OS X and iOS, and how easy it is to share code between the two. After that, Jake talks about some big changes he’s made recently and the positive impact they’ve had on his remote working habits.
[Subscribe in iTunes] [RSS Feed]
This episode was brought to you by the incredibly kind folks over at Hired.
Hired is the platform for the best iOS developer jobs.
Candidates registered with Hired receive an average of 5 offers on the platform, all from a single application. Companies looking to hire include Facebook, Uber and Stripe.
With Hired, you get job offers and salary and/or equity before you interview, so you don’t have to waste your time interviewing for jobs you might not end up wanting, and it’s totally free to use!
Plus you, our loyal audience, will receive a $2000 bonus from Hired if you find a job through the platform, just for signing up using the show’s exclusive link: hired.com/ray
Interested in sponsoring a podcast episode? We sell ads via Syndicate Ads, check it out!
We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.
We’d love to hear what you think about the podcast, and any suggestions on what you’d like to hear in future episodes. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com.
The post Podcast: OS X Development, and Remote Working Habits appeared first on Ray Wenderlich.
You’ve seen a lot of apps that depict beautiful graphics and stylish custom views. The best of them make a lasting impression, and you always remember them because they are just so pretty.
Core Graphics is Apple’s 2D drawing engine, and is one of the coolest frameworks in OS X and iOS. It has capacity to draw anything you can imagine, from simple shapes and text to more complex visual effects that include shadows and gradients.
In this Core Graphics on OS X tutorial, you’ll build up an app named DiskInfo to create a custom view that displays the available space and file distribution of a hard drive. It’s a solid example of how you can use Core Graphics to make a dull, text-based interface beautiful:
Along the way you’ll discover how to:
In the first part of this Core Graphics on OS X tutorial, you’ll implement the bar chart using Core Graphics, before moving on to learn how to draw the pie chart using Cocoa Drawing.
So put on your painter’s hat and get ready to learn how to color your world.
First, download the starter project for DiskInfo here. Build and run it now.
The app lists all your hard drives, and when you click on one it shows detailed information.
Before going any further, have a look at the structure of the project to become familiar with the lay of the land:
How about a guided tour?
VolumeInfo
class, which reads the information from the hard drive, and the FilesDistribution
struct that handles the split between file typesNote: The app shows the correct disk usage information, but for the sake this tutorial, it creates a random file distribution.
Calculating the real file distribution each time you run the app will quickly become a time drain and spoil all your fun, and nobody wants that.
Your first to-do is to create a custom view named GraphView
. It’s where you’ll draw the pie and bar charts, so it’s pretty important.
You need to accomplish two objectives to create a custom view:
NSView
subclass.drawRect(_:)
and add some drawing code.
On a high level, it’s as easy as that. Follow the next steps to learn how to get there.
Select the Views group in the Project Navigator. Choose File \ New \ File… and select the OS X \ Source \ Cocoa Class file template.
Click Next, and in the ensuing screen, name the new class GraphView
. Make it a subclass of NSView
, and make sure that the language is Swift.
Click Next and Create to save your new file.
Open Main.storyboard, and go the the View Controller Scene. Drag a Custom View from the Objects Inspector into the custom view as shown:
Select that new custom view, and in the Identity Inspector, set the class name to GraphView
.
You need some constraints, so with the graph view selected, click on the Pin button in the Auto Layout toolbar. On the popup, set 0 for the Top, Bottom, Leading and Trailing constraints, and click the Add 4 Constraints button.
Click the triangular Resolve Auto Layout Issues button in the Auto Layout toolbar, and under the Selected Views section, click on Update Frames — should it show as disabled, click anywhere to deselect the new GraphView, and then re-select it.
Open GraphView.swift. You’ll see that Xcode created a default implementation of drawRect(_:)
. Replace the existing comment with the following, ensuring that you leave the call to the superclass method:
NSColor.whiteColor().setFill() NSRectFill(bounds) |
First you set the fill color to white, and then you call the NSRectFill
method to fill the view background with that color.
Build and run.
Your custom view’s background has changed from standard gray to white.
Yes, it’s that easy to create a custom drawn view.
Xcode 6 introduced an amazing feature: live rendering. It allows you to see how your custom view looks in Interface Builder — without the need to build and run.
To enable it, you just need to add the @IBDesignable
annotation to your class, and optionally, implement prepareForInterfaceBuilder()
to provide some sample data.
Open GraphView.swift and add this just before the class declaration:
@IBDesignable |
Now, you need to provide sample data. Add this inside the GraphView
class:
var fileDistribution: FilesDistribution? { didSet { needsDisplay = true } } override func prepareForInterfaceBuilder() { let used = Int64(100000000000) let available = used / 3 let filesBytes = used / 5 let distribution: [FileType] = [ .Apps(bytes: filesBytes / 2, percent: 0.1), .Photos(bytes: filesBytes, percent: 0.2), .Movies(bytes: filesBytes * 2, percent: 0.15), .Audio(bytes: filesBytes, percent: 0.18), .Other(bytes: filesBytes, percent: 0.2) ] fileDistribution = FilesDistribution(capacity: used + available, available: available, distribution: distribution) } |
This defines the property fileDistribution
that will store hard drive information. When the property changes, it sets the needsDisplay
property of the view to true to force the view to redraw its content.
Then it implements prepareForInterfaceBuilder()
to create a sample file distribution that Xcode will use to render the view.
Note: You can also change the visual attributes of your custom views in real time inside Interface Builder. You just need to add the @IBInspectable
annotation to a property.
Next up: make all the visual properties of the graph view inspectable. Add the following code inside the GraphView
implementation:
// 1 private struct Constants { static let barHeight: CGFloat = 30.0 static let barMinHeight: CGFloat = 20.0 static let barMaxHeight: CGFloat = 40.0 static let marginSize: CGFloat = 20.0 static let pieChartWidthPercentage: CGFloat = 1.0 / 3.0 static let pieChartBorderWidth: CGFloat = 1.0 static let pieChartMinRadius: CGFloat = 30.0 static let pieChartGradientAngle: CGFloat = 90.0 static let barChartCornerRadius: CGFloat = 4.0 static let barChartLegendSquareSize: CGFloat = 8.0 static let legendTextMargin: CGFloat = 5.0 } // 2 @IBInspectable var barHeight: CGFloat = Constants.barHeight { didSet { barHeight = max(min(barHeight, Constants.barMaxHeight), Constants.barMinHeight) } } @IBInspectable var pieChartUsedLineColor: NSColor = NSColor.pieChartUsedStrokeColor @IBInspectable var pieChartAvailableLineColor: NSColor = NSColor.pieChartAvailableStrokeColor @IBInspectable var pieChartAvailableFillColor: NSColor = NSColor.pieChartAvailableFillColor @IBInspectable var pieChartGradientStartColor: NSColor = NSColor.pieChartGradientStartColor @IBInspectable var pieChartGradientEndColor: NSColor = NSColor.pieChartGradientEndColor @IBInspectable var barChartAvailableLineColor: NSColor = NSColor.availableStrokeColor @IBInspectable var barChartAvailableFillColor: NSColor = NSColor.availableFillColor @IBInspectable var barChartAppsLineColor: NSColor = NSColor.appsStrokeColor @IBInspectable var barChartAppsFillColor: NSColor = NSColor.appsFillColor @IBInspectable var barChartMoviesLineColor: NSColor = NSColor.moviesStrokeColor @IBInspectable var barChartMoviesFillColor: NSColor = NSColor.moviesFillColor @IBInspectable var barChartPhotosLineColor: NSColor = NSColor.photosStrokeColor @IBInspectable var barChartPhotosFillColor: NSColor = NSColor.photosFillColor @IBInspectable var barChartAudioLineColor: NSColor = NSColor.audioStrokeColor @IBInspectable var barChartAudioFillColor: NSColor = NSColor.audioFillColor @IBInspectable var barChartOthersLineColor: NSColor = NSColor.othersStrokeColor @IBInspectable var barChartOthersFillColor: NSColor = NSColor.othersFillColor // 3 func colorsForFileType(fileType: FileType) -> (strokeColor: NSColor, fillColor: NSColor) { switch fileType { case .Audio(_, _): return (strokeColor: barChartAudioLineColor, fillColor: barChartAudioFillColor) case .Movies(_, _): return (strokeColor: barChartMoviesLineColor, fillColor: barChartMoviesFillColor) case .Photos(_, _): return (strokeColor: barChartPhotosLineColor, fillColor: barChartPhotosFillColor) case .Apps(_, _): return (strokeColor: barChartAppsLineColor, fillColor: barChartAppsFillColor) case .Other(_, _): return (strokeColor: barChartOthersLineColor, fillColor: barChartOthersFillColor) } } |
This is what the code above does:
Open Main.storyboard and have a look at the graph view. It’s now white instead of the default view color, meaning that live rendering is working. Have patience if it’s not there right away; it may take a second or two to render.
Select the graph view and open the Attributes Inspector. You’ll see all of the inspectable properties you’ve added.
From now on, you can choose to build and run the app to see the results, or just check it in Interface Builder.
Time to do some drawing.
When you use Core Graphics, you don’t draw directly into the view. You use a Graphics Context, and that’s where the system renders the drawing and displays it in the view.
Core Graphics uses a “painter’s model”, so when you draw into a context, think of it as if you were swooshing paint across a canvas. You lay down a path and fill it, and then lay down another path on top and fill it. You can’t change the pixels that have been laid down, but you can paint over them.
This concept is very important, because ordering affects the final result.
To draw a shape in Core Graphics, you need to define a path, represented in Core Graphics by the type CGPathRef
and its mutable representation CGMutablePathRef
. A path is simply a vectorial representation of a shape. It does not draw itself.
When your path is ready, you add it to the context, which uses the path information and drawing attributes to render the desired graphic.
A rounded rectangle is the basic shape of the bar chart, so start there.
Open GraphView.swift and add the following extension at the end of the file, outside of the class definition:
// MARK: - Drawing extension extension GraphView { func drawRoundedRect(rect: CGRect, inContext context: CGContextRef?, radius: CGFloat, borderColor: CGColorRef, fillColor: CGColorRef) { // 1 let path = CGPathCreateMutable() // 2 CGPathMoveToPoint(path, nil, CGRectGetMidX(rect), CGRectGetMinY(rect)) CGPathAddArcToPoint(path, nil, CGRectGetMaxX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMaxY(rect), radius) CGPathAddArcToPoint(path, nil, CGRectGetMaxX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMaxY(rect), radius) CGPathAddArcToPoint(path, nil, CGRectGetMinX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMinY(rect), radius) CGPathAddArcToPoint(path, nil, CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMinY(rect), radius) CGPathCloseSubpath(path) // 3 CGContextSetLineWidth(context, 1.0) CGContextSetFillColorWithColor(context, fillColor) CGContextSetStrokeColorWithColor(context, borderColor) // 4 CGContextAddPath(context, path) CGContextDrawPath(context, .FillStroke) } } |
TL/DR: That is how you draw a rectangle. Here’s a more comprehensive explanation:
CGPathAddArcToPoint
. This method draws the horizontal line and the rounded corner..FillStroke
parameter, which tells Core Graphics to fill the rectangle and draw the border.You’ll never look at a rectangle the same way! Here’s the humble result of all that code:
Note: For more information about how CGPathAddArcToPoint
works, check out Paths & Arcs in Apple’s Quartz 2D Programming Guide.
Drawing with Core Graphics is all about calculating the positions of the visual elements in your view. It’s important to plan where to locate the different elements and think through they should behave when the size of the view changes.
Here’s the layout for your custom view:
Open GraphView.swift and add this extension:
// MARK: - Calculations extension extension GraphView { // 1 func pieChartRectangle() -> CGRect { let width = bounds.size.width * Constants.pieChartWidthPercentage - 2 * Constants.marginSize let height = bounds.size.height - 2 * Constants.marginSize let diameter = max(min(width, height), Constants.pieChartMinRadius) let rect = CGRect(x: Constants.marginSize, y: CGRectGetMidY(bounds) - diameter / 2.0, width: diameter, height: diameter) return rect } // 2 func barChartRectangle() -> CGRect { let pieChartRect = pieChartRectangle() let width = bounds.size.width - CGRectGetMaxX(pieChartRect) - 2 * Constants.marginSize let rect = CGRect(x: CGRectGetMaxX(pieChartRect) + Constants.marginSize, y: CGRectGetMidY(pieChartRect) + Constants.marginSize, width: width, height: barHeight) return rect } // 3 func barChartLegendRectangle() -> CGRect { let barchartRect = barChartRectangle() let rect = CGRectOffset(barchartRect, 0.0, -(barchartRect.size.height + Constants.marginSize)) return rect } } |
The above code does all of these required calculations:
Time to draw it in your view. Add this method inside the GraphView
drawing extension:
func drawBarGraphInContext(context: CGContextRef?) { let barChartRect = barChartRectangle() drawRoundedRect(barChartRect, inContext: context, radius: Constants.barChartCornerRadius, borderColor: barChartAvailableLineColor.CGColor, fillColor: barChartAvailableFillColor.CGColor) } |
You’ve added a helper method that will draw the bar chart. It draws a rounded rectangle as a background, using the fill and stroke colors for the available space. You can find those colors in the NSColor+DiskInfo extension.
Replace all the code inside drawRect(_:)
with this:
super.drawRect(dirtyRect) let context = NSGraphicsContext.currentContext()?.CGContext drawBarGraphInContext(context) |
Here is where the actual drawing takes place. First, you get the view’s current graphics context by invoking NSGraphicsContext.currentContext()
, and then you call the method to draw the bar chart.
Build and run. You’ll see the bar chart in it’s proper position.
Now, open Main.storyboard and select the View Controller scene.
You’ll see this:
Interface Builder now renders the view in real time. You can also change the colors and the view responds to those changes. How awesome is that?
You’re at the part where you make the distribution chart, a bar chart that looks like this:
Take a step back here and dabble in a bit of theory. As you know, each file type has its own color, and somehow, the app needs to calculate each bar’s width based on the corresponding file type’s percentage, and then draw each type with a unique color.
You could create a special shape, such as a filled rectangle with two lines at bottom and top of the rectangle, and then draw it. However, there is another technique that will let you reuse your code and get the same result: clipping areas.
You can think of a clipping area as a sheet of paper with a hole cut out of it, which you place over your drawing: you can only see the part of the drawing which shows through the hole. This hole is known as the clipping mask, and is specified as a path within Core Graphics.
In the case of the bar chart, you can create an identical fully-filled bar for each filetype, and then use a clipping-mask to only display the correct proportion, as shown in the following diagram:
With an understanding of how clipping areas work, you’re ready to make this bar chart happen.
Before drawing, you need to set the value for fileDistribution
when a disk is selected. Open Main.storyboard and go to the View Controller scene to create an outlet.
Option-click on ViewController.swift in the Project Navigator to open it in the Assistant Editor, and Control-Drag from the graph view into the view controller class source code to create an outlet for it.
In the popup, name the outlet graphView
and click Connect.
Open ViewController.swift and add this code at the end of showVolumeInfo(_:)
:
graphView.fileDistribution = volume.fileDistribution |
This code sets the fileDistribution
value with the distribution of the selected disk.
Open GraphView.swift and add this code at the end of drawBarGraphInContext(_:)
to draw the bar chart:
// 1 if let fileTypes = fileDistribution?.distribution where fileDistribution?.capacity > 0 { var clipRect = barChartRect // 2 for (index, fileType) in fileTypes.enumerate() { // 3 let fileTypeInfo = fileType.fileTypeInfo let clipWidth = floor(barChartRect.width * CGFloat(fileTypeInfo.percent)) clipRect.size.width = clipWidth // 4 CGContextSaveGState(context) CGContextClipToRect(context, clipRect) let fileTypeColors = colorsForFileType(fileType) drawRoundedRect(barChartRect, inContext: context, radius: Constants.barChartCornerRadius, borderColor: fileTypeColors.strokeColor.CGColor, fillColor: fileTypeColors.fillColor.CGColor) CGContextRestoreGState(context) // 5 clipRect.origin.x = CGRectGetMaxX(clipRect) } } |
This is what the code above does:
fileDistribution
.
You might wonder why you need to save and restore the state of the context. Remember the painter’s model? Everything you add to the context stays there.
If you add multiple clipping areas, you are in fact creating a clipping area that acts as the unifying force for all of them. To avoid that, you save the state before adding the clipping area, and when you’ve used it, you restore the context to that state, disposing of that clipping area.
At this point, Xcode shows a warning because index
is never used. Don’t worry about it for now. You’ll fix it later on.
Build and run, or open Main.storyboard and check it out in Interface Builder.
It’s beginning to look functional. The bar chart is almost finished and you just need to add the legend.
Drawing a string in a custom view is super easy. You just need to create a dictionary with the string attributes — for instance the font, size, color, alignment — calculate the rectangle where it will be drawn, and invoke String
‘s method drawInRect(_:withAttributes:)
.
Open GraphView.swift and add the following property to the class:
private var bytesFormatter = NSByteCountFormatter() |
This creates an NSByteCountFormatter. It does all the heavy work of transforming bytes into a human-friendly string.
Now, add this inside drawBarGraphInContext(:_)
. Make sure you add it inside the for (index,fileType) in fileTypes.enumerate()
loop:
// 1 let legendRectWidth = (barChartRect.size.width / CGFloat(fileTypes.count)) let legendOriginX = barChartRect.origin.x + floor(CGFloat(index) * legendRectWidth) let legendOriginY = CGRectGetMinY(barChartRect) - 2 * Constants.marginSize let legendSquareRect = CGRect(x: legendOriginX, y: legendOriginY, width: Constants.barChartLegendSquareSize, height: Constants.barChartLegendSquareSize) let legendSquarePath = CGPathCreateMutable() CGPathAddRect(legendSquarePath, nil, legendSquareRect) CGContextAddPath(context, legendSquarePath) CGContextSetFillColorWithColor(context, fileTypeColors.fillColor.CGColor) CGContextSetStrokeColorWithColor(context, fileTypeColors.strokeColor.CGColor) CGContextDrawPath(context, .FillStroke) // 2 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineBreakMode = .ByTruncatingTail paragraphStyle.alignment = .Left let nameTextAttributes = [ NSFontAttributeName: NSFont.barChartLegendNameFont, NSParagraphStyleAttributeName: paragraphStyle] // 3 let nameTextSize = fileType.name.sizeWithAttributes(nameTextAttributes) let legendTextOriginX = CGRectGetMaxX(legendSquareRect) + Constants.legendTextMargin let legendTextOriginY = legendOriginY - 2 * Constants.pieChartBorderWidth let legendNameRect = CGRect(x: legendTextOriginX, y: legendTextOriginY, width: legendRectWidth - legendSquareRect.size.width - 2 * Constants.legendTextMargin, height: nameTextSize.height) // 4 fileType.name.drawInRect(legendNameRect, withAttributes: nameTextAttributes) // 5 let bytesText = bytesFormatter.stringFromByteCount(fileTypeInfo.bytes) let bytesTextAttributes = [ NSFontAttributeName: NSFont.barChartLegendSizeTextFont, NSParagraphStyleAttributeName: paragraphStyle, NSForegroundColorAttributeName: NSColor.secondaryLabelColor()] let bytesTextSize = bytesText.sizeWithAttributes(bytesTextAttributes) let bytesTextRect = CGRectOffset(legendNameRect, 0.0, -bytesTextSize.height) bytesText.drawInRect(bytesTextRect, withAttributes: bytesTextAttributes) |
That was quite a bit of code, but it’s easy to follow:
NSMutableParagraphStyle
. The paragraph defines how the string should be drawn inside the given rectangle. In this case, it’s left aligned with a truncated tail.drawInRect(_:withAttributes:)
.bytesFormatter
and create the attributes for the file size text. The main difference from the previous code is that this sets a different text color in the attributes dictionary via NSFontAttributeName
.Build and run, or open Main.storyboard, to see the results).
The bar chart is complete! You can resize the window to see how it adapts to the new size. Watch how the text properly truncates when there isn’t enough space to draw it.
Looking great so far!
OS X apps come with the option to use AppKit framework to draw instead. It provides a higher level of abstraction. It uses classes instead of C functions and includes helper methods that make it easier to perform common tasks. The concepts are equivalent in both frameworks, and Cocoa Drawing is very easy to adopt if you’re familiar with Core Graphics.
As it goes in Core Graphics, you need to create and draw paths, using NSBezierPath
, the equivalent of CGPathRef
in Cocoa Drawing:
This is how the pie chart will look:
You’ll draw it in three steps:
Open GraphView.swift and add this method into the drawing extension:
func drawPieChart() { guard let fileDistribution = fileDistribution else { return } // 1 let rect = pieChartRectangle() let circle = NSBezierPath(ovalInRect: rect) pieChartAvailableFillColor.setFill() pieChartAvailableLineColor.setStroke() circle.stroke() circle.fill() // 2 let path = NSBezierPath() let center = CGPoint(x: CGRectGetMidX(rect), y: CGRectGetMidY(rect)) let usedPercent = Double(fileDistribution.capacity - fileDistribution.available) / Double(fileDistribution.capacity) let endAngle = CGFloat(360 * usedPercent) let radius = rect.size.width / 2.0 path.moveToPoint(center) path.lineToPoint(CGPoint(x: CGRectGetMaxX(rect), y: center.y)) path.appendBezierPathWithArcWithCenter(center, radius: radius, startAngle: 0, endAngle: endAngle) path.closePath() // 3 pieChartUsedLineColor.setStroke() path.stroke() } |
There are a few things to go through here:
init(ovalInRect rect: _)
, set the fill and stroke color, and then draw the path.
stroke()
method.You may have noticed a couple of differences compared to Core Graphics:
Now, add the following code inside drawRect(_:)
to draw the pie chart:
drawPieChart() |
Looking good so far!
Cocoa Drawing uses NSGradient
to draw a gradient.
You need to draw the gradient inside the used space segment of the circle, and you already know how to do it.
How will you do it? Exactly, clipping areas!
You’ve already created a path to draw it, and you can use it as a clipping path before you draw the gradient.
Add this code at the end of drawPieChart()
:
if let gradient = NSGradient(startingColor: pieChartGradientStartColor, endingColor: pieChartGradientEndColor) { gradient.drawInBezierPath(path, angle: Constants.pieChartGradientAngle) } |
In the first line, you try to create a gradient with two colors. If this works, you call drawInBezierPath(_:angle:)
to draw it. Internally, this method sets the clipping path for you and draws the gradient inside it. How nice is that?
Build and run.
The custom view is looking better and better. There’s only one thing left to do: Draw the available and used space text strings inside the pie chart.
You already know how to do it. Are you up to the challenge? :]
This is what you need to do:
bytesFormatter
to get the text string for the available space (fileDistribution.available
property ) and full space (fileDistribution.capacity
property).NSFont.pieChartLegendFont
NSColor.pieChartUsedSpaceTextColor
NSColor.pieChartAvailableSpaceTextColor
Solution Inside: Draw Pie Chart Legend | SelectShow> | |
---|---|---|
Add this code inside the
This code does the following:
Now, build and run and see the final result of your handiwork.
|
You can download the completed project here.
This Core Graphics on OS X tutorial covered the basics of the different frameworks available to use for drawing custom views in OS X. You just covered:
You should now feel confident in your abilities to use Core Graphics and Cocoa Drawing next time you need clean, responsive graphics.
If you’re looking to learn more, consider the following resources:
If you have any questions or comments on this tutorial, feel free to join the discussion below in the forums! Thanks for joining me again!
The post Core Graphics on OS X Tutorial appeared first on Ray Wenderlich.
Your challenge is to bring to life a whole new view controller for the “My Tasks” tab. See the Challenge PDF in the resources link below for full details.
View previous video: Updating Objects
Additional resources: NSPredicate Cheatsheet
The post Video Tutorial: Beginning Realm on iOS Part 4: Collections appeared first on Ray Wenderlich.
Your challenge is to play with some more notifications to liven up the app UI. See the Challenge PDF in the resources link below for full details.
View previous video: Collections
The post Video Tutorial: Beginning Realm on iOS Part 5: Notifications appeared first on Ray Wenderlich.
View previous video: Notifications
Check out these additional resources to learn more:
The post Video Tutorial: Beginning Realm on iOS Part 6: Conclusion appeared first on Ray Wenderlich.
From May 18th to 20th, I was super lucky to have the opportunity to attend Google I/O.
This year was the 10th anniversary of Google’s annual conference, and it brought a change of venue: instead of the usual Moscone Center in San Francisco, it was outdoors at the Shoreline Amphitheatre right by the Google campus in Mountain View, CA.
The event certainly had a unique, more festival-like atmosphere at the outdoor venue than last year—as well as higher sunburn per capita. :]
But of course, it’s not all about the venue. A ton of Google I/O 2016 announcements and reveals aimed at us Android developers were at the heart of the conference. These announcements covered all sorts of areas of Android development from Android N to Android Studio to virtual reality to Firebase.
In this article, I will take you on a quick tour of the newest and shiniest of these announced Android goodies and let you know where you can get a closer look.
Here we go!
Let’s start with the basics: the SDK. During the I/O keynote, Google announced a new release of the newest version of the Android operations system: Android N Developer Preview 3!
A significant portion of the information presented on Android N included previously-announced features. However, DP3 also contains plenty of new features, APIs, and (of course) bug fixes. :]
One of these new APIs is the FrameMetricsListener API, which allows you to measure UI rendering performance at a per-frame granularity and collect data for a particular user interaction. While you could previously do this with adb shell dumpsys gfxinfo framestats
, the FrameMetricsListener API allows you to perform measurements from within the app and is not limited to the 120 frame limit of dumpsys
.
For anyone interested in developing virtual reality applications, DP3 introduces a new VR Mode that is specifically for high-quality VR apps and provides access to an exclusive VR-specific CPU, single buffer rendering (which speeds up display drawing), increased sensor performance, and stereo notifications. Overall, apps running in VR Mode should run with high-performance as well as reduced “motion-to-photon ratio” (the latency between user head movement and screen updates that can induce motion sickness).
In actuality, VR Mode is not just a new Android N feature. It is actually part of a new virtual reality platform that was one of the big keynote announcements.
This new VR platform powered by Android is called Daydream. While the previous Cardboard platform allowed any phone on Android 4.1 and above the ability to run VR experiences, Daydream focuses on bringing high-quality, next-level VR to users.
Daydream consists of both new software and new hardware components. On the software side is Android N’s VR Mode that tunes the platform for optimal rendering and interaction. On the hardware side is a VR headset reference design, a new controller, and “Daydream-ready” smartphone specifications.
The controller—which might remind some of you Nintendo fans of a Wiimote–is small but packed with several sensors providing users three degrees of freedom to move and gesture within VR apps. While the controller (and really any of the Daydream hardware) is not yet available, there is a controller emulator app available as part of the Daydream Development Kit.
The headset reference design outlines a headset geared towards long term use, though no concrete examples are available just yet. The high-end smartphone specifications follow the Daydream’s progression to more high-quality, high-performance VR experiences, but it is important to note that Google’s VR lead, Clay Bavor, states that most, if not all, of currently available smartphones are not “Daydream-ready”.
Daydream itself will be out Fall 2016. However, if you are itching to be part of those next-gen VR apps, you can get started with a Daydream Development Kit if you have a Nexus 6P, a second phone running KitKat or above, and a Google Cardboard (or other VR Viewer).
Fair warning: You will need to install DP3 on the Nexus 6P. Also (as hinted above) the 6P is not actually “Daydream-ready” and so you might experience throttled CPU and GPU performance depending on your app’s work load.
A big announcement for Android developers of the Wear variety is Android Wear 2.0, a huge update and re-work of many of the Wear foundations both from a developer and a user perspective.
The most significant change in Android Wear 2.0 is the introduction of standalone apps. Apps maintain full functionality even if a user’s phone is far away or is turned off, and they will have direct network access to the cloud. Rather than being embedded inside of phone apps, Wear apps will instead be delivered as independent APKs. This will allow developers to update Wear apps independently of the matching phone app. This new independence of Wear apps will also mean new ways for users to authenticate independently of a phone.
Android Wear 2.0 adds keyboard input, which recognizes both normal and gesture typing, as well as Smart Reply (Inbox’s automatic responses generated by machine learning from previously received messages).
I did not know this before hearing about Android Wear 2.0’s new Complications API, but “complications” is in fact a horology term that describes “any feature in a timepiece beyond the simple display of hours and minutes” (Wikipedia). The Complications API allows watch face developers to connect with data provider apps to display extra information.
Android Wear gets some more Material Design love with two new navigation components:
Check out the Material Design for Wearables documentation for good practices in wearable design. For example, something I learned during one of I/O’s Wear sessions is to use darker color palettes for Wear apps because:
Android Wear 2.0 contains both a visual update for notifications and new expanded notifications allowing you to provide additional content and actions to your users.
Keep an eye on the Material Design for Wearables for more information on notification design and best practices, and keep in mind that as Android Wear 2.0 is still just a developer preview, these guidelines may change.
For more detailed info and to find the developer preview, watch this Google I/O session on “What’s new in Android Wear 2.0” and check out developer.android.com.
Firebase is a Backend-as-a-Service (BaaS) and cloud services company that launched in 2012 with a realtime cloud database. Google acquired Firebase in 2014 and in the time since has grown from 110,000 users to over 450,000.
Google I/O 2016 marked another huge leap for Firebase as it has expanded to become a unified app development platform with more features and services. Quite a few of these services are actually familiar Google services that have been integrated into and rebranded with Firebase.
At the core of the new Firebase is a new analytics solution which gives you a single dashboard for analyzing both user behaviors and demographics as well as your advertising and marketing. Furthermore, the intention is that these analytics will be used in conjunction with other Firebase tools and features.
Before the announcement at Google I/O, Firebase offered a realtime database, user authentication, and hosting to developers. Now it has added the following offerings:
As you can see, Firebase seems to have changed to an essentially “All the Things” application platform. Something to note is that developers can choose which of these features to include so your app does not have to be as big as “All the Things” to take advantage of Firebase.
For the full scoop, head over to the firebase.google.com.
For me, one of the most intriguing announcements from both a UX and a development perspective is the new Android Instant Apps project. Instant Apps aims to ease the process of bringing new users into your app.
As noted in the Android Developers Blog introductory post on Instant Apps, if you think about the web, it takes a single click to take new users to a new website. On mobile platforms, your users must explicitly download your entire app to be able to experience it.
Instant Apps aims to change this and bring users more easily into your app by reducing what Google calls “install friction.” Via Instant Apps, a user could tap once on a deep link to specific content within your app and only those components necessary to display that content would be downloaded and launched.
Users could then have the option of installing your entire app from the downloaded components, or they could just finish viewing and/or interacting with your content and leave without any residue of your application.
For now, most of us developers have to wait to utilize Instant Apps, but we do know that:
Google says that “it can take less than a day” to upgrade apps to Instant Apps, but that comes with a “your mileage may vary” caveat. It seems that the relative ease with which you can upgrade depends largely on the structure and modularity of your existing app. I am looking forward to see what else Google has to say about Instant Apps, but there is still much to figure out in terms of how Instant Apps will jive with more complex applications.
For now we will have to wait and see, and you can keep an eye on g.co/InstantApps for further updates.
Okay, so a lot of the Google I/O 2016 announcements I have covered so far are still off in the far future, like Instant Apps. Some things are particular to specific types of apps, like Daydream and Android Wear 2.0. However, one thing for which every Android developer can cheer is a bunch of new features for the Android Studio 2.2 Preview!
A few months ago, I took at look at slew of new features in Android Studio 2.0. Not to rest on their laurels, the Android Tools team announced a whole bunch of new features and tools at Google I/O to take our productivity up to 11. This was easily my favorite session, and from the cheers in the audience, I don’t think I’m alone in that. Here’s what had us in the audience applauding:
Android Studio 2.2 introduces a whole new way of building layouts with the new Layout Editor, which includes drag-and-drop addition of widgets to a layout, a new blueprint mode that details the spacing and arrangement of widgets, a properties panel for easily changing widget properties, and the ability to edit menus and system preferences files.
To accompany the powerful new visual editor, there is also the brand new ConstraintLayout
. While it may sound similar to the RelativeLayout
, ConstraintLayout
helps you reduce the number of nested layouts that you need to implement your UI while still being high-performing and adaptive to different screen sizes and orientations. It was designed to work with the Layout Editor and the constraints inference engine, which automatically generates constraints for you using machine learning. ConstraintLayout
is distributed as a support library and is backwards compatible back to API 9.
A third new layout design tool is the Layout Inspector which allows you to drill down into your view hierarchy and examine the attributes of each view. Furthermore, Android Studio can now give you information on the default font size of a view as inherited from the theme of the layout.
Android Studio 2.2 has added quite a few new tools and features to improve development productivity.
In regards to builds, the Tools team has made improvements to the Jack compiler, including support for annotations and reduced build times for incremental builds. Also there is now a merged manifest viewer that allows you to analyze the dependencies and permissions in your app for your various build variants.
Two of my favorite new Android Studio announcements were the Espresso test recorder and the APK analyzer.
The Espresso Test Recorder aims to make generating UI tests incredibly simple. When the Test Recorder is active and you are interacting with your app, Espresso test code is generated automatically based on your interactions. This test code is reusable and editable.
Getting to watch the code generated as the Tools team moved through an app was pretty amazing and fun. Test recorder eliminates a whole bunch of excuses for not getting started UI testing.
By using the APK analyzer, you can view a breakdown of the memory usage of an APK by raw file size as well as download size. The APK analyzer is also a great tool for keeping your app’s method limit under control with detailed method and reference counts. You can even drill down to the app resources and see the compiled versions of them.
There were just so many improvements and new features that it would take a while to go through each and every one. For the full scoop, check out the What’s new in Android development tools session from Google I/O and read up on Android Studio 2.2 at the Android Developers Blog.
Google I/O 2016 definitely had its share of party and spectacle, but what should really get Android developers excited is the sheer number of new platforms and new tools that improve both the quality and functionality of apps as well as the productivity of developers. There really is more content than I can cover here, but luckily all of the Google I/O sessions were recorded and can be viewed on the Android Developers YouTube channel.
I hope you enjoyed this recap and are as excited as I am about all the incredible Android news from Google I/O this year!
The post What Every Android Developer Needs to Know About Google I/O 2016 appeared first on Ray Wenderlich.
View next video: Core Location
The post Video Tutorial: MapKit and Core Location: Series Introduction appeared first on Ray Wenderlich.
Learn the basics of working with Core Location and how to integrate it into your app.
The post Video Tutorial: MapKit and Core Location Part 1: Core Location appeared first on Ray Wenderlich.
It’s the most wonderful time of the year for Apple developers!
The first day of WWDC brought lots of new APIs and features for us to dive into, including Swift 3, SiriKit, iMessage Apps, and more.
Ever since the Platforms State of the Union I’ve been diving into the docs, and I thought it would be useful to post my first impressions of all the news, from a developer’s perspective.
Feel free to post any of your own thoughts, or anything I may have missed!
The change from this year that will have the biggest impact on developers is the release of Swift 3 in late 2016, since it will require us to all make some major changes to our Swift code.
However, if you’ve been following along with the Swift evolution project, this really shouldn’t be a surprise. Since Swift is open source, Apple and the community have been working extremely hard on this over the past 6 months, and everything’s been discussed publicly. Nothing new was announced today, aside from one thing: Swift 3 is conveniently packaged with Xcode 8, side-by-side with Swift 2.3.
This addresses one of my biggest complaints from last year, where we were unable to use Xcode 7 unless we also migrated our source code to Swift 2. But since Xcode 8 ships with both Swift 2.3 (which is source code compatible with Swift 2.2), you can now bring your Swift 2.2 projects over to Xcode 8 right away, and you can wait to upgrade to Swift 3 until you’re ready.
In case you haven’t been following the Swift 3 discussion, we’ll be releasing a full post on What’s New with Swift 3 tomorrow. In the meantime, I did want to mention one thing in particular that will affect all of us.
One of the biggest changes coming with Swift 3 is that Apple is giving a massive face-lift to its APIs to make them more “swifty”.
It’s easiest to understand this by looking at a few examples. Here’s an example of working with strings:
// Swift 2.2 let content = listItemView.text.stringByTrimmingCharactersInSet( NSCharacterSet.whitespaceAndNewlineCharacterSet()) // Swift 3 let content = listItemView.text.trimming(.whitespaceAndNewlines) |
Note how the Swift 3 version is much more concise, and makes use of an enum.
And here’s an example of working with Core Graphics:
// Swift 2.2 let context = UIGraphicsGetCurrentContext() CGContextMoveToPoint(context, 5, 0) CGContextAddLineToPoint(context, 10, 10) CGContextAddLineToPoint(context, 0, 10) CGContextClosePath(context) // Swift 3 let context = UIGraphicsGetCurrentContext()! context.moveTo(x: 5, y: 0) context.addLineTo(x: 10, y: 10) context.addLineTo(x: 0, y: 10) context.closePath() |
Note the switch from global C functions to handy methods on the context.
And finally, here’s an example of using GCD with a much simpler API:
// Swift 2.2 let queue = dispatch_queue_create("myqueue", nil) dispatch_async(queue) { // do stuff } // Swift 3 let queue = DispatchQueue(label: "myqueue") queue.async { // do stuff } |
As you can see, the goal is to reduce verbosity in naming in favor of terse yet expressive code; and moving away from globally defined functions in favor of members of respective types.
The changes here are going to take some getting used to for seasoned developers, but in the long run it will make the language cleaner and more approachable to new developers. Also, Xcode 8 ships with a migration tool to convert your existing code to Swift 3, which should make things much easier.
I am really excited to see these changes because ultimately the new APIs feel much more intuitive than they do today.
Ever since the release of the iPad Pro, developers have been anticipating Xcode for the iPad.
We didn’t quite get that, but we did get a step in that direction with the announcement of Swift Playgrounds for the iPad. It’s similar to the Playgrounds we already know and love, but it also has a nice custom keyboard and UI for easily creating code, and some nice built-in tutorials for beginners.
It looks to be particularly well suited for teaching people Swift as their first programming language, but I can also see it being handy for experienced developers looking to prototype some code on the go.
It wouldn’t be WWDC without a major update to Xcode!
Here are some of the top highlights for me so far.
One of the coolest new features for me was Xcode 8’s new memory debugger.
This is a built-in tool that lets you view the entire memory object graph of your running application, so you can quickly isolate leaks and circular references. As soon as you spot them in the graph you can select it, view that frame’s stack and jump straight to the line of code causing the issue. Simply brilliant!
Even more, the new memory debugger can automatically detect memory leaks and help you quickly diagnose the problem. The demo was beyond impressive and drew massive applause from the audience. Goodbye, retain cycles!
Have you ever tried zooming out in Interface Builder, then tried to drag in a button, and realized that you couldn’t unless you were at 100% zoom level?
Well, those days are no more! Interface Builder in Xcode 8 now allows you to edit your scenes at any zoom level.
It also comes with a handy new configuration bar that allows you to easily preview your view controller sized for different devices and size classes (iPhone, iPad, etc), and identify ambiguous layout constraints before you ever build and run. This is going to be such a time saver for users of Interface Builder.
Xcode 8 improves on the source editor by autocompleting image assets in your project with a preview of the image itself, right in line with your code!
You achieve this by typing the name of your image and a non-optional UIImage
instance is returned.
In addition, Xcode 8 can display colors right in line for literal definitions:
You achieve this by typing color
into the editor and choosing the “Swift Color Literal” option which will bring up a color picker.
You can also create your own Source Code Editor Extensions to customize the coding experience. There is a new Xcode template to get started with, and when you’re finished you can distribute your extensions via the Mac App Store or as a Developer ID signed binary through any other medium. I am looking forward to seeing what you all develop!
Apple claims that Xcode 8 is radically faster in several categories – for example Indexing Tests can be up to 50 times faster.
Speed improvements leads directly to more productivity as developers, so this is great news!
The iOS 10 SDK adds a number of new kits, extension points, and enhancements to existing frameworks. Below is a small pickings of the ones that stood out to me.
Arguably the most long awaited developer feature is the ability to integrate with Siri. Now you can in iOS 10 with SiriKit!
SiriKit defines six distinct domains that your app can use to make services available to Siri:
If your app falls into one of the domains listed above, you should provide an Intents Extension point within your app. Siri deals with all of the nuances of language processing and semantic analysis, and translates the user’s request into an actionable item that you handle in your Intents Extension. You can opt to provide custom UI as necessary when your app is passed an Intent from Siri or Maps.
There are a number of details that your extension must provide in order for the system to determine that your app can handle a user’s request, but if you are familiar developing App Extensions that were introduced with iOS 8 you will be on your way to creating a Siri extension in no time.
As a Slack and Facebook Messenger user, I am super excited about the enhancements to messages. Animated GIFs and fireworks, here I come! :]
In the keynote, Apple demonstrated a ton of cool new features like link/media unfurling, reactions, message bubble effects and even window effects that I don’t quite understand how to create yet. As the demos went on, I kept hoping that they’d announce an extension to allow third party developers into the messaging platform, and they did! With the new Messages framework you can create extensions that let users send text, stickers, media, files and most intriguing: interactive messages.
Sticker Packs
The simplest type of extension is sticker packs. These are ridiculously easy to build and allow you to define a set of stickers that a user can use to send to their friends. If you’re at all familiar with Facebook Messenger it looks very similar, except that stickers can be “peeled” and placed on top of other messages. Honestly, it’s a bit gimmicky, but should still be very entertaining. :]
Interactive Experiences
You can go a lot farther than sticker packs though. The APIs allow you to create entire experiences right within the Messages app, even providing a custom user interface! This is obviously interesting for services like Giphy, where providing such an extension may have a better experience than what their third party keyboard does today. But it may also be extremely powerful in business contexts as well.
Consider a service company who has a fleet of techs that use Messages to communicate. It might be useful for them to have access to data from their customer management system right within messages to get information back and forth to each other quickly. And with interactive messages each party can “build” upon a message. The Keynote demo that was given was creating a group food order where each person on the group chat could modify the food order before it was sent.
There are a ton of apps I can foresee benefiting from this and I am excited from a user’s perspective to see where it goes.
A new UserNotificationsUI
framework has been introduced which allows developers to create rich notifications that were never possible before.
For example, notifications can now have embedded media much like the stock Messages app. This appears to involve an intermediate server between your app and APNS but it looks to be extremely powerful. You can even provide your own layer of end-to-end encryption features through the use of the intermediate server.
I haven’t had time to look into this much yet, but look forward to more details on notification enhancement as the sessions play out and also check out the UserNotifications framework reference.
Widgets are getting a big overhaul in iOS 10 and I am glad to see it. I was originally pretty excited for widgets in iOS 8, but as it turned out they just weren’t that great living in the Notification Center.
Now, widgets live to the left of your home screen kind of like how they used to be on macOS. Widgets can also appear with your 3D Touch Quick Actions on above/below your app icon. This is a much more natural place to look for quick information in my opinion, it’s almost as if you’re peeking into the app’s content.
It’s a common opinion that the Apple Watch platform has been a bit of a flop with regards app development. Although it’s a very fascinating device and is pretty good at its core functionality, it has been missing something since the beginning: speed.
Launching apps on the watch is simply painful. Often you’re met with a spinner that goes on and on for 20-30 seconds and even sometimes bails out completely, leaving you frustrated and confused. Eventually you find yourself stashing your watch in a drawer, selling it, or like me wearing it simply as a time piece and notification viewer.
When Kevin Lynch opened the keynote by saying that their main focus was making apps launch instantly, I was pretty excited! If this pans out to be truth, this makes me believe that watchOS development will be great again. :]
The big things behind the speed enhancements of the watch are the introduction of Snapshots, the Dock, and Background Tasks. The three of these combined allow watch apps to stay up to date and available to the user at a moment’s notice.
Snapshots and Background Tasks are similar are just like on iOS:
You can now utilize both SceneKit and SpriteKit in your watch apps. At first mention I thought this was just for games, but then Apple explained another use case: creating nice custom animations for regular apps.
The current limitations of UIKit on the watch prevent developers from creating custom animations. But with watchOS 3, you can add live 3D rendered content to your apps using .scn
files bundled with your resources, or you can opt to create interactive 2D animations with bundled .sks
files. It will be really interesting to see what developers do here!
When a user adds your complication to their watch face in watchOS 3, you gain the ability to keep your app in a ready to launch state and get a guaranteed 50 push updates per day. This is a pretty compelling reason to provide a complication if it makes sense for your app’s data. Perhaps even in some instances the complication data may not be that valuable to a user but the added benefit of faster app launch is.
The updates to the tvOS SDK seem pretty light.
There is a new concept of single sign-on with TV providers so that users can authenticate with their provider once and be logged in to all supported video channel apps. So if you develop apps that need this level of authentication please check out the VideoSubscriberAccount
framework!
The main items of interest for tvOS are that there are a number of existing frameworks made available to developers:
ExternalAccessory
HomeKit
MultipeerConnectivity
Photos
ReplayKit
UserNotifications
After 15 years, OS X has been renamed to macOS to better align with the other three platform names. The latest version of macOS is macOS Sierra.
I’m personally not a macOS developer, so I’m not going to dive into this much. However, I do want to highlight one feature that is particularly interesting to me.
With macOS Sierra users can make purchases using Apple Pay on the web!
This is huge for any developers working on a web site with eCommerce, as it lowers the barrier of entry for a paying customer almost entirely. Imagine not having to deal with the security concerns of handling customer credit card data – and even better, the confidence your customers have knowing that their credit card information is not being stored on various web sites.
As far as I can see it there is no reason (barring legal commitments) to not add Apple Pay support to your websites. The process involves integrating an Apple Pay JavaScript framework.
Last but not least, I’d like to discuss something that is relevant across all of the platforms: Apple has announced an entirely new file system!
Had I not listened to John Siracusa talk about file systems on various podcasts I would have never expected this. The improvements appear to be pretty great though!
The current file system used by default is HFS+ which was released in 1998 when floppy disks were still a thing. Today most – I am looking at you base model iMac with your 5400RPM HDD – new systems include fast Flash based SSDs. The Apple Filesystem was designed with Flash/SSD in mind and built with native encryption.
The user benefits include things like crash protection, space sharing, cloning and snapshots. Crash protection uses a copy-on-write metadata scheme which ensures that updates to the file system are crash safe and reduces the need of journaling used by HFS+. Space sharing allows multiple file systems on the same disk to share the free space available without the need to repartition the drive.
Cloning provides the ability to create instant “copies” of files and directories that cost nothing in disk space. Due to the copy-on-write behavior the cloned files and directories are not actually copied unless modifications are made. *NIX users might relate this to creating symbolic links, it’s the first thing I thought of, but I am sure there is a ton more to it. Finally, the snapshotting ability allows the system to create a read-only instance of the data so that it can be efficiently restored to a given point in time.
So that concludes my initial impressions of all the new goodies in store for us this year.
As I mentioned, I haven’t had a chance to look through everything yet, so I may have missed some buried gems. Please let us know if you spot anything, we’re just as excited and overwhelmed by all the new content!
In the meantime, we’ll be working hard on making some new written tutorials, video tutorials, and books in the coming weeks. Stay tuned! :]
The post WWDC 2016 Initial Impressions appeared first on Ray Wenderlich.
Learn how to receive background updates, deferred updates, and how to get a singular location using Core Location.
The post Video Tutorial: MapKit and Core Location Part 2: Background Updates appeared first on Ray Wenderlich.
Swift 3 is coming later this year, and it brings major code changes to all Swift developers.
If you haven’t been following the Swift Evolution project closely, you may wonder what changes are in store, how it will affect your code, and when you should start porting your code to Swift 3. This article is for you! :]
In this article, I’ll highlight the most significant changes in Swift 3 that will impact your code. Let’s dive in!
Swift 3 preview is available in Xcode 8 beta which is out today. While the evolution of Swift 3 is winding down, there still may be a few accepted changes in the next few months. Feature freeze will occur when Xcode achieves GM in late 2016, so you’ll have to hold off until then before you release Swift 3 apps to the App Store.
To allow developers to make the migration to Swift 3 on their own terms, Apple has included Swift 2.3 as a minor update bundled with Xcode 8. To you as a developer, Swift 2.3 is the same as Swift 2.2 but with support for many of the new SDKs and Xcode features announced at WWDC. Once Xcode 8 comes out of beta, you will be able to submit apps using Swift 2.3 if you have not yet migrated your code to Swift 3.
I recommend trying out the features we discuss in a playground and maybe even running the Migration Assistant on one of your projects so you can get a feel for everything that is changing. But since you can’t release an app to the App Store until Xcode 8 is out of beta and Swift 3 is final, you may want to consider waiting to port your code to Swift 3 until things settle down.
When converting to Swift 3, you’ll notice that practically every file needs changes! That’s largely because, all the Cocoa API names have changed. Or to be more precise, the API is the same, but there’s one name appropriate for Objective-C and one name appropriate for Swift. Swift 3 is going to make Swift much more natural to write in the years ahead.
Apple has included a Migration Assistant with Xcode 8 that can brilliantly make most of these changes in one fell swoop. Don’t be surprised though if you need to touch up a few areas yourself that the migrator doesn’t handle automatically.
You can convert to either Swift 2.3 or Swift 3 immediately. If you ever need to bring it back up, you can always navigate in Xcode to Edit > Convert > To Current Swift Syntax…. The compiler fortunately shares the same smarts as the Migration Assistant as well. If you accidentally use the old API on a method call, the compiler will offer a Fix-It option that will help you use the correct modern API.
The best news of all is that Swift 3 aims to be the last release with breaking source changes. So looking forward, you should be able to keep your Swift code from version to version. While the Swift core team can’t predict the future, they have promised that if they do need to break source compatibility, they will offer long deprecation cycles. That means the language has achieved source stability that will encourage more conservative companies to adopt it.
That said, the goal to achieve binary stability was not reached. You’ll find more on the impact of this at the end of this article.
Community members submitted over 100 proposals for changes to Swift since it went open source. A large number of them (70 so far) have been accepted after discussion and modification. Those that have been rejected have sparked some intense discussion as well. In the end however, the core team makes the final decision on all proposals.
The collaboration between the core team and the wider community has been impressive. In fact, Swift has garnered 30 thousand stars on Github. Several new proposals are submitted every week, week-after-week. Even Apple engineers pen proposals on open Github repository when they want to make changes.
In the sections below, you’ll see linked tags such as [SE-0001]. These are Swift Evolution proposal numbers. The proposal numbers included here have been accepted and will be implemented in time for the final Swift 3.0. The links to each proposal have been included so you can discover the full details of each particular change.
The biggest update in Swift 3 involves the standard library adopting consistent naming conventions across libraries. The API Design Guidleines contain the rules that the team settled on as they were building Swift 3, which place a high value on readability and accessibility to new programmers. The core team operated on the principal that “Good API design always considers the call site”. They strove to bring clarity to the point of use. Without further ado, here are the changes most likely to impact you.
Let’s start off strong with a direct reversal of a practice you use every day in Swift.
The first parameter in functions and methods now always has a label unless you request otherwise. Previously when you called a function or method you omitted the first parameter label [SE-0046]:
// old way, Swift 2, followed by new way, Swift 3 "RW".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding) "RW".write(toFile: "filename", atomically: true, encoding: NSUTF8StringEncoding) SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10) SKAction.rotate(byAngle: CGFloat(M_PI_2), duration: 10) UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline) UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline) override func numberOfSectionsInTableView(tableView: UITableView) -> Int override func numberOfSections(in tableView: UITableView) -> Int func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? func viewForZooming(in scrollView: UIScrollView) -> UIView? NSTimer.scheduledTimerWithTimeInterval(0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true) NSTimer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true) |
Take note of how the method definitions use prepositions like “of”, “to”, “with”, and ” in” for the external name. These are part of an effort to optimize readability.
If the method call reads well without a preposition and doesn’t need a label, you should explicitly exclude the first parameter name with an underscore:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... } override func didMoveToView(_ view: SKView) { ... } |
In many programming languages, methods may share a base name and offer different parameter names. Swift is no exeption, and now you’ll come across overloaded method names much more since the APIs have been translated to be more direct. Here’s an example with two forms of index()
:
let names = ["Anna", "Barbara"] if let annaIndex = names.index(of: "Anna") { print("Barbara's position: \(names.index(after: annaIndex))") } |
Altogether, the parameter name changes make method naming more consistent and easier to learn.
In previous iterations of Apple libraries, methods included a name that indicated their return value. Because of the Swift compiler’s type checking, this is much less necessary. The team took a hard look at how to filter out all the noise so that only the signal remains and thus a lot of word repetition has been removed.
The API has gotten smarter about how Objective-C libraries are transformed into native Swift [SE-0005]:
// old way, Swift 2, followed by new way, Swift 3 let blue = UIColor.blueColor() let blue = UIColor.blue() let min = numbers.minElement() let min = numbers.min() attributedString.appendAttributedString(anotherString) attributedString.append(anotherString) names.insert("Jane", atIndex: 0) names.insert("Jane", at: 0) UIDevice.currentDevice() UIDevice.current() |
Speaking of old API holdouts, GCD and Core Graphics have both received a much-needed makeover.
Grand Central Dispatch is used for many threading tasks such as long calculations or to communicate with a server. By moving activity to a different thread, you prevent locking up the user interface. The libdispatch library was written in the C programming language and has always used a C style API. The API has now been reimagined in native Swift [SE-0088]:
// old way, Swift 2 let queue = dispatch_queue_create("com.test.myqueue", nil) dispatch_async(queue) { print("Hello World") } // new way, Swift 3 let queue = DispatchQueue(label: "com.test.myqueue") queue.asynchronously { print("Hello World") } |
Similarly, Core Graphics was written in C and in the past used awkward function calls. Here’s how the new way looks [SE-0044]:
// old way, Swift 2 let ctx = UIGraphicsGetCurrentContext() let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512) CGContextSetFillColorWithColor(ctx, UIColor.blueColor().CGColor) CGContextSetStrokeColorWithColor(ctx, UIColor.whiteColor().CGColor) CGContextSetLineWidth(ctx, 10) CGContextAddRect(ctx, rectangle) CGContextDrawPath(ctx, .FillStroke) UIGraphicsEndImageContext() // new way, Swift 3 if let ctx = UIGraphicsGetCurrentContext() { let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512) ctx.setFillColor(UIColor.blue().cgColor) ctx.setStrokeColor(UIColor.white().cgColor) ctx.setLineWidth(10) ctx.addRect(rectangle) ctx.drawPath(using: .fillStroke) UIGraphicsEndImageContext() } |
In another reversal from the way you’ve been used to coding Swift, lowerCamelCase now replaces for enumeration cases. This makes them more consistent with other properties – or values [SE-0006]:
// old way, Swift 2, followed by new way, Swift 3
UIInterfaceOrientationMask.Landscape
UIInterfaceOrientationMask.landscape
NSTextAlignment.Right
NSTextAlignment.right
SKBlendMode.Multiply
SKBlendMode.multiply |
UpperCamelCase is now reserved solely for names of types and protocols. While this may take some getting used to, the Swift team had really good reasoning in their strive for consistency.
The standard library is also getting more consistent in method naming with verbs and nouns. You choose a name based on the side effects or the actions taken. The rule of thumb is that if it includes a suffix like “-ed” or “-ing” then think of the method as a noun. A noun method returns a value. If it doesn’t have the suffix, then it is most likely an imperative verb. These “verb” methods perform the action on referenced memory. This is also known as modifying in place. There are several pairs of methods that follow this noun/verb convention. Here are a few of them [SE-0006]:
customArray.enumerate() customArray.enumerated() customArray.reverse() customArray.reversed() customArray.sort() // changed from .sortInPlace() customArray.sorted() |
Here’s a snippet of them in action:
var ages = [21, 10, 2] // variable, not constant, so you can modify it ages.sort() // modified in place, value now [2, 10, 21] for (index, age) in ages.enumerated() { // "-ed" noun returns a copy print("\(index). \(age)") // 1. 2 \n 2. 10 \n 3. 21 } |
Function declarations and function calls have always required parentheses around their parameters:
func f(a: Int) { ... } f(5) |
However, when you use a function type as a parameter itself, you might write something like this:
func g(a: Int -> Int) -> Int -> Int { ... } // old way, Swift 2 |
You probably notice that it’s fairly difficult to read. Where do the parameters end and the return types begin? With Swift 3 the correct way to define this function is [SE-0066]:
func g(a: (Int) -> Int) -> (Int) -> Int { ... } // new way, Swift 3 |
Now the parameter lists are surrounded by parentheses and followed by the return type. Things are clearer, and consequently, the function type is easier to recognize. Here’s a more robust comparison:
// old way, Swift 2 Int -> Float String -> Int T -> U Int -> Float -> String // new way, Swift 3 (Int) -> Float (String) -> Int (T) -> U (Int) -> (Float) -> String |
While the biggest update to Swift 3 has been the modernization of the existing APIs, there is much more the Swift community has been hard at work at – including several useful additions to the Swift API as well.
When you define a static property or method, you have always called them on the type directly:
CustomStruct.staticMethod() |
If you are writing code in the context of a type, you still need to include the name of the type to call a static method on the type. To make this a bit cleaner, you can now call Self
to get the containing type. The capital ‘S’ refers to the type of self, whereas the lowercase ‘s’ refers to the instance of self.
Here’s how it works in action [SE-0068]:
struct CustomStruct { static func staticMethod() { ... } func instanceMethod() Self.staticMethod() // in the body of the type } } let customStruct = CustomStruct() customStruct.Self.staticMethod() // on an instance of the type |
sequence(first:next:)
and sequence(state:next:)
are global functions that return infinite sequences. You give them an initial value or a mutable state and they will lazily apply a closure [SE-0094]:
for view in sequence(first: someView, next: { $0.superview }) { // someView, someView.superview, someView.superview.superview, ... } |
You can constrain the sequence by using the prefix
manipulator [SE-0045]:
for x in sequence(first: 0.1, next: { $0 * 2 }).prefix(while: { $0 < 4 }) { // 0.1, 0.2, 0.4, 0.8, 1.6, 3.2 } |
#keyPath()
works like #selector()
and helps you vanquish typos in stringly typed APIs
Float.pi
, CGFloat.pi
. And most of the time the compiler can infer the type: let circumference = 2 * .pi * radius
[SE-0067]
NS
prefix has been removed on old foundation types, you can now use Calendar
, Date
instead of NSCalendar
and NSDate
.Swift is a language, and a large part of writing it involves using a development environment – which for Apple developers is likely Xcode! The changes going on with the tooling will impact how you write Swift every day.
Swift 3 fixes bugs in the compiler and IDE features. It also improves the precision of error and warning messages. And as you might expect, with each release, Swift is getting faster in how it runs and compiles:
Xcode is also learning how to think in native Swift:
sort()
and jump to its definition, you used to be taken to a cryptic header file. Now, in Xcode 8, you see that sort()
is an extension to Array
like you would expect.
Open source Swift is actually a family of repositories including the language, the core libraries, and the package manager. Together, this suite makes up what we think of as Swift. The Swift Package Manager defines a simple directory structure for any Swift code that you share and import into projects.
Similar to package managers you may be used to such as Cocoapods or Carthage, Swift’s package manager will download dependencies, compile them, and link them together to create libraries and executables. Swift 3 is the first release to include the Swift Package Manager. There are 1,000 libraries that already support it and in the coming months, you’ll start to see more formatted for it.
It was previously mentioned that Swift 3 aims to let you keep your code from version to version in the future by striving to avoid breaking changes. While that is true, there were some loftier, related goals that weren’t reached for this release, namely generics additions and Application Binary Interface (ABI) stability.
The generics additions will include recursive protocol constraints and the ability to make a constrained extension conform to a new protocol (i.e., an array of Equatable elements is Equatable). Before these features are complete, Swift is unable to declare ABI stability.
ABI stabilization will allow applications and libraries compiled with different versions of Swift to be able to be linked and interact with each other. This is a vital step for third party libraries to ship frameworks without providing the source code since new versions of Swift not only require them to update their code, but to rebuild their frameworks as well.
Additionally, ABI stability would remove the need to ship the Swift standard library along with binaries, as is currently the case with iOS and macOS apps created with Xcode. Right now binaries are bundled with 2 MB extra filesize that ensures that they will run on future operating systems.
So to summarize, you can now keep your source code version to version, but the compiled binary compatibility from version to version is not yet here.
Swift continues to evolve as the community converges on best practices. While still in its infancy, the language has a lot of momentum and a big future. Swift already runs on Linux, and you will likely see it running on servers in addition to devices in the coming years. Designing a language from scratch certainly has its advantages as opportunities to break ABI stability once its locked down will be rare. This is a unique chance to get the language correct without regrets.
Swift is also expanding its reach. Apple is eating their own dogfood. Teams at Apple use Swift on the Music app, Console, picture-in-picture in Sierra, the Xcode Documentation viewer, and the new Swift Playgrounds app for iPad.
Speaking of which, there’s a big push to get non-programmers learning Swift on the iPad and education initiatives!
The takeaway here is that Swift continues its ascent: the names are better, the code reads clearer, and you have the tools to migrate. If you’re inspired to dig deeper, you can watch the WWDC session videos.
There will surely be more to come by the time Swift 3 is finalized in late 2016. We’ll be staying on top of all the updates here, so keep an eye out for tutorials, book announcements, and videos as we start using the exciting changes.
What parts of Swift 3 are you most excited about? What would you like us to cover first? Let us know in the comments below!
The post What’s New in Swift 3? appeared first on Ray Wenderlich.