From idea to Apple App Store

I think it’s important as a developer to constantly challenge yourself. This means jumping in cold water and learn new languages and developing on other platforms.
I was interested in iOS development since a long time, but I did’t like objective C. Because swift was just released when I started playing around with app development, I concentrated my learning on swift. It’s a modern language and constantly evolving.

After doodling around with playgrounds and building SpriteKit 2D games from tutorials I decided to learn more about app development. My goal is to build a “Personal productivity” app, which helps to records, measure and optimise my time. I started developing the app in the mid of June 2016 with many question signs above my head. CoreData and especially AutoLayout were absolutely new to me and it took some time and effort get proficient skills.

A parallel project

One month after starting the personal productivity app tried to “Shh…” my baby to sleep. So I thought there must be an app for that. I downloaded  it, but it just played about 15 minutes without a (expensive) in-app-purchase. Because I had some first experience with audio from the SpriteKit development I spontaneously decided to build a simple app for myself. A simple app thats plays continuously a “Shhh…” sound.

A simple prototype with continuous playback was done in about half an hour. But I continued to add features like a more sophisticated UICollectionView layout (and an internal playlist for it), a configureable playback duration, a recording function, and so on.
Because I had to join the Apple developer program to use shared containers for the other app I decided to deliver this app to the app store on the beginning of October.

What I’ve learned

During the development phase which was primarily from the end of August to the begin of October I hit many walls. When you’ve experience and a good skill set for multiple years in another platform you forget this feeling. Getting started is always hard, but if you push the walls again and again you get moving and reach your goals.

I learned a much about AutoLayout and StackViews. When I just started out  I used “git checkout -f” many, many times because I totally ruined the layout with bad constraints or randomly changed “hugging priorities” & “compression resistance”. But after a while things things started to make sense. I’m far off being a AutoLayout expert but I’m quite used to it and will get a working layout without hours of fiddling around.
I heavily used StackViews, which made things much easier – I’m glad I started AppDevelopment after they were available.

Because I store static sounds and recorded sounds in the AppContainer together with 2 pList files (static & recorded sounds) I learned how iOS stores data.

I used Xcode Unit-Testing (XcTest) for the playlist logic and also the BackgoundAudioPlayer. This parts of the app contain much of logic, so It’s good to have a safety net around them. The ViewControllers are not covered with test’s, this may be something to learn at a later point of time.
The PPA app contains a coded UI test, which were not easy to develop. I used the recording function to learn how to control the ui. They are very brittle, but give a good overall feedback. They take about 2 minutes to run, I usually prefer shorter feedback cycles.

The most exiting part was the audio API “AV Audio” itself. Playing a sound is very simple, but playing background audio for a configureable time and recording audio requires a a deeper understanding of the API. For a overall good user experience iOS manages audio playback in sessions. With audio sessions you configure wether you playback and / or record audio, in foreground, background or mixing in with other concurrent playing sounds.

What’s very different to what I’ve worked before was muli-threading in iOS. As many other API’s “Grand Central Dispatch” was a very C like API but very powerful. Performance is very important in mobile apps, I early encountered performance problems while scrolling the UI ViewController. When I started working with async queues I learned more about “ARC and memory management” to prevent memory leaks.

Migration to Swift 3

During development I downloaded a few times an XCode 8 beta version and tried the swift 3 migration. As soon as I had the golden master version (the last before production) I migrated the coding to swift 3.

As apple promised the conversion assistant touch nearly every file. There were also many manual changes necessary. Due tue the “Swift API Design Guidlines” the coding looked really beautiful. As a developer that has not really developed with objective C many API’s usage and names were very C like and horrible to use or read before (NS*, CoreGraphics, GCD, …).

Luckily my codebase wasn’t that huge, because a swift 3 migration requires a lot of work – and can break things.

Handoff to applE – The Review

Every app that is in the apple app store listed, is previously reviewed by apple. They have many guidelines about how apps should be developed and what’s allowed or not. After many testing and reading the guidelines and checklists I submitted the app for an external testing (testflight) review and in about 24h I was allowed to release the app for external testflight testers.

I didn’t expected it, but the final App Store review was successful on the first submit again in about 24h the app was “ready for sale”, after a few hours it was available on the app store. I was sure that I missed something small that would lead to a rejection. A re-review after a minimal app and description change took again about 24h.

What the git!

As a side effect I heavily used git as version control system (which is available at GitHub). I used it already before, but not that much. For this project I tried to commit small changes and for larger I used branches. It worked very well and I finally got some deeper understanding of merging and rebasing. And I learned that it’s quite painful if you wait to long until you merge branches again 😉

