Archive for 'iPhone'

Xcode Transformers – Settings In Disguise

We’re great fans of .xcconfig files and other textua Xcode build process manipulations around here, and here’s some handy undocumented feature tips for you:

Xcode Build Setting Transformations

Xcode supports the ability to substitute the value of build settings using the $(BUILD_SETTING_NAME) or ${BUILD_SETTING_NAME} syntax in a number of places including Info.plists, other build setting values, and .xcconfig files. In these substitutions it’s also possible to add operators that transform the value in various ways. You may have seen one of these in the Info.plist included in project templates:

com.company.$(PRODUCT_NAME:rfc1034identifier)

This results in the value of the PRODUCT_NAME build setting being transformed into a representation suitable for use in the reverse DNS format used by CFBundleIdentifier. So if PRODUCT_NAME is “Whatever App” the resulting string is “com.company.Whatever-App”.

These transformations can be quite useful but don’t appear to be documented, so here’s the list of available operators and what they do…

Note that these operators can be chained, so you can do things like $(PRODUCT_NAME:lower:rfc1034identifier) or $(CONFIGURATION:upper:identifier).

Be sure to bookmark that for next time you’ve got some manipulating setup to do!

h/t: Michael Tsai!

UPDATES:

Sam Marshall writes lots of Xcode-related goodies, check out particularly

The Unofficial Guide to xcconfig files; Managing Xcode; Using Xcode Targets

Continue Reading →
0

Threading Safety First

Now this is a truly epic investigation of the evolution of how to write a singleton in Swift:

THE RIGHT WAY A.K.A. “THE ONE LINE SINGLETON (NOW WITH PROOF!”)

We knew about this “right” method of writing singletons, but we had no proof to back up our reasoning other than postulation … So I decided to do something about it and wrote up every way of initializing a singleton and inspected them at runtime using breakpoints. After analyzing each stack trace for any similarities I came across something interesting – PROOF!

*mic drop*

There’s been a number of other good posts lately in the area of threading and memory safety; we recommend checking out

Atomics in Objective-C

This post talks about the use of OS low level atomic functions (compare-and-swap, fetch-and-increment) to achieve both wait and lock free, thread-safe concurrent algorithms in your iOS/OSX apps.

It introduces a few classes that abstract away the gory details of some of the atomic functions made available by libkern/OSAtomic.h into conceptually simpler components that use Foundation types…

Strong, Weak, and Unowned – Sorting out ARC and Swift

I wanted to stop being unsure about the implications of typing one of those three words before variable / constant declarations, so I finally pulled up the Apple Documentation on ARC and began trying to digest the semantics. This article is an attempt to share what got sorted out in my brain as it regards ARC and Swift…

“Weak, Strong, Unowned, Oh My!” – a Guide to References in Swift

I often find myself worrying about retain cycles in my code. I feel like this is a common concern amongst others as well. I don’t know about you, but it seems like I am constantly hearing “When am I supposed to use weak? And what the hell is this ‘unowned’ crap?!” The issue we find is that we know to use strong, weak, and unowned specifiers in our swift code to avoid retain cycles, but we don’t quite know which specifier to use. Fortunately, I happen to know what they are AND when to use them!

Demystifying Retain Cycles in ARC

Retain cycles in ARC are kind of like a Japanese B-horror movie. When you start as a Cocoa/Cocoa Touch developer, you don’t even bother about their existence. Then one day one of your apps starts crashing because of memory leaks and suddenly you become aware of them, and start seeing retain cycles like ghosts everywhere. As the years pass, you learn to live with them, detect them and avoid them… but the final scare is still there, looking for its chance to creep in.

Tip: Avoid retain cycles without doing the strong to weak dance by passing block parameters instead of remembering to capture weakly.

And Grand Central Dispatch helper frameworks in Swift seem to be quite a thing lately; here’s some for you to check out:

Async: “Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch.”

Eki: “is a framework to manage easily concurrency in your apps that wraps the powerful API Grand Central Dispatch”

GCDKit: “Grand Central Dispatch simplified with Swift.”

iDispatch: “Easy to use wrapper over GCD for iOS.”

KillerRabbit: “THGDispatch module, includes GCD bits such as Queues, Groups, Timer, Semaphore, etc.”

Continue Reading →
0

React Nativity

