Monday 7 October 2013

Xcode 5 support for iOS6 SDK

Issue:

1. You're device is running iOS 7 and so, any apps you deploy to it have to be deployed from Xcode 5.
2. You have a project that you'd like to run that has a target SDK of iOS 6. This project uses things like the camera or microphone that have to be tested on a real device?

Xcode 5 only ships with support for iOS 7 targets. Blah. But, you can add support for earlier targets if you can get your hands on those earlier SDKs.

I needed iOS 6 to run the PhotoPicker sample project on my device. I found that in my Xcode 4 installation at

/Applications/Xcode4.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk

Copy that into the same directory for you Xcode 5 installation and you're off.

Thursday 19 September 2013

Presentation at Brooklyn iOS Meetup

I had the opportunity to put a presentation together for the Brooklyn iOS meetup recently and decided to do one based on 'Lessons Learned' from a self-taught stand point. I am an iOS developer largely self-taught and many things I learned along the way, I wish I had known earlier!

I think the meet-up has a range of people from lots of different experience levels and I wanted to engage all of them to also talk about what they've learned that they wish they knew earlier.

It went in a really cool direction with a lot of discussion around the tools people use. A lot of a developers power is in the tools they use and it seems like the iOS space is exploding with new and awesome tools to help you write apps more efficiently.

Here's the video of the presentation.



Also, a lot of tools were mentioned by audience members in the discussion following the presentation.. I'll mention here some of the tools I discussed and those mentioned by others:

Mentioned in presentation:

PaintCode, CocoaPods, AFNetworking, HockeyApp, TestFlight, RestKit(verdict: avoid), and MagicalRecord.

Mentioned in discussion:

iExplorer, Reveal, ImageOptim, Crashlytics, Pop, and Envision.

Saturday 14 September 2013

GoFest Released!

My first app released to the App Store, GoFest was released today.



You can find it there here.

It feels pretty good! GoFest is an app for beer festivals and will be hosting it's first festival in 2 weeks at New Orleans on Tap.



Thursday 5 September 2013

Metadata Rejected!

Rejection feels horrible doesn't it? It feels even worse when you could have avoided it so easily!

I submitted my first iOS app, GoFest, to iTunes Connect last week and just got notice back yesterday that it's been rejected because of it's metadata. What does this mean? Well, in my particular case, it's because I submitted my 4" retina screenshots were taken on a device running iOS 7. Doh! The app itself targets iOS 6, but because the phone I took the screenshots on was running iOS 7, they're not accepted.

I wish I had lots of devices around running all the various iOS versions available.. but alas, I do not. So, retake the screenshots. Resubmit. 

Tuesday 20 August 2013

Deploying an Echoprint server to EC2

For my current client work, I recently needed to deploy an instance of the open-sourced Echoprint server to the cloud. Echoprint is written in Python and uses Tokyo Cabinet and Tokyo Tyrant as it's data store. I found the only cloud hosting option available (given these technologies) was a custom Amazon EC2 environment. Now, I'm not an EC2 expert. And I must say their documentation and tutorials are both confusing.. and frequently out of date. It was a bit of a headache to get everything setup and configured.. so I thought I'd document it!

Here goes, if you'd like to setup the Echoprint open-sourced project on an Amazon EC2 instance... here's what you have to do. (As of Aug, 2013)


Setup an AWS account and launch an EC2 instance


Create (or login to) an Amazon AWS account and go to the management console. Navigate to your EC2 dashboard and click 'Launch Instance'. From here, choose the 'Quick Launch' wizard. This will be fine just to get us going. A few things to note:

1. Create a new public/private key pair for this server. We'll be using this later to setup ssh access. If you can download it now we'll get back to this later.

2. Server type. I chose the default Linux AMI, this is fine.

From here, finish up and click 'Continue' and then 'Launch'. This should launch an virtual server for you.. which is what we want!

From here, we need to be able to access this machine from our local computer. We'll need to setup SSH access for this. Download CLI tools. Confusingly these are called either the CLI tools or the API tools from different places in the AWS documentation. They are the same thing. Jeez!