I’m still learning more about more advanced topic’s. I worked with SVN and Microsoft Team Foundation Server before, but git is my absolute favourite. It’s so simple and lightweight, but can solve really complex problems.

I recommend reading the free online available book “Pro Git“.

And now?

It started with many problems that lead to more problems. But by the time  it became fun to develop with Xcode and swift. Raywenderlich.com tutorials, videos and sample code were a great help that saved my a lot time reading all the apple documentations.

After playing around with the analysis tools I found a situation that could lead to a race condition. This alone wasn’t worth a re-review and update.  I’ll wait a few weeks for crash reports or any feedback and then submit an update for a review.

In the meantime I continue the development of the initial project. I added a widget (today extension), that can access the app’s core data database, which is now in a shared container. To use the app myself in the near future I’m working currently on a “CloudKit” sync (to prevent data loss).

I’ll definitively continue developing iOS apps. Not to become a 1€ app or in-app purchase millionaire, just for fun.
The fact that Apple and SAP have a partnership shows that there is a market for native enterprise applications – even if SAP has a modern powerful web UI technology. Looks like SAP developments becomes more and more technically interesting with modern ABAP, JavaScript and Swift 🙂

The iOS Projects on Github

Apple App Store – Baby Shhh… (US App Store)

Git – SleepBabySleep / Baby Shh…

Git – PersonalProductivityAssistant / PPA

They don’t know what they want!

Developing software can be frustrating. In a recent discussion with a junior developer she said, that it’s not easy to develop software. In long hours of hard work the result is built as previously discussed and it works. But the customer says, that’s good, but not exactly what we need.

I remember that feeling, It’s disappointing. Short before the deadline the customer want’s something different. Often huge changes to the codebase are necessary to meet the new requirements. The codebase you were so proud of before starts to rot and more and more bugs sneak into the code.

Why haven’t they said upfront what they really want?

Maybe they said what want but you didn’t understand it well enough. Or maybe they just learned what they really need after seeing your product the first time. Many problems are so complex, that’s not easy to plan and communicate everything upfront. And also, life goes on – markets and requirements change.

Your cannot change the facts above. As hard as you try and the more you plan upfront, you’ll need more time for a solution and it will have the same problems.

Try to start small and involve your customers as early as possible. Try to provide value as soon as possible. Start with a small subset of all the features that the customer wants. Show him the result, and in many cases they are happy to have an incomplete solution early than waiting a long time to get a (maybe) complete one.

This way, by involving your customer, you’ll get early feedback. Early changes are easier and cheaper. You’ll also discuss the details of the feature that should be developed next and the customer can re-prioritise continuously. There will by features the customer said “we’ll need this later, I’m sure”, but then skipped over and over again – or dropped.

The customer want’s working software, as soon as possible. It’s our job to deliver it. This requires planning, effective communication and high-quality (tested) code. Design for change, but build only what’s necessary.

You don’t have to use scrum to be agile, learn about the agile principles & patterns. Change your perspective on the current development process.

Have a look at the “Principles of the agile manifesto“.

“Agile” software development is not the solution for all your problems. But the insights you’ll gain will lead you to a better process. Don’t be the slave of a process, use a continuously reviewed process as a tool.

 

Record UI tests in Xcode

In a previous article I gave a short introduction into UI testing with Xcode. It works fine, but sometimes it’s a bit complicated to learn how to interact with the ui elements. This video shows by example how the recording feature helps with this problem.

Demo: Record UI interaction


Continue reading “Record UI tests in Xcode”

Are you a developer or do you just write code?

I am now about 10 years as self taught developer in business, and over the last years I learned the one thing: A good developer must know much more then just how write code!

When you just start out, the technology and the code itself are the most important thing. Learning a programming language and really master it by understanding complex concepts is really hard.
As a beginner, you know the frustration of compiler errors, crashing applications and weird problems of all kind. So often you stood before a mountain of problems and after some time and many tries – you will reach the top of the mountain. You jump up from your chair dancing and shouting Yes! Yes! finally! I got it!
This is a rewarding and motivates you to go on. In the best case you continue reading technical books and try to learn another language. You go on and solve more and more and more complex problems and projects. You hack the hell out of your editor and work long, long hours – you’re on the way to become an intermediate programmer. Some developers stop here. They don’t learn new things – only if they have to, and some even can’t program a fizz buzz game without google.