Appropriately enough for 2015, there’s a bit of a “Back to the Future” vibe about the latest excitement in the app development world:

React Native: Bringing modern web techniques to mobile

React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. The focus of React Native is on developer efficiency across all the platforms you care about — learn once, write anywhere…

This is very exciting indeed, we are breathlessly assured. Seems to strike some chord though … can’t quite place it …

Introducing React Native

… and there’s always something to learn from other frameworks. But if there’s one thing Appcelerator and we as community should learn is that it looks like we have to do a better job at getting the word out. The word that Appcelerator has been doing this for years!

Yes, that was it. And while we’re delighting in curmudgeonry:

React.native isn’t

While we’re on the subject of terminological disasters, Facebook’s react.native seems to be doing a good job of muddling the waters.

While some parts make use of native infrastructure, a lot do not:

  1. uses views as drawing results, rather than as drawing sources, has a
  2. parallel component hierarchy,
  3. ListView isn’t UITableView (and from what I read, can’t be),
  4. even buttons aren’t UIButton instances,
  5. doesn’t use responder chain, but implements something “similar”, and finally,
  6. oh yes, JavaScript

None of this is necessarily bad, but whatever it is, it sure ain’t “native”.

Perhaps despite all this, there is indeed some reason that React Native will displace SDK Native for development in the same fashion that Titanium has not; but we’d bet against it, personally. However, there is significant contrary opinion; here’s some of the more interesting ones, along with some resource links:

Diary of Building an iOS App with React Native

Retrospective on Developing an Application with React Native for the obligatory Wenderlich tutorial

React Native For Beginners – The Next Big Thing?

ReactNative.com has a good spread of news and resource links

React.parts: “A catalog of React components”

Custom Native iOS Views with React Native

React Native Fundamentals

Now, one assertion in the above that is worthy of consideration is that the more functional model of React has its design advantages. But as it happens, there’s a way to experiment with React design that is actually native:

Introducing ComponentKit: Functional and declarative UI on iOS

Building user interfaces for iOS requires lots of imperative code. As a developer, you create views, configure them, and add them to the hierarchy. You then have to implement callbacks to controllers, which in turn must change the state of your views. Implementing this two-way data flow, even for a simple UI, can be tedious and error prone … To tackle this challenge, we wanted a better abstraction. We drew inspiration from React and its functional reactive programming model for building UI and made a native, Objective-C++ library called ComponentKit which is now used to render News Feed in the Facebook iOS app…

And how did that work out?

ComponentKit gave us performance and reliability gains in News Feed UI Rendering and made the system easier to reason about. It allowed us to:

  • Reduce the size of our rendering code by 70%. Manual and intricate layout code was completely removed as it was no longer needed.
  • Significantly improve scroll performance. ComponentKit eliminated many superfluous container views and significantly flattened our view hierarchy. A flatter hierarchy means less time spent on the main thread to render UI.
  • Improve test coverage. ComponentKit made it easy to build modular UI for which each piece can then be tested in isolation. We now have almost all of News Feed UI under test coverage using snapshot tests.

Making News Feed nearly 50% faster on iOS

OK, now this, this intrigues us.

If you want to dive deeper into the details of how ComponentKit works you can check out this article from Adam Ernst or the second half of this @Scale talk by Ari Grant.

Why yes, yes we will give that some very serious consideration. Much more serious than switching to JavaScript!

UPDATES:

Wait, now apps using JavaScriptCore have Apple’s blessing to update themselves without review? Maybe there is A Dynamic, Crazy, Native Mobile Future—Powered by JavaScript after all. We’d noted that possibility way back in 2011, and got a little more interested in 2013, so maybe 2015 is finally the right year for it!

Caravel: “A Swift event bus for UIWebView and JS.”

An iOS Developer on React Native

Continue Reading →
0

PaintCode By Numbers

Been waiting patiently for that vector drawing in code PaintCode vs. Android report we promised last year? Well, that kinda wandered off into the weeds. Oops. However, PaintCode continues its relentless march towards ever greater heights of awesomeness in freeing you from PNG tyranny:

PaintCode 2.3 adds 15+ new features, including SVG export

  1. SVG code generation
  2. PDF, AI and EPS import
  3. Completely rebuilt image export
  4. Animated sequence export (“Great for Apple Watch animations!”)
  5. Copy & paste support from Sketch, Illustrator, Pages
  6. Live shape thumbnails in the Shapes & Groups browser
  7. New multithreaded renderer
  8. Support for cut, copy & paste of entire canvases
  9. Support for canvas multi-selection
  10. New way to find out where your library items are used
  11. New, easy way to replace one library item with another
  12. Replace Symbol with its content
  13. Improved PSD and SVG import
  14. Canvas Arrangement
  15. Built-in feedback form

So it’a a better time than ever to check that out. And besides their own excellent tutorials and documentation, there’s an ever growing oeuvre of tips and samples:

A First Project With PaintCode & The Story of Look Up’s Arrow

Create a Resolution Independent iOS8 App and Set Your Images Free

Using PaintCode to Dynamically Create Images in the iOS Football Manager Game Title Challenge

Working With PaintCode And Interface Builder In Xcode

Xcode Live Views: Killing them softly with PaintCode

Responsive iOS Buttons with PaintCode

Creating Custom Animated Buttons

Increasing The Tap Area Of UIButtons Made With PaintCode

Creating Beautiful iOS Controls with PaintCode

MMScalableVectorView: “Turns static PaintCode or Qwarkee code into a UIView that honors the contentMode property.”

FKRBlockDrawing “is a collection of two classes and one category to make creating artwork in code a lot easier. It’s great in conjunction with PaintCode, where the graphics in the examples project are from.”

Recreating MKUserLocationView is a great walkthrough of how to do a tricky control that highlights the benefits of PaintCode nicely.

And just in case you’re taking this all seriously, here is what we confidently predict is the most chuckle-worthy UISwitch you have ever seen:

A rapid prototype of UISwitch built with Swift and PaintCode

UPDATES:

Recreating Apple Watch Activity Rings in PaintCode

Core Graphics, Part 1: In the Beginning and Part 2: Contextually Speaking and Part 3: Lines

PaintCode Tutorial for Designers: Getting Started and PaintCode Tutorial for Developers: Getting Started

Preview PaintCode images directly in Interface Builder

Continue Reading →
0

Tip: Check Your Layout Privilege

On the off chance you haven’t bothered to read carefully the 8.3 point release notes, having been busy fixing up your broken Swift code and all, there’s a subtle time bomb lurking therein for next time you get it building again:

When linking against iOS 8.3, any code that relies on layout information (such as the frame) of a UIButton subview when the button is not in the window hierarchy will need to send layoutIfNeeded to the button before retrieving layout information (such as button.titleLabel.frame) to ensure that the layout values are up to date.

For example, if you had something like this:

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// code that sets up the button, but doesn’t yet add it to a window
CGRect titleFrame = button.titleLabel.frame;
// code that relies on the correct value for titleFrame

You now need:

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// code that sets up the button, but doesn’t yet add it to a window
; // This is also safe pre-iOS 8.3
CGRect titleFrame = button.titleLabel.frame;
// code that relies on the correct value for titleFrame

Yikes. Not sure if there’s any currently in development, but we’ve certainly used and/or written ourselves many pieces of code of that form that are now problematic. Probably a sound plan to audit all your button-creating code … just in case.

h/t: @sanjeetsuhag via @mariozullo!

UPDATES:

Looks like layout’s got some pretty serious under the hood revisions: for instance this example

If you construct layout constraints manually … pass in nil for the second view, and that contradicts the the attribute being specified, you’ll now get an exception. Previous OS releases appear to have quietly ignored this transgression on your code’s part.

So yep, better give all your layout stuff a good checking under 8.3. It’s the only way to be sure.

Adaptability Changes in iOS 8.3

“IB started respecting the “relative to margin” option for constraints starting in 8.3” may explain your cells looking different.

Continue Reading →
0

Thrash Metal

Since all you Dear Readers seemed to think our Daft Punk allusion last post was clever, let’s do another music callout this time. Not that it really takes a whole lot of clever to connect up Metal with a particularly extreme genre of such, but hey, it gives us an excuse to link to the thrashiest of thrash bands playing the Duke Nukem theme for your post-reading background music, which we just haven’t done enough of so far.

Any-ways, in case like us you’d pretty much skipped over stuff about Metal figuring it was only of interest to game engine writers, there’s some interesting stuff around that people are doing with it you might like to be aware of. In particular, this FlexMonkey post caught @NatashaTheRobot‘s eye (and if you’re not subscribed to her Swift newsletter, you should be):

