Tag Archives: Mac

WWDC 2016

I had the opportunity to go to my 3rd WWDC (Apple’s World Wide Developers Conference).  WWDC is a great place to learn about the new things Apple is introducing in upcoming versions of their products as well as to talk with Apple engineers and others who are developing for their platforms.

All of the content from the sessions delivered at WWDC is available online.

High-Level Summary

  • New features in iOS 10
    • SiriKit
    • New user notification framework with more ways to display and manage notifications
    • New extension points in iMessage
    • Improvements in UIKit animations and transitions
    • Improvements in collection views and table views
  • New features in watchOS 3
    • Button modified to bring up a dock of active apps.  Glances removed in favor of docked view of app.
    • Background app refresh
    • Changes to navigation by using the digital crown to navigate between elements at the same level.
    • Access to the digital crown.
  • Swift 3
    • The API design guidelines were applied to the language and Cocoa/CocoaTouch frameworks.
  • Networking
    • HTTP/2 Server Push is now supported
    • Network statistics

Evaluation

The changes in the notification system and in watchOS can really improve the user experience for presenting notifications.

The changes to Swift continue to improve the safety provided by the language to reduce the occurrence of bugs.

Good info on improving the performance of table and collection views.

HTTP/2 Server Push can significantly improve the responsiveness of mobile apps.

Apple made some really nice changes in watchOS (notifications, background refresh, navigation) that should make the watch a lot easier to use.

Sessions

What's New in Swift

Video

Mission Control, the accessibility engine were rewritten in Swift.

  • 15% less code in Swift than in Objective C
  • Engineers love using Swift

Open source – swift.org

  • Big emphasis of Swift 3
  • Everyone follows the same procedure for getting changes incorporated, even Apple, using the swift-evolution repository on GitHub

Naming

New features for controlling how Objective-C APIs are imported into Swift

Whole module optimization is now turned on for al new projects.  Existing projects will get a warning to modernize.

Swift API Guidelines

Video

Principles

  • Clarity at the point of use
    • Design APIs to make uses clear and concise
    • Uses of APIs always have surrounding context
    • Don’t optimize for bad code
  • Clarity is more important than brevity
    • Brevity itself is not a worthwhile goal
  • Concise code is a consequence of using contextual cues

Omit needless words, those that don’t contribute to clarity

Brevity itself is not a worthwhile goal

Make uses of your APIs read grammatically

  • If the first argument is part of a prepositional phrase, give it a label
  • If the first argument is not pat of a grammatical phrase, give it a label
  • Use a verb to describe the side effect
  • Use a noun to describe a result

Name methods based on their side effects

  • Use a verb to describe the side effect
  • Use a noun to describe the result

Mutating/non-mutation pairs

  • ed/ing rule
    • “reverse” – mutating
    • “reversed” – non-mutating

Objective-C names in Swift

  • Avoid strings for selectors and key paths.
  • Use #selector for selectors (introduced in Swift 2.2).  Swift 3 adds support for getters and setters.
  • Use #keyPath for key paths (introduced in Swift 3)
  • NS_EXTENSIBLE_STRING_ENUM – allows you to provide stronger type-safety for Objective-C string values that are intended to be used in a specific way.

Migrating code

  • Swift 3 migrator
  • Compiler helps with renaming-related problems
  • Near-miss detection

Using Store Kit for In-App Purchases with Swift 3

Video

  • Expanded categories
  • Increased proceeds for longer held subscribers (longer than a year)
  • Territory pricing
  • Preserve prices
  • Upgrades and downgrades

Types of in-app purchases

  1. Consumable products
  2. Non-consumable products
  3. Non-renewing subscriptions
  4. Auto-renewing subscriptions

Rely on the payment queue and only the queue

What's New in Cocoa Touch

Video

Core technologies

  • Name changes in Swift
  • Grand Central Dispatch
  • Foundation
    • New ISO 8601 date formatter

UIPasteboard

  • A paste operation might have to retrieve remote content
  • Control over content

UIGraphicsRenderer

  • Fully color managed
  • Block-based
  • Subclasses for images and PDF
  • Manages context lifetime

Asset Management

  • Compression

Accessibility Inspector

  • View and audit accessibility support

Speech Recognition

  • SFSpeechRecognizer
  • Continuous speech recognition
  • From audio files or buffers

Text content type

Dynamic Type

  • Content size
    • No longer a property on UIApplication

Tab Bar customization

Improved WKWebView support for peek and pop

Custom peek and pop animation on UIPreviewInteraction

Full support for UIRefreshControl on UIScrollView and UICollectionView

Collection view

  • Now supports automatic self-sizing cells in flow mode
  • Smooth scrolling with cell prefetching, cell at a time, not by row, for free
  • Data prefetching – new protocol, also on table views

Animation

  • Interruptible
  • Scrubbable
  • Reversible
  • Rich timing features
  • Dynamic
  • Interactive and gesture-driven, all in one animation

Improving openURL

  • Async with completion handler
  • Let’s you check if a handler app is installed

NSUserActivity

  • Capture the state of your application
  • Infrastructure for Handoff, Spotlight
  • Now supports locations
  • Search results can now be continued in your app

SceneKit

  • New realistic rendering
  • Available on watchOS

New display modes for widgets

  • Widgets can be shown on the lock screen
  • Consider privacy in your use of this feature

New user notification framework

  • Unifies local and remote notifications
  • Better delivery management
  • In-app presentation option
  • Multi-platform (iOS, watchOS, tvOS)
  • Service extensions
    • Non-UI extension point
  • Content extension
    • Custom views
    • Cannot interact

CallKit

  • Directory extension
  • Blocking
  • Identification
  • Call provider API

SiriKit

  • Intents and responses
  • Intents are domain specific
  • IntentsUI extension for displaying your own UI

What's New in watchOS 3

Video

Watch app objectives

  • Glanceable
  • Actionable
  • Responsiveness

The Glance functionality has been merged into the new Dock

Spend time figuring out how to shorten interactions with the watch

Background App Refresh

All the user’s favorite apps are in memory.  They are launched and then suspended.  This includes apps associated with complications and those placed in the Dock.

The OS takes a snapshot of an app to show in the dock the last time it was visible.  Use the background refresh APIs to update the snapshot.

The system schedules a refresh when:

  • The user leaves your app
  • Your notification is dismissed

You may want to snapshot a simpler view for display in the dock and then transition to a more complete view when the user brings the app to the foreground

Silent Complication Push Update

  • Each app on the watch face can get up to 50 push updates

If the dock is full, each app in the dock can be updated once per hour

If it is not full, the total number of updates will be distributed amongst the remaining apps

Your app on the phone can also push updates to the app on the watch

Navigation Enhancements