No matter of what kind you are, something strange happens with your projects – over and over again: A shiny new project begins on a green field with blue sky. As the development continues it start’s to rain and the ground becomes a bit muddy – no problem. Things just slow down a bit.
But then, yeah, then comes the day. The day of the meeting with the customer when you demonstrate the application and he says ok – this is good, but not that, what we exactly need! We would like things to go better this way, and by the way we also need this, and that… and you start to become stressed and angry. Why have they changed their mind? A few weeks and month ago we agreed on doing things as we’ve implemented them? Life goes on, requirements (and the business) change.
The time is running up and the way I developed the application, it will become extremely complicated to change it the meet the new requirements…
Time’s ticking and you start to hack around. The muddy field has become a stormy desert with lava rivers. You just want to survive.  After long days, nights and maybe weekends you feel burned out and are just happy that the project is over. Every requested additional feature is blocked “because changes are too complex” or “too dangerous”. Ongoing bugfixes and happy hours in the debugger are normal.

And again, some developers just accept this as the way it is. It’s always been like this in software development – so what. But others, especially those who continue to read and learn may become sceptical. This can’t be the way how software is developed!

So you’ll learn how to test the code. This is again a very, very hard thing. It sound’s simple, but testing your software and in best case adopting test driven development is hard, really hard. To test your code you have to make it testable. You are forced to learn how you decouple classes and how to apply the SOLID principles. Writing good test’s that don’t act like a house of cards and getting a feeling of how to test what – and what not – requires experience which you’ll gain only be doing it over and over again.

Also at some point you may stumble over agile software development. When you’ll try to adopt it, you’ll see that software development is not just about us – the developers. The agile way of development is absolutely different then the way you’ve done it before. Maybe you started with none or some conception or weeks / months of requirement capturing and planning.
As an agile developer the development lifecycle becomes faster. You strive to get working, high quality software to your customer. Good code quality and a safety net of test’s allow you to add features, that the customer wants in a steady pace. You’ll see the debugger only occasionally and yes, there are bugs, but much less. You automate what’s possible and build short feedback loops (Continuous Integration: Improving Software Quality and Reducing Risk (Martin Fowler Signature Books)
and Continuous Delivery: Reliable Software Releases Through Build, Test, and Deployment Automation (Addison-Wesley Signature)).

When you work agile another thing is also changing: You talk much more often with your project team, the stakeholder and / or the customer. Instead of reading large specification documents you learn what and why to implement something by talking with the customer. You have to learn to be come an effective communicator.

And also you’ll notice that you need to organise your work. Different types of work like business projects, internal projects, operational change and unplanned work. Phone-Calls, Mails, IM’s and other distractions all over the day.  Learn to manage your time, energy and the work. I personally use the Pomodoro Technique and Kanban.

Another thing you have to learn about is yourself: How your brain works and how you learn effectively. Andy Hunt wrote a great book about it: Pragmatic Thinking and Learning: Refactor Your Wetware (Pragmatic Programmers)

Our business is changing so fast, that everybody who don’t do this on a frequent base is falling behind and is risking to become totally outdated.
Don’t stick only to your everyday business, read and learn also about other languages and technologies.

A professional developer is curious and always learning. He is used to uncertainty and fear and comes over it by breaking tasks into small pieces just starts working in them. He makes changes also in very small steps. He knows about procrastination and about the imposter syndrome. He is aware, that clean and tested code is extremely important, because it makes software maintainable. And maintainability is in my opinion the most important aspect, more important then performance.

Those are some of the things, that I would say to myself if I could travel back in time. That would have made many things easier…. because this is not possible I’ll have to continue to learn from my failures. I want to stay a passionate developer!

XCode iOS UI testing

As Martin Flowler described in his article TestPyramid, the UI should be the highest (and not the only) layer of the tests.  They are a safety net and errors detected on this layer can point to missing test’s on a lower layer. Automated UI test’s tend to be brittle, because every change in the UI can result in failing test’s.

Since version 7 XCode supports UI tests, with test classes deriving from XCTestCase:

Here’s an example test:

class PersonalProductivityAssistantUITests : XCTestCase {
    
    var app = XCUIApplication()
    var toolbarAddActivityButton: XCUIElement?
    var activityInputField: XCUIElement?
    //...
    var timeLogSaveButton: XCUIElement?
    
    override func setUp() {
    	super.setUp()
    	
    	continueAfterFailure = false
     
    	app.launch()
    
    	activityInputField = app.textFields["textEditActivity"]
    	toolbarAddActivityButton = app.toolbars.buttons["Log Time"]
        // ...
    	timeLogSaveButton = app.navigationBars["Time Log"].buttons["Save"]
    }
    