Two Million Particles at 25 Frames Per Second on an iPad

Following on from my last post where I managed to calculate and render over 1,000,000 particles in realtime, I’ve done some pretty effective tweaking of the code to create an app that calculates and renders (with blur and trails) over 2,000,000 particles at around 25 frames per second on my iPad Air 2…

Not bad, not bad. Also note followup:

Swarm Chemistry: Creating an Advanced GPU Based Particle System with Metal

…With Metal, I’ve been able to create a kernel shader that can calculate and render 4,096 swarm members at 30fps – so that’s 16,777,216 particle interactions per frame or 503,316,480 particle interactions per second! Pretty impressive stuff for a tablet computer!

Code at FlexMonkey / MetalParticles, with UI described in Adding a User Interface to my Swarm Chemistry App on an iPad

So that’s pretty cool, but still a little niche. A good number of you probably run into need for parallel computation, particularly image processing, not all that rarely though, yes? Start over at Metal-dedicated site Metal By Example and check out these articles:

Introduction to Compute Programming in Metal

This post is an introduction to topics in compute (or data-parallel) programming. It is designed to be read before its companion article, Fundamentals of Image Processing. In this article, we will cover the basics of setting up the compute pipeline and executing kernel functions on large sets of data in parallel…

Fundamentals of Image Processing in Metal

In this post, we will start exploring the world of image processing with the Metal shading language. We will create a framework capable of representing chains of image filters, then write a pair of image filters that will allow us to adjust the saturation and blur of an image. The end result will be an interactive app that allows you to control the image filter parameters in real-time…

Back at FlexMonkey there’s a project FlexMonkey / MetalReactionDiffusion building off that described in these posts:

Metal Kernel Functions / Compute Shaders in Swift

Reaction Diffusion Cellular Automata with Metal Compute Shaders

Swift & Metal: 1,000 Reaction Diffusion Solver Iterations per Second

And as long as we’re mining for Metal nuggets here, if this has inspired you to go learn more about it from scratch, here’s some good intros:

Ray Wenderlich’s iOS 8 Metal Tutorial with Swift: Getting Started and Part 2: Moving to 3D

LiquidFun Tutorial with Metal and Swift – Part 1 and Part 2 and Part 3

objc.io’s Metal

An Introduction to 3D Graphics with Metal in Swift

If you want to get more into the rendering side than that, then check out all the rest of the articles at Metal By Example.

UPDATES:

iOS GPU Programming with Swift & Metal

Particles Set Free! High Performance Particles for Swift Developers

Audio Visualisation for iOS with AudioKit & ParticleLab

Rendering Text in Metal with Signed-Distance Fields

Swifter Swift Image Processing With GPUImage

Stream Video Textures into 3D Scene with Metal

The Supercomputer In Your Pocket: Metal & Swift

Understanding PowerVR GPUs via Metal

Continue Reading →
0

A Forest Of Loggers

So since we moved off Lightspeed Pascal as our Macintosh development environment way back in the day, we’ve been toting around this suite of logging, timing, and so forth debugging macros that by this time can be called transparently from .c/.cpp/.m/.mm files in development environments ranging from Lightspeed C through Metrowerks CodeWarrior up to Xcode 6+; but as we gear up to take on our intended New Year’s resolution of shipping a full hand of Swift apps next year … oh wait, there’s no macros in .swift code now! Well, there goes two and a half decades of accumulated cleverness out the window, bah humbug.

Not that it would be too terribly hard to rewrite said suite using NDEBUG and @autoclosure like assert(), but why bother with that when no doubt there’s somebody else’s projects for native Swift logging out there doing that already we can join? And why yes, here’s two that the exemplarily diligent ManiacDev folk have turned up on Github:

XCGLogger looks considerably more active than Swell, so we’ll go with that one. Unless any of you Dear Readers have an excellent reason why not. But long as we’re on the topic, let’s take a look at what Objective-C options checking CocoaPods brings up that we could raid for feature additions … my, there are a lot, aren’t there now?

  • CCLogSystem (5/54/18) “A Log system for iOS.Support print, record and review logs.”
  • CocoaLumberjack (270/4131/705) “A fast & simple, yet powerful & flexible logging framework for Mac and iOS”
  • DLLog (1/2/1) “NSLog-like logging API with support for level and context filtering”
  • GRLogger (1/2/1) “a logger utility for debugging and tracing”
  • LibComponentLogging (5/101/13) “Logging for Objective-C with log levels and log components.”
  • Log4Cocoa (12/80/29) “is a Log4j port for iOS and Mac OS X”
  • MTLog(11/218/24) (ManiacDev) “NSLog replacement for coders!”
  • NALog (1/3/0) “An easy, lightweight, and simple NSLog-based logging tool”
  • NBULog (13/22/5) “Log framework based on CocoaLumberjack…”
  • NSLogger (147/2447/299) “A modern, flexible logging tool”
  • NWLogging (7/14/4) “A minimalistic logging framework for Cocoa”
  • OCLogTemplate (8/9/3) “A flexible logging header for Objective-C”
  • TFLogger (7/2/0) “Dependency free logging library”
  • TULogging (1/7/0) “Better logging that uses ASL log levels”
  • UALogger (11/235/21) “A powerful and flexible logging utility for Mac/iOS apps”
  • WZLog (1/2/0) “A log system for iOS” … and that’s about it not in Japanese.
  • XLFacility (8/97/2) “Elegant and extensive logging facility for OS X & iOS (includes database, Telnet and HTTP servers)”

CocoaLumberjack is pretty much the venerably accepted standard, as the numbers there attest, but some of these othes look interesting too. Particularly that very last one, XLFacility; from the ManiacDev writeup,

Some of the features of XLFacility include:

  • Viewing of logging messages in real-time via Telnet or TCP
  • An HTTP server for viewing real-time log messagess and browsing past logging messages
  • Different logging levels, and macros for easy logging at each level
  • Customizable logging formats
  • An in-app logging overlay that can appear when messages are sent to XLFacility
  • A nice syntax for creating your own custom loggers

With XLFacility you can log to the console, a file, a SQLite database, and you can also view messages in realt-time via Telnet or TCP and there is a built-in http server so you can browse past log messages or see live updates…

That’s some serious feature-laden logging there, that is.

UPDATES:

ZHSwiftLogger: “…will use println() for development and use NSLog() for production.”

PrintlnMagic “An alternative for Swift’s println() function along the lines of DLog.”

SwiftLog “Simple and easy logging in Swift.”

Debug Logging In Swift

Teleport-NSLog: Open Source Library Enhancing NSLog Allowing You To Log To A Remote Server

CleanroomLogger: “provides a simple, lightweight and performant logging API written in Swift”

Learn How People Use Your App – an App Analytics Tools Round-up

ARAnalytics : “is a analytics abstraction library offering a sane API for tracking events and user data. It currently supports on iOS: TestFlight, Mixpanel, Localytics, Flurry, GoogleAnalytics, KISSmetrics, Crittercism, Crashlytics, Bugsnag, Countly, Helpshift, Tapstream, NewRelic, Amplitude, HockeyApp, ParseAnalytics, HeapAnalytics, Chartbeat, Yandex Mobile Metrica, and Branch. And for OS X: KISSmetrics and Mixpanel.”

ARAnalyticsLogger: “A bridge between CocoaLumberjack and ARAnalytics,” derived from CrashlyticsLumberjack

Aspect-Oriented Programming and ARAnalytics

Swiftalytics: “A declarative Swift DSL for your view tracking needs.”

Continue Reading →
2

Prerelease App Store Testing

What, you say, aren’t “prerelease” and “App Store” definitionally contradictory? Why no, no in fact they are not!

How to Test the Final App Binary before It Is Released on the App Store

  1. Manually release the app…
  2. Submit your app for review as usual…
  3. Pending developer release…

… At this point the Promo Codes link appears at the bottom of the app details page.

And apparently promo codes can be requested and work just fine even when the app isn’t technically released yet! Aside from this small caveat:

… when the promo code is for an update, iOS sometimes gets confused. It’s not consistent. But sometimes the App Store app shows an Update button right after the download is complete. It’s not clear to me if tapping the Update button will download the update you really want, or if it will “update” to the latest public release available on the App Store. Sometimes the whole process fails and my update is nowhere to be seen. So don’t be dismayed if need to burn more than one promo code to get the binary you want downloaded onto your device…

Still, it’s pretty awesome to be able to do a final final final test that no showstoppers slipped through into the actual App Store binary and reduce your launch day stress by several orders of magnitude, tisn’t it now?