Use segues so that the watch system can generate views in the hierarchy

Fit as much of your detail view on a single “page”

Crown

You can use the crown to scrub through a graph

This requires that you don’t use a scroll view

Introduction to Notifications

Video

New User Notifications Framework

  • Feature parity with existing API
  • Same code path for local and remote notification handling
  • Your app has access to pending and delivered notifications
  • In-app presentation optino

Local notifications on the watch

Access to user-defined settings

Title always shown.  Subtitle available as well.  Media attachments can also be shown.

Triggers

  • Push (remote only)
  • Time interval
  • Calendar
  • Location

Notification Management

  • Access to pending and delivered notifications
  • Remove notifications
  • Update notifications
  • New field on the HTTP/2 request header on push notifications

Notification Actions

  • Default action
  • Custom actions
    • Background (lets your app process the results in the background
    • Foreground (launches your app)
    • iOS and watchOS
  • Dismiss action (new in iOS 10)
    • Action performed when user dismisses or clears the notification

Service Extension

  • Non-UI iOS extension (runs in the background)
  • Purpose: Augment or replace the content of visible remote notifications
  • Short execution time
  • Fallback called
  • Can perform end-to-end encryption and add attachments
  • New key – “mutable-content” – to signal that the extension should be called

Q: How can service extensions be supported for multiple versions of iOS?

Advanced Notifications

Video

Media Attachments

  • Requires using the new Service Extension feature in iOS 10
  • Allows the app to download the media before the notification is displayed to the user
  • Available for local and remote notifications
  • Limited processing time and size
  • When added, file is moved and managed by the system
  • GIFs are supported

Custom User Interface

  • Allows you to add your own views
  • No interaction with your views
  • Your app can respond to notification actions

Quick Interaction Techniques for watchOS

Video

What is a quick interaction?

  • Starting a timer
  • Checking the weather
  • Checking an item on your grocery list

Apps need to be:

  • Glanceable
  • Actionable
  • Responsive

How long is a quick interaction?  2 seconds

New kinds of user input

  • Gesture recognizers
  • Digital crown rotation
  • Improved table navigation
  • Support for new notifications framework
  • Support for SpriteKit and SceneKit

New gestures

  • Swipe (discrete)
  • Tap (discrete)
  • Pan (continuous)
  • Long Press (continuous)

Add gestures to groups instead of controls

  • Some system gestures will have precedence
    • Scroll, Force Touch, Long Press

Digital Crown Support

  • Rotations per second
  • Rotational delta (1 full rotation = accumulated delta of 1)

Vertical paging

  • Kind of like paging on iOS – user doesn’t have to go back to table
  • Must use segues for the table

Notifications

  • Similar notification APIs across platforms
  • Can schedule local notifications
  • Background actions now delivered to extension if scheduled on the watch
  • If scheduled on the watch, only delivered on the watch
  • Notification identifiers used to avoid duplicate alerts
    • Apple Watch notifications take precedence over forwarded notifications with the same ID

Complications

  • Recommendation is that all apps provide a complication
  • Providing a complication keeps app in memory
  • Accelerates users into your app
  • Complications can be configured on the phone

SpriteKit & SceneKit

  • Not just for gaming
  • SpriteKit is a good choice for graphing
  • Can use the digital crown for scrubbing across a graph

Drop Wrist

  • Avoid showing the loading indicator
  • Show feedback and then use a background NSURLSession and local notifications

Designing Great Apple Watch Experiences

Video

3 components of a watch app

  • Complication – Any feature on a watch face beyond showing hours, minutes, seconds
  • Notification
  • App

Challenge yourself to use quicker and less complicated user flows

Shoot for 2 second user flows

If you’re going to make an Apple Watch app, you should make a complication

Adding extra large complication style

  • The watchOS Human Interface Guidelines describe all the styles and sizes in detail

Glanceable Notifications

  • PRoide a meaningful title
  • Only show what’s necessary
  • Present important information first
  • Establish visual hierarchy
  • Use color, graphics, and animation

Snapshot Best Practices

  • Anticipate user interests
  • Account for user preferences and contextual factors
  • Be logical and predictable
  • Be recognizable – not radically different than your app
  • Awkward views
  • Prepare to get small

Glances evolved into the Dock, which then caused Glances to become redundant

Simplified Navigation

Stickiness

  • Apps can stick around for 8 minutes on watchOS 3

Improving Existing Apps with Modern Best Practices

Video

Minimum deployment of iOS 8 – this hits 95% of all iOS devices

  • Set it to iOS 8.4.  When iOS 10 is released, set the minimum to iOS 9.3

Resolve issues, such as deprecated APIs

Treat warnings as errors.  Now available for Swift in Xcode 8

Accessibility is as much a part of your user interface as the artwork

New locale-aware APIs

  • Dimension and MeasurementFormatter

Add peek, pop, and quick actions

Run the Swift Migrator

File bug reports – bugreport.apple.com

Incorporate new APIs

Asset Catalogs

Use asset catalogs

UIImage(named:) finds image files whether they are stored in an asset catalog or not

  • It also performs caching

Scaled Assets

  • Provide all versions to avoid scaling on the device
    • Scaling up produces blocky image
    • Scaling down uses a lot of memory on the device

Vector Assets

  • Scaled and rasterized at build time

Both

  • Allows you to provide overrides, e.g. if there is too much detail on the vector to be displayed properly in 1x

Rounded/Capped Images

  • Slices can now be performed in the asset editor in Xcode

Dependency Injection

Don’t put everything in the app delegate and access it from everywhere.

  • Instead, inject required components

Other

Start with data bundled with your app and then download an update.  That way the app starts with data.

Playgrounds

You can now run code in playgrounds that finished asynchronously

  • Import PlaygroundSupport

Can show live views in the playground (e.g. a table view)

You can now include code and resources (e.g. plist files) in a playground that is not in the main window of the playground

Adding Platforms

Design for the platform

Pivot the data model

Visual Debugging with Xcode

Video

Runtime issues

  • Elevates issues encountered at run time to the same level as build time issues
    • Threading issues
    • UI layout issues
    • Memory leaks

Thread sanitizer

  • Data races
  • Use of uninitialized mutexes
  • Unlock from wrong thread
  • Thread leaks
  • Unsafe calls in signal handlers

Xcode can now render blurred views starting with Xcode 8 beta 2

More Auto Layout properties are displayed

Ambiguous layouts are detected at runtime

Advances in UIKit Animations and Transitions

Video

UIViewPropertyAnimator

  • Interruptible
  • Scrubbable
  • Reversible
  • Broad availability of timing functions
  • Running animations can be modified

What's New in UICollectionView in iOS 10

Video

Topics

  • Smooth scrolling
  • Improvements to self-sizing cells
  • Interactive reordering

Smooth Scrolling

  • Cells will be brought in before they are needed
  • Cells will be brought in one at a time instead of a row at a time

Cell Pre-Fetching

  • Enabled by default for apps compiled on iOS 10
  • Can be disabled
  • Do heavy lifting in cellForItemAtIndexPath
  • Do minimal work in willDisplayCell / didEndDisplayingCell
  • cellForItemAtIndexPath prepared cell may never display
  • New delegate for pre-fetching: UICollectionViewDataSourcePrefetching with prefetch and cancel prefetching functions
    • This allows fetching to be performed on a background thread

Pre-Fetching API Tips

  •  Use GCD or NSOperationQueue
  • Use cancelPrefetching API to adapt to shifting user focus

Same functionality also available to UITableView

  • UITableViewDataSourcePrefetching

Improvements to Self-Sizing Cells

Introduced in iOS 8

  • Full support in UICollectionViewFlowLayout – set estimatedItemSize
  • Three options for specifying actual cell size: auto layout, override sizeThatFits(), override preferredLayoutAttributesFittingAttributes()

Picking a good estimated item size

  • Hard to guess
  • Now can be automated in iOS 10 with UICollectionViewFlowLayoutAutomaticSize
  • iOS will use the sizes of all the other cells to estimate the size
  • Works best if cells have similar widths and heights

Interactive Reordering

  • Added in iOS 9
  • Paging support added in iOS 10
  • Behaves similar to reordering apps on the home screen

UIRefreshControl

Now supported directly in UICollectionView, UITableView, and UIScrollView because it is a scroll view property

NSURLSession: New Features and Best Practices

Video

NSURLConnection officially deprecated in 2015

Good sessions from WWDC 2014 and 2015 on NSURLSession

Benefits

  • HTTP/1.1, SPDY, HTTP/2 (RFC 7540)
  • App Transport Security (ATS)
  • HTTP Strict Transport Security (HSTS) – no code changes required
  • Cache, cookies, proxy, authentication
  • Configuration

Avoid 1-task-to-1-session model

  • Have 1 session service many tasks
    • Better performance and resource utilization

HTTP/2 Protocol

  • Multiplexing and concurrency
  • Header compression
  • Stream priorities
  • Server Push (new)

HTTP/2 Server Push

  • Prevent network round trips
  • Server support required
  • Now available in NSURLSession
  • Provides 2x to 3x improvement

Network Statistics

  • NSURLSessionTaskMetrics
  • NSURLSessionTaskTransactionMetrics
    • Request and response
    • Protocol and connection
    • Load info
    • Connection establishment and transmission

Transport Layer Security (SSL) is the predecessor

  • Protects data
  • The RC4 cipher is no longer supported

Command-line tool – nscurl

  • nsurl — enable-rc4 – use to find dependencies on RC4

App Transport Security

  • 2 new keys
    • NSAllowsArbitraryLoadsInWebContent
    • NSRequiresCertificateTransparency

Making Apps Adaptive, Part 1

Video

Takeaway

  • The system is going to do most of the work so you don’t have to

Traits – describe the environment that your application is running in

  • Layout
    • Size Classes
    • Dynamic Type
    • Layout Direction
  • Appearance
    • Display Gamut
    • Interface Style
  • Capabilities
    • 3D Touch

Size Classes

  • Screen size
  • Orientation
  • Adaptation (e.g. multi-tasking)

Takeaway

  • Base layout on available space, not device, orientation, or adaptation
  • Size classes express (user) experience

Only have to think about four combinations of size classes

  • But most commonly just two, because width is most common

If you use UISplitViewController, changes between master-detail and navigation will come for free

traitCollectionDidChange: is the key method for adapting changes in traints

Interface Builder is using the simulator to render views

  • You can now quickly switch between devices and orientations to view how a storyboard would be rendered

Architecting for Performance on watchOS 3

Video

2-second tasks

Complications for all

  • All Apple apps now have a complication

Memory limit

  • 30 MB per application in watchOS 3

Tips for keeping memory footprint down

  • Use appropriately sized images
  • Use appropriately sized data sets
  • Use lightweight APIs
  • Don’t keep around things you no longer need

Resume Time

  • Key path to optimize

Lifecycle – extension delegate

  • applicationDidFinishLaunching
  • applicationDidBecomeActive
  • applicationWillResignActive
  • applicationDidEnterBackground
  • applicationWillEnterForeground (not on first launch)

Lifecycle – interface controller

  • awakeWithContent
  • willActivate
  • didAppear
  • willDisappear
  • didDeactivate

Resume Time Tips

  • Use discretion when updating WKInterface objects
    • Setting a property sends data to the watch, so only set them if they have changed
  • WKInterfaceTable is not a UITableView
    • All cells are created up front
    • Keep the size down – it’s best to keep the size to a maximum of just over 20
    • Avoid reloading a table when possible – use insertion and deletion APIs

Design

  • Glanceable
  • Focused purpose
  • Navigation

Improve layout update performance

  • Setting values on a WKInterfaceConnector are not cached, so only set them wifi they have changed

Think small

  • Keep tasks small and easy to perform
  • Simplify your user interface
  • Make use of new Background Refresh APIs

Focus on resume time

  • Pay attention to WKInterfaceController lifecycle methods (especially willActivate and didAppear)
  • Make use of cancelable operations
  • Optimize when updating your user interface

A Peek at 3D Touch

Video

Static Quick Actions

  • Defined in your app’s Info.plist
  • Available as soon as your app has been installed

Dynamic Quick Actions

  • Created by your app at runtime
  • Available after the first launch of your app
  • Shows after any static quick actions (space permitting) – only 4 total
  • Can include a system icon, custom icon, or Address Book contact

Best Practices

  • Every app should provide quick actions
  • Focus on providing quick access to high-value tasks
  • Make quick actions predictable
  • Be prepared to handle dynamic quick actions from previous versions of your app
    • Include the app version in the info provided with the dynamic action
  • Don’t add functionality that is only accessible using quick actions

Register for previewing in viewDidLoad

  • Set self as the delegate

Make sure that similar looking stuff is previewable in similar ways

Preview quick actions

Peek and Pop Best Practices

  • Content that can be tapped should support Peek and Pop
  • Return a preview view controller consistently – similar looking content should be previewable in a similar way
  • Don’t take too long in the previewing delegate
  • Set the previewing context sourceRect to lift the previewing interface element on-screen

UIPreviewInteraction

Low-Level Force API

  • Normalized access to force data

Using and Extending the Xcode Source Editor

Video

New in Xcode 8

  • New font – SFMono – designed for retina displays
  • Current line highlight
  • Command-Option-Slash – inserts documentation comment block
  • Documentation comments use SFMono-medium for keywords and SFMono-light for other text
  • Image and color literals

Not new

  • Command-Option-] – Selects lines and allows you to move them
  • Command-Control-G – Navigates to search results