I created a local directory where I would store all my EC2 stuff. I recommend doing the same. In a terminal execute:


> mkdir ~/.ec2

Unzip and move the bin and lib files from the CLI tools you just downloaded into this directory.
Move the key pair we created and downloaded during the wizard into here too.

You'll also need to update the permissions on that key-pair file.

> chmod 400 ~/.ec2/saskey-ec2.pem

Make sure the following environment variables are set. You'll have to get your AWS access and secret keys from the AWS console to set these variables. They are necessary. On a mac:

> vim ~/.bash_profile

Add:

export JAVA_HOME=$(/usr/libexec/java_home)
export EC2_HOME=~/.ec2
export PATH=$PATH:$EC2_HOME/bin
export AWS_ACCESS_KEY=AKIA***********FRS55A
export AWS_SECRET_KEY=u/ixxR*****************XsTfZl64I/H
export EC2_PRIVATE_KEY=$EC2_HOME/saskey-ec2.pem

Save and close (esc -> :wq!)

> source .bash_profile

Confirm everything is working by running the following command. Get the instance id from your ec2 instance console. It should look something like this: ec2-xx-xx-xx-xxx.compute-1.amazonaws.com.

Now we can ssh into our new linux server!

> ssh -i ~/.ec2/saskey-ec2.pem ec2-user@ec2-xx-xx-xx-xxx.compute-1.amazonaws.com

You should see something like this:

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

[ec2-user@ip-xx-xxx-xx-xx ~]$


Prepare This Server for Echoprint


We need to get the appropriate things onto the server:
Requirements for the server:
Java should be on there. run > java -version

Python should be on there. run > python --version

I'm running Python 2.6.8, so no need to worry about the simplejson

We need to install Tokyo Cabinet - run the following:

> wget http://fallabs.com/tokyocabinet/tokyocabinet-1.4.48.tar.gz
> tar -xvf tokyocabinet-1.4.48.tar.gz
> cd tokyocabinet-1.4.48
> sudo yum install gcc
sudo yum install zlib
> sudo yum install zlib-devel
> sudo yum install bzip2-devel.x86_64
> ./configure --enable-off64
> sudo make
> sudo make install

We need to install Tokyo Tyrant - run the following:

> wget http://fallabs.com/tokyotyrant/tokyotyrant-1.1.41.tar.gz
> tar -xvf tokyotyrant-1.1.41.tar.gz 
> cd tokyotyrant-1.1.41
> ./configure
> make
> sudo make install

Install the Echoprint project


Now we need the Echoprint project itself. I'm going to pull it from the Github project.

> sudo yum install git.x86_64

Go make a fork of the echoprint github project and git the github address. You'll need it below.


> cd /usr/local

> git clone https://github.com/your-git-id/echoprint-server

Now you've got the Echoprint project. Let's fire it up. Everything is installed and ready to startup.