Continue Reading →
1

NSFileCoordinated iOS IPC

IOS IPC? For reals? Well, for a “your app group” definition of “P”, yep pretty much:

Sharing data between iOS apps and app extensions

You’ll want to use NSFileCoordinator any time you want to read or write your shared files. You’ll also want to implement NSFilePresenter any time you need to know if a file has changed. These were introduced as companions to iCloud, where both your app and the iCloud daemon might want to access the same file. They’re not iCloud specific, though…

There’s still no full IPC mechanism on iOS. NSDistributedNotification hasn’t made the jump from OS X to iOS and probably never will. But file coordination and presentation can serve the same purpose, as long as the apps use the same app group.

When I was adding file coordination and presentation to my demo app, I realized that they could also be used for notifications between an app and its extensions. If one of them does a coordinated write while the other is using a file presenter for the file, the call to presentedItemDidChange happens almost instantly. Notification is the whole purpose of that method, so it makes sense it would work this way. I want to be notified if a specific file changes, and that’s how I get the notification.

But you don’t need to care about the file contents to be interested in notifications. If you just want a notification, choose a file name and use it as the notification mechanism. Any time one process needs to notify the other, make a change to the file. The other will get a file presenter call, and the notification is complete. It feels sort of like a hack but really this is exactly how the API is designed to work.

Cool beans! That opens up the extension useful problem space a good deal, doesn’t it now?

h/t: Michael Tsai!

UPDATES:

Accessing Shared Data from an App Extension and its Containing App

Important: When you create a shared container for use by an app extension and its containing app in iOS 8, you are obliged to write to that container in a coordinated manner to avoid data corruption. However, you must not use file coordination APIs directly for this [UPDATE: in iOS 8.1.x and earlier]. If you use file coordination APIs directly to access a shared container from an extension in iOS 8.0 [UPDATE: in iOS 8.1.x and earlier], there are certain circumstances under which the file coordination machinery deadlocks.

WatchKit Data Sharing: Beware of the NSFileCoordinator and NSFilePresenter

Introducing MMWormwhole

ddeville / LLBSDMessaging: Interprocess communication on iOS with Berkeley sockets

Interprocess communication on iOS with Mach Messages

File Coordination Fixed: “In iOS 8.2 or higher, the obvious approach should now be safe.” as noted above.

Continue Reading →
0

Demassify View Controllers

Nice writeup here on formalizing pattern names for approaches to avoiding that Massive View Controller problem it’s all too easy to slip into:

8 Patterns to Help You Destroy Massive View Controller

View controllers become gargantuan because they’re doing too many things. Keyboard management, user input, data transformation, view allocation — which of these is really the purview of the view controller? Which should be delegated to other objects? …

Data Source

The Data Source Pattern is a way of isolating the logic around which objects live behind what index paths. Particularly in complicated table views, it can be useful to remove all of the logic of “Which cells are visible under these conditions?” from your view controller…

Standard Composition

View controllers can be composed using the View Controller Containment APIs introduced in iOS 5. If your view controller is composed of several logical units that could each be their own view controller, consider using Composition to break them apart…

Smarter Views

If you’re allocating all of your view controller’s subviews inside of the view controller’s class, you may consider using a Smarter View. UIViewController defaults to using UIView for it’s view property, but you can override it with your own view…

Presenter

The Presenter Pattern wraps a model object, transforms its properties for display, and exposes messages for those transformed properties…

Binding pattern

In method form, this might be called -configureView. The Binding Pattern updates a view with model data as it changes…

Interaction pattern

Interactions often include an initial user input (like a button press), optional additional user input (“Are you sure you want to X?”), and then some activity, like a network request or state change. The entire lifecycle of that operation can be wrapped up inside the Interaction Object…

Keyboard Manager

Updating the view after the keyboard state changes is another concern that is classically stuck in the view controller, but this responsibility can easily be shifted in a Keyboard Manager. ..

Navigator

Navigating from screen to screen is normally done with a call to -pushViewController:animated:. As these transitions get more complicated, you can delegate this task to a Navigator object..

h/t: Michael Tsai!

And while you’re contemplating how to split things up into maintainability, also check out

Clean Up The Application Delegate With Initializers

Continue Reading →
0
Page 1 of 100 12345...»