Source Editor Extensions

  • Add commands to the source editor
  • Edit text
  • Change selections
  • One extension, several commands
  • They are Application Extensions
    • Each runs in its own process
    • Sandboxed and uses entitlements
    • Gets access to text at invocation
    • Distributable on the Mac App Store

Built into a host application

Extension commands:

  • Your extension’s Info.plist
  • Your extension’s commandDefinitions property, overriding the Info.plist
    • Overrides collection stored in the Info.plist

Speed

  • Text editing is “user-synchronous”
  • Users will invoke your command via typing
  • User changes to a document are prevented while a command is running
  • The user can cancel your command
    • A command that takes a while gets a cancellation banner

How Xcode helps

  • Keeps your extension alive for fast invocation
  • Optimizes data transfer for performance

How you can help Xcode

  • Start up quickly
  • Use GCD and follow standard asynchronous patterns
  • Don’t replace the whole buffer if you don’t need to

Making Apps Adaptive, Part 2

Video

Asset Catalogs

Alignment Insets and Slicing

Dynamic Type

  • Now part of the trait environment with UITraitCollction.preferredContentSizeCategory
  • Set up your text views
    • .font = UIFont.preferredFont(forTextStyle:)
    • .adjustsFontForContentSizeCategory = true
  • Be sure to test with all Dynamic Types sizes