    override func tearDown() {
    	super.tearDown()
    	
    	app.terminate()
    }
}
func testCanAddAndEditAndDeleteActivityFromTable() {
    //
    // Add
    //
    // Open the add time log view
    waitForElementToAppear(toolbarAddActivityButton!)
    toolbarAddActivityButton!.tap()
    toolbarAddActivityButton!.tap()
    
    // Type new time log informations
    waitForElementToAppear(activityInputField!)
    let initialActivityName = getActivityNameWithDateTime()
    typeActivityName(initialActivityName)
    labelActivity?.tap()
    
    buttonPickDateTimeFrom?.tap()
    setDatePickerValues(monthAndDay: "Aug 1", hour: "10", minute: "30", amPm: "AM")
    setDateTimeFromButton?.tap()
    
    buttonPickDateTimeUntil?.tap()
    setDatePickerValues(monthAndDay: "Aug 1", hour: "11", minute: "15", amPm: "AM")
    setDateTimeUntilButton?.tap()
    
    timeLogSaveButton?.tap()
    
    // Verify element has been added
    XCTAssert(getTableStaticTextElement(initialActivityName).exists)
    
    //
    // Edit
    //
    // tap the actiity to open the add/edit segue
    getTableStaticTextElement(initialActivityName).tap()
    
    let changedActivityName = "\(getActivityNameWithDateTime()) #test"
    waitForElementToAppear(activityInputField!)
    clearAndTypeActivityName(changedActivityName)
    
    timeLogSaveButton?.tap()
    
    // Verify element has been modifed
    XCTAssert(getTableStaticTextElement(changedActivityName).exists)
    
    //
    // Delete
    //
    // Swipe up until the new element ist visible
    doSwipeUpUntilTableStaticTextIsHittable(changedActivityName)
    // Swipe left and push delete button
    doDeleteTableRow(changedActivityName)
    
    // Verify the element has been deleted
    XCTAssert(!getTableStaticTextElement(changedActivityName).exists)
}

This is how it looks like, when it runs in the debugger:

You can find the full test in the latest version of my learning app PersonalProductivityAssistant @github.

Learn more about recording UI tests.

iOS Stack Views

Building layout’s for mobile apps is complex because of the many different device screen sizes available. In iOS development it makes a huge difference if you test your app with an iPhone 4, 5 or 6.

So instead of drawing a fixed layout, we place controls and describe the layout with constraints (distances between controls, distance to margin, equal widths…).
Autolayout constraints are tricky, and in iOS 9 Apple introduced the Stack View to simply building app layouts.

If you know HTML, you’ll be immediately familiar tho the concept. Stack Views are like simple tables with row, cells and layout options.

In our sample app we use multiple nested horizontal and vertical stack views to build the layout.

Stackview_Illustrated

Demo

Swift API Design Guidelines

I recently watched the WWDC ’16 Session “Swift 3 API Design Guidelines” and I’m amazed about about apples direction with Swift.
I started playing around with Swift when it was announced at WWDC 14, and since then lot’s of things have changed. Swift, which is now open source, is constantly evolving and version 3 brings major changes.

The API Design Guidelines are still under development, but they’re worth studying. I love clear and focused code that can be read like a story.

Apple also announced, that the whole swift standard API is being reviewed to conform the API design guidelines.
Most current API’s like Cocoa which were originally developed for Objective C. Working with this API’s in swift feels somehow awkward. The necessary changes to migrate existing code bases will be high, but XCode will support it with “Fix-It’s”.

This is a huge announcement, and it shows again, that apple pushes developers towards the Swift language.

The “Elephant” (the C libraries) will be ported to swift too. Instead of using the global “stringly” typed functions with awkward parameter labels, we’ll be able to use well designed and strongly types swift classes.

Interested in more details? Have a look here.

Single Responsibility Principle

The single responsibility is very simple:

A class should have only one reason to change.

Robert C. Martin, SRP - The single responsibility principle

As an example let’s look at a sensor class, which should report it’s status and readings into a text file:

The class sensor has multiple responsibilities: it represents the sensor with it’s data, knows how an export file content should look like and how  to export it to the filesystem.

This is clearly a violation of the single responsiblity principle. Continue reading “Single Responsibility Principle”

Open-Closed Principle

Your company sells temperature sensors and software for it for many years. For the last 5 years there we produced only indoor sensors.
Yesterday your boss came around and told you, that you’ll now sell also outdoor sensors.
There is a class that feeds the gui with the average temperature of multiple sensors. You’re assigned the extend the average temperature class, which look quite messy after your change:

Before your change it simply took a List<IndoorTemperatureSensor> and it had only one for loop. But look at this – feels like we’re missing something….. Continue reading “Open-Closed Principle”

Liskov Substitution Principle

The Liskov Substitution Principle (LSP) says: “Let  \phi(x) be a property provable about objects x of type T. Then  \phi(y) should be true for objects y of type S where S is a subtype of T.” (Wikipedia)

That means: A derived class should by able to be replaced by another object of it’s base class without errors or modified behavior of the base class. Continue reading “Liskov Substitution Principle”