Starting Solr (The Echoprint project uses Solr to index it's audiofingerprints)

> cd solr/solr
> java -Dsolr.solr.home=/usr/local/echoprint-server/solr/solr/solr/ -Djava.awt.headless=true -jar -DSTOP.KEY=YOURKEY -DSTOP.PORT=8079 start.jar

As a note, the logs will now output to: /usr/local/echoprint-server/solr/solr/logs


Stopping Solr (You may need this later)

> java -Dsolr.solr.home=/usr/local/echoprint-server/solr/solr/solr/ -Djava.awt.headless=true -jar -DSTOP.KEY=YOURKEY -DSTOP.PORT=8079 /usr/local/echoprint-server/solr/solr/start.jar --stop


Start Tokyo Tyrant

> sudo mkdir /var/ttserver

> sudo chown ec2-user /var/ttserver/
> cd /usr/local/sbin
> ls
nohup ttservctl start &
Starting the server of Tokyo Tyrant
Executing: ttserver -port 1978 -dmn -pid /var/ttserver/pid

Done

Start Echoprint API Server


sudo easy_install web.py
> cd /usr/local/echoprint-server/API
> nohup python api.py 8080 &

nohup because of ssh session




Make it Accessible to Outside world


If you'd like this accessible to the outside world.. to later do your importing/querying, you'll need to open up the port the Echoprint API server is running on. W
e have to tell our EC2 instance to do this. We do that by adding a rule to the security group's inbound rules, as shown below.



Now you're ready to import and query. Reference the Echoprint project documentation for instructions on how to do this!



Monday 20 May 2013

Start-ups & Growth

I've been spending a lot of time exploring the start-up scene here in NYC. I've got my own, GoFest, that I'm nurturing. I've also been looking to get involved in another. Finding a team with the right mix of people and doing something that fits for you is difficult. As I've been exploring and searching for a start-up to join, I've been learning more about evaluating their business models for risk and potential success. There are lots of angles to come from in doing this, but I've found the easiest is to root everything from the most important central point. Growth.

It seems unanimous that what makes a start-up a start-up is growth. It must attain and maintain (while it's market/infrastructure allows) rapid growth. In this post (whose primary sources are The Lean Startup and Paul Graham) I will examine the definition of a start-up from the view point of Growth. In doing so, I'll cover a number of topics that I've found foundational.

  1. The types of business models capable of rapid growth.
  2. What does this growth look like? How long must it be maintained?
  3. How is it defined? Revenue vs user-base.
  4. Targeting and strategizing to reach rapid growth.

Let's look at these one by one!

Business Models Capable of Rapid Growth


Lots of businesses are started each year.. only a fraction can achieve the rapid growth start-ups aim for. What sets them apart? There's a definitive difference in the business model. For a business to achieve the rapid growth of a startup, it must do, at least, these two things.
  1. It must make something many people want.
  2. It must be able to reach and provide that something to almost all of the people wanting it.
How do startups achieve both of these? Frozen yogurt has recently exploded in popularity. Does selling frozen yogurt equate to a start-up? People everywhere are demanding more frozen yogurt. That satisfies #1. Opening a frozen yogurt shop around the corner from your house doesn't mean you can reach and serve everyone who wants to buy frozen yogurt, however. You will be limited to those who can and are willing to come into your frozen yogurt store. So, businesses like these do not satisfy #2 of the above criteria.

This is why businesses like Etsy, Pinterest and many more have been tagged as super successful startups. They are able to reach anyone who wants to use their service (and has access to the technology that enables them to do so - PC, mobile phones, etc..).

One further thing to note here is that rapid growth is enabled because each new customer who receives service should be, relatively, cheaply acquired. Your infrastructure must support each new user. But, as with Etsy and Pinterest, this can be done in an automated fashion where each new user takes minimal if not zero human interaction. There are still start-ups where this price is not as cheap. If you're selling tangible products you must have the inventory and the workforce to stock, package and ship the items you sell. Allowing for rapid growth with these businesses can be a bit more tricky, to scale things efficiently, but these are still start-ups if they can manage it. (Examples of this are Amazon or many of their acquisitions. Zappos, Endless, etc..)


What is Rapid Growth?


Understanding the business models capable of becoming startups helps to define what this rapid growth looks like. It seems that start-ups go through some pretty standard stages.

  1. Initialization. This is the declaration of intent to start a company and the initial work to lay some framework in place and get the right team of people together. There's probably not yet a customer-base at this point, so growth is typically zero.
  2. Product development. This is where growth is important. If you follow the Lean Startup methodology (the bible for startups) you should be getting an MVP in front of customers as early as possible and begin getting feedback. If you use this feedback to drive your product development, you'll hopefully see customer growth during this phase.
  3. If product development goes well, and something is built that customers love, a business can grow into a large company. It's when a business/business model reaches the limits of it's market or infrastructure capability that growth could start to slow. 
Reaching the final stage doesn't mean the end of growth. It may for a particular product or business model. But, this could be the point when more innovation happens and new markets/products/services are developed. The cycle can happen all over again!


Revenue versus User-base


This question would not have come up 10 or 20 years ago. Previously, a business MUST define their growth by revenue. If it wasn't making money, it wasn't growing. Today, there are more options.

Again, growth rules out. Because rapid growth is only possible by expanding your user-base, it is debatable about whether this should be prioritized over revenue or not. It seems that today, loyal non-paying users are valuable. Facebook has 80 million users. These users are extremely accessible for any contact Facebook wishes to make. This is valuable. Facebook was valued at $104 billion during it's IPO. While Facebook has yet to capitalize on it's user-base, there is trust that there is money in this model.

Still, a strong revenue model should be at the foundation of your business model if possible. The short customer feedback loop returns here. Testing out how to charge for you product or service as it's developed is the path to success. You can determine which features customers are willing to pay for and which one they're not.


Targets and Strategizing


These feedback loops with your customers are what should drive product development and inevitable drive your growth. This is how waste is reduced. If you're building something that customers love it is a success! If you're building something they don't want, it's best to find out as soon as possible. Get it or at least a minimum version of it in front of them as soon as possible. And find out if they think it's valuable or if your assumptions about how they'll receive it are correct.

If you can fake a feature to get customer feedback sooner, do it! I particularly liked the Zappos case study used in the Lean Startup around this topic. Instead of building a complete online shoe store, together with inventory, the founder of Zappos got permission from local shoe stores to photograph their stock. He put the photos online to find out if people were willing to buy shoes over the internet. (A core assumption in his business model.) For each purchase he would go to the store and buy the shoes, mailing them to the customer. This is not a sustainable model.. but it proved that people would buy shoes online. Valuable customer feedback. He could them move on to the next assumption that he needed feedback on, learning from the interaction with his customers as he went.

The take away is to, again, let growth drive your progress. Target the growth of your customer-base and the revenue it generates in the decisions driving your product development. If you take things in one direction and see no growth, it may be time to try something else. (The pivot! - as stated in the Lean Startup.)

In conclusion


This is all really just scratching the surface on this topic. After reading the Lean Startup and several of Paul Graham's posts on the topic, I really liked the idea of basing all thing on Growth. It's easy to ask at each decision-making point. Will this lead to growth? How can we test that quickly?

Tuesday 9 April 2013

Heroku Dyno-wha??



I've been using Heroku for a few months to host rails app that serves as the backend to a iOS app I've been working on. Heroku has been awesome because it's incredible easy to deploy your web app to a production environment seamlessly.

How does all of this work behind the scenes, however? Let's start with what Heroku calls the 'basic unit of composition'.

Dynos


These are essentially each a virtualized Unix container. You execute commands against them. They start out with a default environment (Heroku's Cedar stack). When your app gets installed onto one of these (as a slug.. more on this later!) commands are executed against it based on your app and it's dependencies.

Web vs. Worker dynos

Web dynos serve web requests. If your web requests trigger things like fetching data from remote APIs or uploading data to S3, these can potentially tie up your web dyno. Worker dynos come in here. You can use a strategy that delegates these processes to a job queue and worker dynos will pick things up from this queue. 

So, how do you scale these two types of dynos?
  • Use more web dynos to support more concurrent users
  • Use more worker dynos when your job queue starts getting backed up.

All manual activity like console sessions, or rake tasks trigger a 'one-off' dyno where they run in isolation. This includes all of your 'heroku run' this or that commands? 

The Job Queue

This image is a good visualization for how it works.



Backgrounding tasks or processes is a concept. Heroku doesn't define how to implement this. With RoR, I've used Resque successfully.

If the user request that triggers the job needs to await the response, you do need to come up with a strategy for getting it to them when the process finishes. Polling to see when their job has finished is generally acceptable.

Dyno Management

What manages these different dynos and makes sure they're in sync? Heroku uses it's dyno manifold to do this. When you deploy new code, all of your app's dynos are restarted. The dyno manifold also monitors your dynos for errors or issues and restarts or moves them accordingly. I think the way the dyno manifold is implemented is one of Heroku's secrets as I haven't been able to find documentation anywhere. They do say that it coordinates your dynos, manages the programs that operate your app and generally allows you to remain hands-off in how it works.

Slug Compilation

When you git push to Heroku, the code is received by the slug compiler. This transforms your repository into a 'slug'. These are precompressed and pre-packaged copies of your application optimized for distribution by the dyno manifold. When you scale your application by increasing web or worker dynos, these slugs are distributed and expanded on each new dyno as well.

Dyno Idling

One thing you'll care about immediately after beginning to use Heroku will be the dyno idling policy. If your app has only a single web dyno running (this is the default and free option), it will idle out - irrespective of the number of worker dynos. This means that if you have no web requests for 1 hour, your app is effectively put to 'sleep' (idled). 

Subsequent requests to an idled app will result in the dyno manifold for the app being signaled to unidle or 'wake up' your dyno. This can result in a delay of up to 15 seconds... sometimes longer. Pretty annoying and incentive to increase your number of web dynos to ensure one is always there to receive a request.

Check out the Heroku documentation for dynos as well. This is where I got most of my information!

Wednesday 20 March 2013

Multiple MOCs - Why?

I've been using Core Data with my current iOS app since early days. I've been learning more and more about the idiosyncrasies of Core Data and this magical thing called the 'Managed Object Context'.

What is the Managed Object Context?

I've heard it described as a scratchpad for you persistent data store. You can use it to represent the current state of your data store, or it can function to hold temporary data... that won't be or hasn't yet been persisted to your data store.

I think knowing these functions and thinking about them when you first start working with Core Data and managed object contexts is important. Otherwise, you ask yourself... 'Why, do I have to go through this thing to talk to my data store'.

After you understand this, you might ask yourself.. 'Well, why do I need to hold temporary data..? Or hold data before persisting it?'

I know of few cases where this is useful.
  1. Entity creation that spans multiple screens. As a ex-web developer I can think of what a pain it is to do this in the web world. If the user cancels half-way through, you need to ensure that nothing has persisted to the database. In web, you would have to have some fancy javascript or session storage going on to make this work. It's a huge pain! If you use something like an MOC to store this temporary object while the user builds it out, you don't have to persist it until it's completed.
  2. Data synchronization. Consider a situation where the user creates some entity that needs to be persisted to a back-end server. One strategy for doing this involves hold that entity in an MOC and only merging it to the main MOC and underlying data store when it has successfully been persisted to the back-end server.
I bet there are lots of other useful ways of using multiple MOCs. I'm just starting to explore this realm of Core Data and will update this post if I find other use cases!

Tuesday 12 March 2013

Property Attributes and Definition in iOS

Properties are an alternative to defining instance variables and their corresponding accessors methods. Let's go over the difference

Defining a Property vs. an Instance Variable


Without Properties

With Properties

What happens behind the scenes here are declarations for you accessor methods. This means with the above header and implementation code, you can operate on an instance of this object as follows.

Property Attributes


Each property has a set of attributes that describe the behavior of the accessor methods for that property. Here's an example.

There are three property attributes. Two of these must be specified and the 3rd has a default.
  1. The first attribute specifies either atomic or nonatomic. This has to do with multi-threading. Let's just say here that if you're doing a standard iOS app you should be using nonatomic.
  2. The second attribute specifies either readwrite or readonly. This tells Objective-C whether it should generate a getter and a setter(readwrite)... or just a getter(readonly).
  3. The final attribute has to do with memory management, which I've talked about in more detail here. The options here are weak, strong, or assign. Assign is the default which can be used for primitive values that don't point to an object. (like int)

iOS memory management with ARC

I've been learning iOS development over the last few months. I've been lucky enough to be working with iOS's ARC or automatic reference counting. This is what was introduced in iOS 5 and makes life a lot easier for iOS developers.

To understand how ARC works, a few concepts involving application memory need to be considered.

The Heap

This is the part of memory where all Objective-C objects are stored. When you send the alloc as a message to a given class, a chunk of memory is allocated from the heap for this new instance. This chunk includes space for the object's instance variables. However, if these instance variables are references to other objects, those objects are stored in their own heap allocation.

Pointers are used to remember where objects are stored in the heap.

The Stack

If the heap can be visualized as a heap of objects we reference via pointers, the stack can be visualized as a stack of frames (or chunks of memory). Frames from the stack are allocated as methods are executed and they store variables declared inside the method (i.e. local variables).

If you think about it. Most programs start by running some sort of main function. This would be the first frame on the stack. If it calls another method which then calls another method... each of these would get new frames allocated from the stack. As each method finishes, it's frame is popped off the stack and destroyed.

Pointers

These point to objects stored in the heap.

These can exist in 2 forms:

  1. As references from the local variables defined by methods using frames on the stack.
  2. As references from instance variables on another object stored within the heap
Memory Management

Heap memory is obviously not endless. It is important to destroy objects that are no longer needed to make room for new objects. It is also very important to not destroy objects that are STILL needed.

Object ownership is what helps in determining whether an object should be destroyed or not.
  • An object with no owners can be destroyed
  • An object with one or more owners can not be destroyed
iOS's ARC

Automatic reference counting was introduced in iOS 5 and takes care of deciding which objects have owners and which don't. And destroys those that don't! Before this, you would have to manage memory yourself using retain and release messages.

ARC now takes care of most of this for you, but it's still important to know what's going on behind the scenes in case you need to step in at some point.

How does ARC know an object doesn't have any more owners? It keeps track of all pointers to that object as they are created. Later, a number of things can happen to these pointers which mean they don't 'own' the object at the other end of the pointer.
  1. The pointer is changed to point to another object
  2. The pointer is set to nil
  3. The variable holding the pointer is destroyed
The last one is interesting because, as objects own other objects, which can own other objects.. the destruction of a single object can set off a chain reaction of loss of ownership and subsequent object destruction.

Your Hook in ARC

In Objective-C you're able to define variables as having strong or weak references. This ties directly into how ARC will manage the objects pointed to by these variables.

Strong Reference - This encompasses the discussion so far. If a variable is defined as pointing to an object, that object will never be destroyed.

Weak Reference - A variable that does not take ownership of the object it points to. If an object only has pointers from weak references pointing to it, it will be destroyed

Why have weak references? They're mostly used for retain cycles. This is when two or more objects have strong references to each other. This is bad because neither of these (or any objects they own) will ever be destroyed, even if all other pointers to both have been removed.

An interesting thing about weak references is that they know when the object they point to is destroyed. They are set to nil in this case. This will prevent any exceptions from occurring if the object containing that weak reference ever tries to use it.

Conclusion

So, if all those strong vs. weak variable definitions were confusing you (as they did me at first) there you go. It's the framework for memory management in Objective-C.

Monday 4 March 2013

AF Networking Simplifies iOS Http Requests

I wrote this post a month or so ago on implementing http requests using the built in iOS libraries. I've been building a iOS app with a Rails on Mongo instance functioning at the backend API. I just switched everything over to AF Networking, which has helped simplify my network calls greatly!

If you compare these two approaches you can see the simplicity AF Networking gets you!

And then you just implement the two methods given to the networking operation callback block. In this case, processResult and processFailure. It's so simple! And so much less code than the standard iOS option.

The AF Networking github page.

Monday 25 February 2013

iOS Data Synchronization - How???

I'm working on an iPhone app at the moment and I'm approaching the time when I'll need to do data synchronization with my backend Rails API. Up to this point, I've only pulled data down to the mobile device so the backend has acted as the sort of 'master' of the data. Now, data entered on the device will need to be incorporated into the 'master' data and available to all users.

I've sort of been deferring the decision of how to implement this until the last 'responsible' point because it's a daunting task... and done wrong, would perhaps need to be completely done over again in the future.

I remember the pain on my last project (an Android tablet app) after we brought in our first solution to data syncing between device and backend. We suffered through 3 months of headache and then gutted the whole thing for another strategy. The odd thing is the initial thing we'd gone for was one of the Android 'recommended approaches'. These things called Cursor Adapters. Steer clear! I'll maybe do a different post on these and why they are painful.

So, I'm cautious about using libraries intended to be a one-size-fits-all. Luckily I guess, I haven't actually found any for iOS, so I think I'll be rolling my strategy.

These are the questions I'm asking myself.

1. How close are the data models between the device and backend?
2. How much data will be need to be synchronized?
3. How frequently will it need to be synchronized?
4. If the user deletes the app and reinstalls it, will data need to be downloaded to the device in the same state as before the delete?
5. I'm going to need to know which data came from which user.. how will I tag the data as such?
6. How to queue up changes if they are made while the user if offline?

Because I don't have a huge amount of data that will need to be synched, my initial approach will be to set up a process that checks for changes across the tables where they might occur (initially only 2 for my case) and then pushes these to my RESTful backend using JSON over an HTTP post request. My backend, will then store these data in separate tables where the user and timestamps are recorded. After this, I should be able to set up another timed request. More posts as I move forward on this!

Tuesday 19 February 2013

My start-up experience (to date)

I've been working on GoFest, a start-up I created, for the last 4 months and it's been a really interesting ride. I'm close to an iOS app store release and I have my first potential customer. I realized I'd been blogging about the technical side of what I was doing.. but not on the experience itself. I wanted to remedy that! I think I'll keep trying to blog, but for starters, I want to give a little overview of how things have gone so far.

It all started when I left my job (of 6+ years) in software consulting last October. I did this for a couple of reasons.
  1. I was unhappy with the current state of things in my work life. I felt like things were in a rut and I wasn't growing. On top of that, there was a lot of conflict and aggression occurring in the project I was on that I was eager move beyond.
  2. I had a growing urge to start something on my own. I'd been exposed to the start-up world expanding around me and was getting more and more excited by it. I had a mobile app idea that I knew I could build, if I had the time.
  3. I felt starting a company would be a great opportunity for the growth and learning that I was craving.

So, off I went! I knew I would make a lot of mistakes, but I was hoping to make them quickly and learn quickly. I left my job and dove into learning how to start a company.

Here's a quick overview of the activities I busied myself with.

Reading
  • I knew I had a lot to learn, so I picked up 2 books that were recommendations from friends and collegues: The Lean Start-up by Eric Reis and The Personal MBA by Josh Kaufman. I've since read them both and they are invaluable! I'd highly recommend them to everyone working in the business world.
Market Research (This is where I started.)
  • I looked around for apps even remotely related to my idea. I compiled of list of those I felt would be competitors or those that should just be watched for future direction. I allowed this to influence my idea because it's likely better to create a product with as little competition as possible.
  • I explored the Twitter and Facebook world around the topic my app would relate to. People on these networks would probably be the easiest to reach later when I wanted to do user research.
  • I tried to define who my customer would be and what they were interested in/willing to pay for.
Business Model/Plan
  • This obviously has to make me money. How was it going to do this? When was it likely that this would first happen?
Define MVP (minimum viable product)
  • What was the minimum feature set I needed to get this to the market?
Building
  • I started building the product. It was a lot of fun! I hadn't done any iOS development before, so I had a lot to learn.. but it's fun learning a new language and framework. And you get all those little wins each time you make something work.
Outside Help
  • One of my weaknesses was that I didn't have a solid co-founder. I had an ex-colleague offering business type advise and I had a friend here or there helping with with UX (user experience) or design. 
  • Tandem Incubator - In early December I was almost 2 months into this whole thing and I decided to look into incubators. I'd heard of these, but had earlier felt that I needed to get a little further with my project before applying. I decided that now was the time and dove into the application process.
    • I worked very hard for about 2 weeks getting things ready for the application. Deploying the app's website, generating screenshots and even a presentation. In the end, I didn't get accepted. But, going through the application ended up being a really beneficial thing. I refined my business plan, answered some hard questions about timelines and really worked out what the 'Pitch' for this app would focus on.
Where I am I now?
  • My iOS is app is nearing completion (I hope to deploy it in the app store in the next 6 weeks)
  • I have my first customer (my app is sort of based on customer subscriptions in a way)
  • I'm running out of money. :-)
  • While revenue could start coming in soon, I'm realizing that it won't start pouring in any time in the near future.

So, I'm undecided on what to do! I'm still lacking the co-founder. I've been attending networking events with different entrepreneurial circles here in NYC. I'm seeking the cofounder at these, but I'm also seeking community and potential role models. This process has been really awesome actually! It's great to meet so many people doing amazing things. 

One thing that afflicts the developer entrepreneur is the knowing of the current state of the job market. There are lots of jobs out there for an experienced engineer. Exciting, well paying jobs! The lure of this is in the back of my head every time I think about my checking account balance.

I think blogging about this is good for me to figure out what's next. Maybe I'll get accepted to an incubator! Who knows? Maybe I do take a job with a start-up and learn in a more mature, but related environment.  For now, I'm going to keep plugging at it for a while more.

Thursday 14 February 2013

iOS provisioning HELL (solved)

Sometime I feel like the relationship I have with Apple is quite similar to that one would have with a bipolar boyfriend or girlfriend. The good times are really good... and the bad times are REALLY bad. But you just stay because you can't imagine life without them. :-) They brought us smart phones, mac books and iPods. You can't give those up! And they obviously brought us mobile apps easily distributed though an app store. This is great!

But it's well known that it's a pain the ass releasing your app through their long and tedious process. Provisioning used to be a nightmare! It also used to be hard to get your app to beta testers because you needed their phone's UDID and then you would have to produce a different build for each UDID. PAIN!

Test Flight was the earliest tool out there for managing your builds and distributing them to stakeholders, testers, etc.. I was even talking to Jeff Soto from the iOS Brooklyn Meetup and his team at Tendigi are building a tool to integrate Test Flight with their QA process. Very cool!

I've actually just started using AirOnApp because they go one step further and remove the need for collecting each of the UDIDs from every device that you'll distribute to during testing. They resign the app automagically for the each device. :-)

I'm planning on releasing my app in the next month and will use their automated release process as well. Hoping that goes as well as beta testing distribution!

Tuesday 22 January 2013

Git Alias & Ignore

Quick Reference for Git Aliasing and Ignoring

Aliasing:


$ cd ~
$ vim .gitconfig

Add the following (and any additional shortcuts you want):


[alias]
ci = commit
st = status
co = checkout
lc = log ORIG_HEAD.. --stat --no-merges

Ignoring

(This is mine for a rubymine project)

Thursday 10 January 2013

Network JSON request in iOS


I had to dig a little to bring all the components together necessary for something like this so I thought it best to document it.

For the request you need: 

1. Create an NSMutableRequest
2. Create an NSURLConnection with the above request
3. Set the class encapsulating this behavior as the delegate to the connection
4. Implement the call back methods the connection makes based on the result it gets (so you can decide what to do)

Monday 7 January 2013

iOS 6 Facebook Integration

<script src="https://gist.github.com/4161726.js?file=AppDelegate.m"></script>

<script src="https://gist.github.com/4161735.js?file=AppDelegate.m"></script>

Add the plist item 'FacebookAppID'

Add the entry to URL types.

Knock this into a delegate method.

<script src="https://gist.github.com/4161746.js?file=gistfile1.txt"></script>

<script src="https://gist.github.com/4161750.js?file=gistfile1.m"></script>

Thursday 3 January 2013

Configuring Environment Variables iOS

Say you've got an iOS app talking to a backend api. Maybe this api runs as localhost on your machine when you're in development and maybe you also have staging and production environments out in the cloud somewhere. What's the best way to set this up?

I've gone with an encapsulated pList... setup as follows.

This is my pList file.
I encapsulate that in a class called EnvironmentVars.

After which, I can access it as follows from anywhere. This is an example of using it to create a NSUrl object.
Objective C code can be terse. I find it's best to exercise encapsulation to the extremist point to maintain sanity.