Layout Guides

  • UIView.layoutMarginGuid
  • UIView.readablContentGuide

UIAppearance

Design you app for different adaptations

  • Consider the possible combinations of device, orientation, and size
  • Make designs
  • Define rules for which design to use

Defining Rules

  • Don’t check if size exactly matches
  • Do define Boolean conditions
    • Use size class
    • Compare value to a threshold
    • Compare values to each other

Implement the Designs

  • Find the size of the app
  • Use the rules to decide which design to use
  • Apply the design to the UI

Where does the code go?

  • Don’t put design-specific code in viewDidLoad
  • Put it in viewWillLayoutSubviews
  • This is called very often, so do as little work as possible
  • Find out what has changed since last time
  • Don’t cause a layout loop

Reusable Elements

  • Build your app out of pieces that can be reused in different designs
  • Each piece is typically a view controller
  • View tree and constraints
  • Connections to other view controllers
  • Connections to the rest of your app

Design Object

  • Stores information describing a design
  • Immutable struct for safety
  • Allows comparison

Iterative UI Design

Understanding Swift Performance

Video

Understanding the implementation to understand the performance

Dimensions of Performance

  • Allocated on the stack or the heap
  • How much reference counting
  • Statically or dynamically dispatched

Allocation

Stack – very fast

  • Decrement stack point to allocation
  • Increment stack pointer to deallocate

Heap

  • Advanced data structure
    Search for unused block of memory to allocate
  • Reinsert block of memory to deallocate
  • Thread safety overhead

Structs are allocated on the stack

Class references are allocated on the stack, instances on the heap.  It also allocates more memory than is needed

Changing an instance of a class will also change other instances.

Reference Counting

There’s more to reference counting than incrementing, decrementing

  • Indirection
  • Thread safety overhead

There’s no reference count overhead with a struct that has only value type members

A struct incurs reference counting overhead proportional to the number of reference type members

Foundation added UUID type in iOS 10 that’s a value type (struct)

An enum backed by a string doesn’t require heap allocation

Method Dispatch

Static

  • Jump directly to implementation at run time
  • Candidate for inlining and other optimizations

Dynamic

  • Look up implementation in table at run time
  • Then jump to implementation
  • Prevents inlining and other optimizations

Marking a class as final will allow the compiler to statically dispatch functions on that class

Performance Types

  • Polymorphism without inheritance or reference semantics
  • Protocol Witness Table (PWT)
  • Dynamic dispatch without a V-Table
  • The Existential Container
  • Boxing values of protocol types
    • Inline Value Buffer – currently 3 words
  • Large values stored on heap
    • The Value Witness Table (VWT)
    • Allocation, Copy, Destruction of any Value
  • Reference to Value Witness Table
  • Reference to Protocol Witness Table
// Protocol Types
// The Existential Container in action
func drawACopy(local: Drawable) {
    local.draw()
}
let val: Drawable = Line()
drawACopy(val)
// Generated code
func drawACopy(val: ExistContDrawable) {
    var local = ExistContDrawable()
    let vwt = val.vwt
    let pwt = val.pwt
    local.type = type
    local.pwt = pwt
    vwt.allocateBufferAndCopyValue(&local, val)
    pwt.draw(vwt.projectBuffer(&local))
    vwt.destructAndDeallocateBuffer(temp)
}

Protocol Type Stored Properties

struct Pair {
    init(_ f: Drawable, _ s: Drawable) {
        first = f
        second = s
    }
    var first: Drawable
    var second: Drawable
}

var pair = Pair(Line(), Point())

Expensive Copies of Large Values

let aLine = Line(1.0, 1.0, 1.0, 3.0)
let pair = Pair(aLine, aLine)
let copy = pair

References Fit in the Value Buffer

Indirect Storage with Copy-on-Write

Use a reference type for storage

class LineStorage { var x1, y1, x2, y2: Double }
struct Line: Drawable {
    var storage: LineStorage
    init() { storage = LineStorage(Point(), Point()) }
    func draw() { ... }
    mutating func move() {
        if !isUniquelyReference(&storage) {
            storage = LineStorage(storage)
        }
        storage.start = ...
    }
}

Summary – Protocol Types

  • Dynamic polymorphism
  • Indirection through Witness Tables and Existential Container
  • Copying of large values causes heap allocation

Generic Code

protocol Drawable {
    func draw()
}
func drawACopy(local: T) {
    local.draw()
}

let line = Line()
drawACopy(line)
// ...
let point = Point()
drawACopy(point)

Generic code implements static polymorphism – one type per call context

  • Type substituted down the call chain

Implementation of Generic Methods

  • One shared implementation
  • Uses Protocol/Value Witness Table
  • One type per call context – passes tables instead of using existential container

Specialization of Generics

  • Static polymorphism – uses type at call-site
  • Creates type-specific version of method
  • Version per type in use
  • Can be more compact after optimization

When does specialization happen?

  • Infer type at call-site
  • Definition must be available

Whole Module Optimization

  • Increases optimization opportunity
  • Now enabled by default in Xcode 8

Specialized Generics – Struct Type

  • Performance characteristics like struct types
    • No heap allocation on copying
    • No reference counting
    • Static method dispatch

