With discussions on custom controls versus standard controls and if Apple is doing enough to make iOS fully accessible, I wanted to contribute with my experiences and my thoughts on all of this as a developer in Apple's ecosystem.
Setting numerical values is something many apps have to deal with, whether it's the changing the volume or display brightness, scrubbing through a song or a video, rating a great app, or something completely different. The two standard components we have for this task are sliders and steppers. There are reasons to extend these controls to provide app specific functionality like custom callouts, range selection, circular sliders, etc. and there are plenty of custom slider like controls out there. Whenever we choose to write a custom control, we're likely to lose the built-in accessibility of the standard control. In the case of sliders, the ability to easily adjust its value.
If you've haven't seen it before, there is a cool accessibility feature in UITableView that allows the user to toggle between different actions. It's really very elegant and it's a powerful and convenient implementation for VoiceOver users on iOS. One could say that it's the VoiceOver version of the swipe-to-delete feature. If we've written a custom gesture to delete cells, then chances are that we've broken this behvaior. Luckily, it's not that difficult to put it back.
Just before WWDC I answered an interesting question on Stack Overflow asking where to update the model value when following Core Animation best practices. It may sound like a simple question but it touches on deep topics like implicit vs. explicit animations, stand-alone vs. backing layers, and multiple animations. I'm not going to reiterate the whole question and answer here, but I'm going to start with the same question.
This post is going to be a little bit different. Instead of showing some niche animation technique or giving detailed explanations of how it works, it's about how to write clear animation code. More precisely it's about what I think is clear, readable code and how I approach writing it.
There is a protocol called CAMediaTiming which is implemented by CAAnimation, the base class of CABasicAnimation and CAKeyframeAnimation. It is where all the timing related properties – like duration, beginTime and repeatCount – come from. All in all the protocol defines eight properties that can be combines in a number of ways to precisely control timing. The documentation is only a few sentences per property so you could probably read it all and the actual header way faster than this article but I feel that timing is better explained with visualizations.
As programmers we have to deal with dates and times in many real life situations: "are there any calendar events today?", "how many days until the new iPhone comes out?", "sort these messages by when they were posted", "set an alarm for tomorrow morning at 7". At first glance these tasks can seem simple but dates have a lot of subtleties that can easily be overlooked.
In todays world of mobile devices with touch screens we all know that we shouldn't make interface elements to small or pack them to close to each other because they will be hard to hit but some elements just look bulky when we try and make them bigger. In those cases we can use transparency to get small elements with big tappable areas.
SceneKit offers a wide range of built in geometry like cubes, cylinders, pyramids, spheres, torus, etc., that can be used to for example create beautiful 3D bar charts. More advanced geometry (and even full scenes) like an environment for a game or an interior design application can be created by a designer in their favorite 3D modeling software to be modified and rendered by your application. In addition to these two options SceneKit can be used to generate geometry from a list of points. This comes in very handy when doing 3D graphs and visualizations.
SceneKit is a high level 3D framework for Mountain Lion that was introduced almost a year ago at WWDC 12. It is all Objective-C and integrates with other UI frameworks like Cocoa and Core Animation. This means that you can use normal NSColors, NSImages and CATransform3Ds to configure your 3D scene. It also means that you can easily animate property changes, like for example position or transform, using a regular CAAnimations and addAnimation:forKey:. Sounds amazing? It is.
There is more to an app with great accessibility than just labels, hints and traits. The app needs to have the correct behavior as well. When it comes to implementing accessibility on iOS the golden rule is “do it the same way that Apple is doing it”. You may have your opinions about the visual appearance of some of the built in controls but they behave great. It’s also not only the behavior of the individual controls that matter but the bigger picture.
Bézier paths are a powerful part of computer graphics. They allow the construction of any vector shape that can later be rendered in any resolution. Construction of a Bézier path can initially seem strange but after breaking them down into the lines, curves and arcs they are composed of can help us understand them.
For the most part, adding support for VoiceOver isn’t really that difficult. Setting appropriate labels and hints for your views goes a long way. Custom drawing however is less than the sound of crickets to a visually impaired user. Text that would otherwise be accessible just by being text is no longer accessible and if your custom drawing contains multiple elements there is no way to differentiate between them... ...or is it?
We have objects on our screen that are visually defined by the fours corners of the rectangle they lie within. Even objects that are not rectangles themselves can be contained by a rectangle. We know that applying a transform to this object on screen causes it to change its position, size or rotation on screen. The transform is used to calculate the new positions of the four corners and everything inside the rectangle stretches to fill the rectangle just as before the transform. Our goal is to understand how the new positions are being calculated for different kinds of transforms.
When working with transforms and wanting to rotate around some other point than center or origo you hear that you need to translate (move), then rotate and then translate back. Let me explain what that means.
While browsing Stack Overflow over the past few weeks there was many occasions when I wanted to say: “Go read this blog post about the anchorPoint, it will explain things to you.” Luckily I can say that now.
In maths and computer science we sometimes use sets, unordered collections of unique entries. NSMutableSet has good basic support for set-operations like unions, intersections, relative complements (also called difference) with operations like unionSet:, minusSet: and intersectSet:. There is also support for subsets. The other extremely common data type is an array, an ordered collection of entries. We don't usually talk about array intersections or array complements but they can sometimes come to good use. While there is no built in methods for this, NSPredicate makes it really easy.
This week I found an actual use for CAReplicatorLayer, not just a place where I could make use if it but a place where it was a really good fit: Custom activity indicators AKA spinners. Lets go trough the process.
At the core of Core Animation is the fact that it changes the animated property right away (or not at all) but smoothly animates the change visually over time. If you inspect the value of the animated property during the animation it will already have been set to its final value (or never been changed at all). Knowing this, what do you do when you need to know the values that is being used to render the layer during the animation? How do you hit test a moving layer?
I've seen so many people trying to or asking how to modify collections while enumerating them. Sometimes they don't even notice that they are doing it. Depending on where you are coming from it is sometimes called iterating but the problem remains the same: it is not allowed to modify a collection (a set, an array or a dictionary) while enumerating over it.