Specialized Generics – Class Type

  • Performance characteristics like class types
    • Heap allocation on creating instance
    • Reference counting
    • Dynamic method dispatch through V-Table

Unspecialized Generics – Small Value

  • No heap allocation – value fits in Value Buffer
  • No reference counting
  • Dynamic dispatch through Protocol Witness Table

Unspecialized Generics – Large Value

  • Heap allocation (use indirect storage as a workaround)
  • Reference counting if value contains references
  • Dynamic dispatch through Protocol Witness Table

Summary

  • Choose fitting abstraction with the least dynamic runtime type requirements
    • Enables static type checking, allows compiler to ensure correctness at compile time
    • struct types – value semantics
    • class types – identity or OOP style polymorphism
    • Generics – static polymorphism
    • Protocol types – dynamic polymorphism
  • Use indirect storage to deal with large values

Double-Checked Locking and Objective-C

A common problem in software is to do something exactly once – e.g. create a singleton.  A corollary of that action is to do something exactly once in the life of an instance.  I have found myself using the corollary much more frequently as I move away from using singletons, which I’ve done to improve testability.

With singletons, a common solution is to use locking or, to avoid the performance penalty of locking, double-checked locking.  Of course, double-checked locking has issues with most modern languages caused by CPU and compiler instruction reordering.  Objective-C has provided an elegant solution to those problems, but the solution comes up a little bit short.

Creating a Singleton – Single-Threaded

In a single -threaded application, creating a singleton can be done without additional protection, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        s_sharedInstance = [MyClass new];
    }

    return s_sharedInstance;
}

Creating a Singleton – Multi-Threaded

In a multi-threaded application, it’s not so simple as you will want to protect yourself against multiple callers of this method.  A simple solution simply adds a lock:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    @synchronized(self)
    {
        if (s_sharedInstance == nil)
        {
            s_sharedInstance = [MyClass new];
        }
    }

    return s_sharedInstance;
}

The problem with this solution is that you pay the price of locking even though you only need it the first time the method is called.

Double-Checked Locking

A common solution to avoid the penalty of locking is to use double-checked locking.  With double-checked locking you check the value of the static instance both outside and inside the lock, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                s_sharedInstance = [MyClass new];
            }
        }
    }

    return s_sharedInstance;
}

At first blush, it would seem that this would solve the problem of assigning the static variable AND avoiding the penalty of the lock.  The problem is that the CPU and/or the compiler could reorder the memory access instructions.  A solution suggested by Mike Ash inserts memory barriers before accessing the variable and uses the volatile keyword.  The memory barrier, available in libkern/OSAtomic.h, solves the CPU problem and the volatile keyword solves the compiler problem.

+ (MyClass *) sharedInstance
{
    static MyClass * volatile s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                OSMemoryBarrier();
                s_sharedInstance = [MyClass new];
            }
        }
    }

    OSMemoryBarrier();
    return s_sharedInstance;
}

The problem with this solution is that it is still quite expensive in the most common case.  Apple has provided another solution:  dispatch_once.

dispatch_once

dispatch_once is provided with Grand Central Dispatch to execute statements exactly once, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_sharedInstance = [MyClass new];
    });

    return s_sharedInstance
}

This is a terrific solution for use with singletons, but what if you want to use it with an instance?  It actually happens to work, but Apple has a warning against using it in this way in the documentation for dispatch_once:

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.

Hmm, that’s unfortunate.  Here’s hoping Apple will change their implementation.  In the meantime, it would appear that the only solutions for the non-static and non-global case are:

  1. Use a synchronized block for every call.
  2. Use memory barriers.

References

Rolling a Ruby gem back to a previous version

I ran into a problem with the Ruby gem for a tool I use recently when I installed the latest version and then found it was broken.  I wanted to roll back to the previous version, which turns out to be extremely simple.  Here is the command I used and the responses I received:

> sudo gem uninstall cocoapods
Password:

Select gem to uninstall:
1. cocoapods-0.23.0
2. cocoapods-0.24.0
3. cocoapods-0.25.0
4. cocoapods-0.26.2
5. cocoapods-0.27.1
6. cocoapods-0.28.0
7. cocoapods-0.29.0
8. cocoapods-0.30.0
9. All versions
>

I selected 8 in the list, and when I checked the version of the gem after running this command, it had indeed been rolled back.  Simple.  Sweet.  Just what I needed.

CocoaConf 2013 in San Jose

Last weekend I attended CocoaConf in San Jose.  CocoaConf is a technical conference for developers working iOS or Mac OS X.  Workshops and sessions are taught by form Apple developers and important developers in the industry, many of whom have written books.  It was a great conference, both for the content and for the opportunity to mingle with other like-minded individuals.

Resources

My Highlights

  • Beautiful and Shiny – The iOS Graphics System (all-day workshop) – The info is all available, but the workshop was a great forcing function to learn about it and try things out.
  • Unit Testing Your iOS App With Kiwi – Very interesting way to write unit tests. Built on top of the unit testing framework (OCUnit) that comes with an Xcode installation.
  • Cocoa Gesture Recognizers – Awesome flexibility.
  • Stronger, Better, Faster With Instruments And Debugging – Great introduction to using Instruments. One thing I didn’t know is that there are different instruments when you’re connected to the device and when you use the simulator.
  • Exploring MVC-N – My favorite session of the conference. The concept isn’t all that earth shattering – have a single component that is responsible for communicating over the network – but it’s one that we haven’t implemented to date that could simplify our network code.
    • The speaker is really down on 3rd party libraries because you’ve then delegated the knowledge of that area to a library you don’t know much about. Since networking is a core component of most apps, it should be something that is written in-house.
  • Cocoa Design Patterns – Presentation of using the Chain of Responsibility pattern to avoid singletons is very interesting.
  • NSPredicates for Fun and Profit – Very cool way to search through text and collections. Can make that logic very simple (or very complicated if you’re not careful).
  • Advanced Behavior and Performance Testing with UI Automation – Really interesting testing can be done with UIAutomation, but it’s all done in JavaScript and within Instruments.
    • Great list of tools provided in this talk.
  • Making Successful Apps – Good stuff for program and product management, although applicable for anyone designing and building apps.

My Detailed Notes

Beautiful and Shiny – The iOS Graphics System (all-day workshop)

Bill Dudney

  • The Layer of a UIView uses memory for every pixel
  • The frame property is now (iOS 6) a computed value.  Setting the frame sets the center and the bounds.size.
  • We shouldn’t be changing the frame on a view anymore as that messes up auto layout.
    • Note: We don’t currently use auto layout anywhere.
  • If you use the simple masks and shadows APIs, it uses offscreen rendering and is expensive.
    • Example: Rounded corners with clipsToBounds
    • Instead, use clipping masks.
    • Before you ship, always test with Debug -> Color Offscreen-Rendered in the Simulator to see what the app is doing.
  • You should avoid drawing unless you can build it in Photoshop, because drawing is expensive.
  • “Introduction to Geometric Modeling” video by professor at UC Davis who describes how Bezier curves work.
  • Don’t implement gesture handling using touchesBegan and touchesEnded.  Instead, use a gesture recognizer.

Mastering The Project File

Michele Titolo

  • Slides
  • Apparently project.pbxproj files can be converted to JSON, although I couldn’t get it to work.
    • plutil -convert json project.pbxproj

Unit Testing Your iOS App With Kiwi

Pete Hodgson

  • Slides
  • Kiwi is built on top of SenText (OCUnit) using blocks and syntax that looks vaguely like English.
  • Kiwi can handle stubbing and mocking, although he didn’t include any details in his talk.
  • It is recommended that we use CocoaPods to pull in 3rd party software.
  • “Test what you can isolate.”

Keynote:  The People We Work For

Matt Drance

  • Customers
    • Think about how what you are doing (designing, implementing a feature, fixing a bug) will make their lives better.
  • Peers
    • Communication is important in helping the team be productive.  This could be as simple as sending an email to let people know where you left off if you are going on vacation, moving to a different project or group, or leaving.   “Reduce tension in the room.”
  • You
    • Make sure you take care of yourself.
  • Tools

Cocoa Gesture Recognizers

Jonathan Penn

Stronger, Better, Faster With Instruments And Debugging

Kyle Richter

  • Slides
  • This was a fairly basic overview of the debugger and Instruments, but very useful.
  • Breakpoints:
    • Conditional breakpoints appear to be pretty performant.
  • Debugger command line:
    • The list command will list the source code around the current breakpoint.
    • The bt command will list the backtrace for the current break.
  • “Make sure you test against slower devices, such as the 3GS or the 4.”
  • There are different instruments for running on a device and running on the simulator.
  • Leaks that are the same size but aren’t grouped together may be the same leak but for some reason Instruments didn’t group them together.  This is similar to behavior we see in BugSense when grouping crashes together.
  • Other tools:
    • Network Link Conditioner.
    • Blended Layers in the Simulator
      • Using a clear background color requires iOS to composite the view with the background which is expensive.  Avoid clear background unless you can’t determine the background color.
    • Misaligned Images in the Simulator
      • Misaligned images will be slightly blurry.  Normally caused by math errors when laying out views.
    • Slow Animations in the Simulator

Exploring MVC-N

Marcus Zarra

  • Slides
  • If you’re using other people’s code (e.g. a 3rd party framework) you’re probably doing the wrong thing.  Why?  Because you consider this a solved problem but you didn’t write the code and therefore likely don’t understand what that 10,000 lines of code are doing.
  • The concept of MVC-N is that networking is separated out from the view controllers.
  • The NetworkController talks to the network and stores the result in the persistent store – Marcus uses Core Data.
    • Properties:
      • NSOperationQueue
      • NSMnagedObjectContext
    • Method
      • Different method for each type of request
    • How to create
      • Dependency injection
      • Singleton
      • AppDelegate property
  • Have one NSOperation subclass for each network call.
    • He doesn’t recommend using blocks because blocks are not easily cancelable.
    • Another problem with blocks is because of code bloat – a lot of code in one place.
  • For unit testing, he recommends setting up a simple server on the local network that always returns the same result.
  • If you can let network operation fail without notifying the user, do it.
  • Summary
    • Own your network code.
    • Don’t put network code in view controllers.
    • Keep all network code together.
    • All UI should feed from Core Data.
    • Disconnect data collection and data display.
  • http://github.com/zarrastudios
  • Questions:
    • I asked him about using Core Data for data we don’t need to persist (e.g. most of our data) and he recommended it using an in-memory store.
    • NSManagedObjectContext can be used to represent data received from the network, which represents the data as key-value pairs.

Cocoa Design Patterns

Saul Mora

  • You don’t want to release crapps.  You want to release apps.
  • Patterns
    • Chain of Responsibility pattern, aka Responder Chain
      • Call sendAction:to:from:forEvent: to make a request of an object in the hierarchy.
        • Example: Dismissing the keyboard can be done by calling this method on the application object and specifying self for the “from” property.
      • Derive the app delegate from UIResponder.
    • Command pattern
      • We do this with our operations by creating a separate object for each network operation.
    • Template pattern
  • Anti-Patterns
    • Factory, Abstract Factory
    • Singletons
      • Consider a Singleton Manager – Service Locator pattern.

NSPredicates for Fun and Profit

Josh Smith

  • Slides
  • You can use it for scanning strings, arrays, and Core Data.
  • Predicates are basically search expressions which can be strings (BEGINSWITH, ENDSWITH, CONTAINS, etc.) or a block.

Advanced Behavior and Performance Testing with UI Automation

Jonathan Penn

  • Slides and sample code
  • UIAutomation is all in JavaScript in Instruments.
  • It is completely sandboxed so you can’t use NodeJS or other frameworks.
  • You can see screenshots within Instruments as your script runs.
  • You can use the accessibilityIdentifier to display various states in Instruments as you change the state.
  • He recommends including “use strict” at the top of the script.
  • Define tests in a function in the script.  Doing this puts all messages displayed by the script on a single line that can be expanded.  This also sets a log type (e.g. Pass or Fail) and shows a different color on the timeline.
    • He showed raw JavaScript, which was very messy.
    • Then he showed functionalizing the JavaScript so that the tests looked like single statements.  Much cleaner.
  • He showed swiping up and then down repeatedly in a loop to find a memory leak.  Very cool!
  • Tools:
    • Reflector – AirPlay iOS device screen to your Mac
    • UI Screen Shooter – Take screen shots of your app for the app store
    • tuneup.js – Collection of JavaScript utilities that build upon and improve UIAutomation
    • mechanic.js – Lets you take the power of UIAutomation with the simplicity of modern JavaScript CSS selector engines to make your UIAutomation scripts terse and beautiful
    • Bwoken – iOS UIAutomation  test runner runs UIAutomation tests from the command line in the simulator or on the device
    • cisimple – Continuous integration in the cloud
    • Book: Test iOS Apps with UI Automation
    • UIAutoMonkey
    • KIF (Keep It Functional) – iOS integration testing framework

Making Successful Apps

Michael Simmons

  • Co-owner of Flexibits who created Fantastical which was at one point the top app in the App Store.  He also owns the company that does HockeyApp.
  • Why are you *really* doing this?
  • What are your goals?
    • > You cannot be on autopilot.  You have to question everything.  Otherwise, how do you know that what you are doing is right?
    • > (If the UI is good (easy to use, simple, etc.) it will be successful.)
    • Why are you doing this?
    • What do you want?
    • Dream but be realistic!
      • Don’t be afraid to ship your 1.0 with limited features, but communicate with your users what your plans are to provide those features.
  • What is your plan?
    • Too ambitious?  Not enough?  Real artists ship.
  • Who is your audience?
    • Consumers?  Professionals?  Both?
      • How can it be for both?  It can start out simple and then build up as the user uses it.
    • Creating an appropriate app is vital.
  • What is your passion?
    • What excites you?
    • What makes you happy?
    • What underwhelms you?
  • Details you should be thinking about
    • Be the best.
    • Are you doing something unique and original?
    • Marketing is not an evil word.  If you build it, they might come.  Marketing doesn’t have to be sleazy.  It is required to build awareness.
      • Marketing is also about the design of the app and of the icon.
      • They use the Icon Factory for their icons.
  • App Launch
    • Sneak peek/teaser (public beta?).  Create mystique.
    • Last minute details dialed in.
      • For sales, they use Fast Spring for selling from their website as well as selling through the App Store.  This also allows them to offer a free trial.
      • You can create promo codes to make your app available to press or others before you release.
    • Marketing/PR
      • Embargoes are tricky.  He doesn’t use them anymore because when you release through the App Store you don’t have any control on when it is actually available.
    • Launch!
      • You should do your own support because it is the lifeline to your customers.
      • Negative emails are fantastic because your users are passionate about your app.
      • Don’t rely on your users to design your app.
      • 99 cents is not the right price for app.  Is a a marketing tool.  If your app is that good it will sell.
  • So, how do you make great apps?
    • Define your goals.
    • Create a plan.  Or two.
    • Find your passion.
    • Admit your weaknesses.
  • Piwik (http://piwik.org/) – Web analytics.
  • Frequency of updates
    • You want to get an update out at least every 3 months.
    • Don’t update for the sake of updates.
  • 3rd party support (e.g. Get Satisfaction)
    • He doesn’t like them as it gets between you and your users.
    • He hates forums.
    • He prefers email support.
    • He has a policy of responding within 24 hours.  Users love it.
  • Release notes
    • If just “Bug Fixes” include the release notes for the previous version as well.
  • Keywords
    • Don’t use competitor names as keywords.
    • The obvious ones are the important ones.

Mac App: Ejector

Does this ever happen to you?  You download a DMG file to install an application, mount it, then install the app.  At that point you go on your way and forget about the mounted image.  Or how about you have connected an external drive or a flash drive and you can’t get to your desktop easily to eject them.

The Ejector app is a menu bar app that gives you a single place to see all the drives or disk images that have been mounted so you can eject them.  This is one of my must-have apps on my Mac.

Mac Mail and ReplyWithHeaders

I’ve been using Microsoft Outlook 2011 on Mac OS X for a couple years and I finally decided I needed to give Mac Mail and iCal a try.  In Lion (Mac OS X 10.7), Mac Mail has added some great features, but one thing it is missing is including the headers of the original message when replying.  Here is an example of what Mac Mail shows:

On Jun 14, 2012, at 1:03 PM, Geoff Walker wrote:

Outlook shows this:

From: John Smith [mailto:jsmith@example.com] Sent: Thursday, June 14, 2012 12:41 AM
To: MyTeam
Subject: Yesterday’s meeting

I found an add-on that will modify Mac Mail to do the same thing.  Saptarshi Guha wrote ReplyWithHeaders, which is a bundle that can be added to Mac Mail to modify its behavior, and released the source on GitHub.  Here are the steps to use it if you have access to Xcode (the development tool for Mac OS X and iOS):

  1. Clone the ReplyWithHeaders repository by using the following command:
    git clone https://github.com/saptarshiguha/ReplyWithHeaders.git ReplyWithHeaders
  2. Quit out of the Mail app.
  3. Build the ReplyWithHeaders project in Xcode.  This will place the ReplyWithHeaders.mailbundle file in the right place, which is in ~/Library/Mail/Bundles directory.
  4. From a Terminal window, execute the following commands:
    defaults write com.apple.mail EnableBundles -bool true
    defaults write com.apple.mail BundleCompatibilityVersion 4
  5. Start the Console app to help you verify that the installation worked.  In the search bar in the upper right corner of the Console app type ‘Mail’.
  6. Restart the Mail app.
  7. In the Console app you should see the following lines:
    ReplyWithHeaders: Oh its a wonderful life
    Loaded ReplyWithHeaders

You can also find these instructions on the webpage for the bundle.  Pretty cool, huh?

Folding code in Xcode

A colleague of mine has the practice of collapsing all the methods in an Objective C file when he loads it to simplify finding the right method to view. When I asked him how he did it, he couldn’t remember since it was an automatic action. I finally got around to figuring out how to do it.

The feature is called Code Folding and can be done using the pointer, the menu bar, and the keyboard.

Code Folding using the Pointer

You may have noticed the different colored gray bars on the left of your code in Xcode and may have even accidentally hovered over one of them and been treated to a drastic change in the UI. Those gray bars allow you to fold – or collapse – your code. Using those bars, you can fold any size block, such as an if block, a for block, an @synchronized block, or even a whole method block.

Hovering over the gray bar shows you the block that will be folded. Clicking on the gray bar folds the block and shows a yellow ellipsis between the curly braces where the block used to be. It also changes the gray bar to an arrow. Clicking the arrow or double-clicking the ellipsis will unfold – or expand – the folded block.

Code Folding using the Menu Bar

The code folding functionality is exposed in the menus accessible from the menu bar as well.  In Xcode 4, check out Editor -> Code Folding.

Code Folding using the Keyboard

Apple has defined default keystrokes for code folding, but I found that some of them conflicted with keystrokes defined for other functions. In most cases the conflicts were caused by changes I had made – either in Xcode or in Mac OS X Lion – to accommodate writing code.

The following code folding functionality can be controlled using the keyboard:

  1. Fold all methods and functions – Option + Cmd + Shift + Left Arrow
  2. Unfold all methods and functions – Option + Cmd + Shift + Right Arrow
  3. Fold the current block – Option + Cmd + Left Arrow
  4. Unfold the current block – Option + Cmd + Right Arrow

I had to change the fold/unfold block key bindings because they conflicted with the key bindings I had selected for switching between Spaces in Lion. I changed them to Ctrl + Cmd + Shift + Left Arrow/Right Arrow respectively. This, of course, required that I change another key binding in Xcode – the key bindings for fold/unfold comment blocks.

Comment blocks are blocks of comments using /* and */ as delimiters. Since I almost never use this style of commenting, removing the key binding for folding/unfolding comment blocks in favor of code folding/unfolding was a good trade-off for me.

Mac Utility: Save

I’ve been enjoying my switch from Windows to Mac.  However just like Windows, Mac OS X has its quirks and irritations.  There are some very nice changes in 10.7 (Lion) to window management, but one thing missing is to restore window positions and sizes when switching between a single monitor and multiple monitors.

The Stay utility from Cordless Dog solves this problem.  Here is the summary of the app from the website:

What is Stay?

If you’re fastidious about keeping your windows tidy, Stay is for you. Stay ensures that your windows are always where you want them to be, even as you connect and disconnect displays.

The app is available both from the App Store as well as from their website and costs $15 ($14.99 from the App Store).  The difference between the two versions is that the version from the website supports Spaces.  The reason for this is that Spaces support requires private APIs, and Apple doesn’t allow apps submitted to the App Store to call private APIs.  Cordless Dog did a cool thing, though, for those that want to purchase from the App Store but also want Spaces support.  Simply make your purchase from the App Store and then install from the website.

One thing I’m not crazy about is that they app is delivered as a .zip file from the website rather than as a .pkg file.

Functionality Overview

Stay provides the following functionality:

  • Store windows for all applications.
  • Store windows for the current application.
  • Store the active window.
  • Restore all windows.
  • Edit stored windows.

When you choose to store windows for all applications, the app flips through all the windows, which takes more time than you’d think.  If you’re running the version that supports Spaces, it takes even longer, depending on how many windows and spaces you have.

Restoring windows isn’t quite as reliable as I was hoping.  The app uses window titles to identify windows, but some applications, such as Google Chrome, use a relatively transient string – the webpage title – for the window title.  This means as you switch tabs, Stay may not be able to identify the window to restore its position.

Overall, Stay is a big help in window management when switching between a single monitor and multiple monitors.

Git and git-flow command line completion

I switch between the command line and a GUI tool called SourceTree to manage my Git repositories.  When I first installed git-flow, I noticed that the readme talked about command line completion.  It took me a while to get around to installing it, but I have to say that it is really impressive.

Git and git-flow command line completion works like the rest of bash against the file system.  It reminds me a little of PowerShell on Windows (that should tell you how much I know about bash).

To install command line completion on a Mac, you need to find a copy of the git-completion.bash script.  Some of the posts I read on the net seem to indicate that it should be installed with Git in a contrib folder, but I couldn’t find it (showing how new I am on a Mac), so I decided to just clone Git from Git-Hub. Once I had that, I created a link to the script in my ~/bin directory:

cd ~/src/external
git clone https://github.com/git/git.git git
cd ~
mkdir bin
ln -s ~/src/external/git/contrib/completion/git-completion.bash ./git-completion.sh

I did a similar thing for git-flow-completion:

cd ~/src/external
git clone https://github.com/bobthecow/git-flow-completion.git git-flow-completion
cd ~/bin
ln -s ~/src/external/git-flow-completion/git-flow-completion.bash ./git-flow-completion.sh

The next thing to do is to modify your .bash_profile to call those scripts.

source ~/bin/git-completion.sh
source ~/bin/git-flow-completion.sh

Now when you execute git commands from the command line, you can use tab to complete commands, branches, remotes, and features. On top of that, it works for both local and remote elements. Very cool!

Resources

MySQL issue installing Gerrit on Snow Leopard Server

I spent more time than I wanted installing Gerrit on our Snow Leopard Server at work so that we could streamline code reviews.  I’ve found dealing with diffs in email to be rather inconvenient, so I’m hoping that Gerrit will be a big help.

As I went through the process of installing Gerrit, I hit a speed bump at the end of the init process where it couldn’t create a required function (nextval_account_id()).

Here’s a log of what happened:

$ java -jar gerrit.war init -d /Library/Gerrit/

*** Gerrit Code Review 2.1.6.1
***

*** Git Repositories
***

Location of Git repositories   [/Volumes/Data/src/git]:
Import existing repositories   [Y/n]?

*** SQL Database
***

Database server type           [MYSQL/?]:
Server hostname                [localhost]:
Server port                    [(MYSQL default)]:
Database name                  [reviewdb]:
Database username              [gerrit2]:
Change gerrit2's password      [y/N]?

*** User Authentication
***

Authentication method          [OPENID/?]:

*** Email Delivery
***

SMTP server hostname           [exchsrvr]:
SMTP server port               [(default)]:
SMTP encryption                [NONE/?]:
SMTP username                  [devbuilder]:
Change devbuilder's password   [y/N]?

*** Container Process
***

Run as                         [devbuilder]:
Java runtime                   [/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home]:
Upgrade /Library/Gerrit/bin/gerrit.war [Y/n]?
Copying gerrit.war to /Library/Gerrit/bin/gerrit.war

*** SSH Daemon
***

Listen on address              [*]:
Listen on port                 [29418]:

*** HTTP Daemon
***

Behind reverse proxy           [y/N]?
Use SSL (https://)             [y/N]?
Listen on address              [*]:
Listen on port                 [8081]:
Canonical URL                  [http://myserver.local:8081/]:

Exception in thread "main" com.google.gwtorm.client.OrmException: Error in mysql_nextval.sql:
CREATE FUNCTION nextval_account_id ()
  RETURNS BIGINT
  LANGUAGE SQL
  NOT DETERMINISTIC
  MODIFIES SQL DATA
BEGIN
  INSERT INTO account_id (s) VALUES (NULL);
  DELETE FROM account_id WHERE s = LAST_INSERT_ID();
  RETURN LAST_INSERT_ID();
END;

	at com.google.gerrit.server.schema.ScriptRunner.run(ScriptRunner.java:55)
	at com.google.gerrit.server.schema.SchemaCreator.create(SchemaCreator.java:103)
	at com.google.gerrit.server.schema.SchemaUpdater.update(SchemaUpdater.java:52)
	at com.google.gerrit.pgm.Init$SiteRun.upgradeSchema(Init.java:190)
	at com.google.gerrit.pgm.Init.run(Init.java:85)
	at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:155)
	at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:89)
	at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:47)
	at Main.main(Main.java:25)
Caused by: java.sql.SQLException: This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3558)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3490)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2109)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2642)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2571)
	at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:782)
	at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:625)
	at com.google.gerrit.server.schema.ScriptRunner.run(ScriptRunner.java:53)
	... 13 more

The solution is to make one change to the MySQL configuration before initializing Gerrit:

SET GLOBAL log_bin_trust_function_creators=1;

Thanks to Anthony on the Google Group for Gerrit for the answer.