Creating iOS Frameworks

For iOS, no XCode template for creating frameworks exist. Reason seems to be that Apple doesn’t want that people create dynamically linked libraries, so they just removed it completely.

But for sure, using static libraries is ok, there is even an XCode template for this. People said that they published apps to the Apple AppStore that use frameworks with static libraries, and that they did get approved without problems.

There are some approaches out there for creating frameworks for iOS (1, 2, 3, 4), but this one is the simplest and works very well: ios-static-framework.

Much more background can be found in this and this great posts.

So, go and create frameworks that work on multiple architectures using static libraries and bundle resources, and make it easy for 3rd parties to add functionality to their projects :-)

Documenting Objective-C Code using AppleDoc

I earlier wrote a post pointing to a blog post about documenting Objective-C code using Doxygen and Xcode. While this works quite well, there is a much simpler approach which produces documentation looking similar to Apple’s own iOS documentation: Using AppleDoc.

This post shows you how to set up AppleDoc, and how to integrate with the build process to keep your documentation up-to-date: Documenting you code in Xcode 4

This still works with XCode 4.3.1 without any problems.

The generated documentation is automatically pushed to XCode and available beside all other documentation in the Organizer.

Posted in iOS

Converting Timestamp to NSString Providing the Difference to “Just Now”

If you got a timestamp, e.g. from an SQL database entry, and you need a NSString on iOS that tells you how many seconds, minutes, hours, etc. ago this event happened (to display to the user), NSDateComponents is your friend.

Here is a small utility method that illustrates the conversion:

+ (NSString*)timeAgoString:(NSString *)timestampString
{
    double eventSecondsSince1970 =
        [timestampString doubleValue] / 1000.0; // milliseconds to seconds
    NSDate *eventDate =
        [NSDate dateWithTimeIntervalSince1970:eventSecondsSince1970];
    NSCalendar *gregorian =
        [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
        autorelease];
    int unitFlags = NSYearCalendarUnit |
                    NSMonthCalendarUnit |
                    NSDayCalendarUnit |
                    NSHourCalendarUnit |
                    NSMinuteCalendarUnit |
                    NSSecondCalendarUnit;
    NSDateComponents *comps =
        [gregorian components:unitFlags
        fromDate:eventDate toDate:[NSDate date] options:0];

    NSString *timeAgoString = [NSString string];
    if ([comps year] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i years ago", [comps year]];
    }
    else if ([comps month] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i month ago", [comps month]];
    }
    else if ([comps day] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i days ago", [comps day]];
    }
    else if ([comps hour] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i hours ago", [comps hour]];
    }
    else if ([comps minute] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i mins ago", [comps minute]];
    }
    else if ([comps second] > 0) {
        timeAgoString =
            [NSString stringWithFormat:@"%i secs ago", [comps second]];
    }
    return timeAgoString;
}
Posted in iOS

Mark Zuckerberg about Facebook Product Development

Great quote from Mark Zuckerberg: “The biggest risk is not taking any risk…In a world that changing really quickly, the only strategy that is guaranteed to fail is not taking risks.”

In those video clips you can learn about Mark Zuckerberg and Facebook Product Development:

From Y Combinator’s Startup School interview, Zuckerberg starting around the 43 minute mark and talks around 40 minutes:


Watch live video from Startup School on Justin.tv

At Stanford’s Entrepreneurship Corner, there are 9 short clips from Mark Zuckerberg. This is the first one, where he comments about product development at Facebook:

Communication Between View Controllers in iOS

Basically, there are three different ways to implement a communication between view controllers in iOS:

  • If the view controllers are closely related to each other, you can give them instance variables that point to each other. This is the easiest way to send messages between view controllers, but it’s the least adaptable. You should avoid this.
  • You can create a delegate protocol that specifies the messages that one view controller can send to the others. Other view controllers can then adopt to this protocol. Your view controller does not need to know to which type of view controllers it sends the message, only that they conform to the protocol.
  • If there is no relation between the view controllers, the notification system can be used. It also makes sense if multiple view controllers are interested in the messages of one view controller. Posts can go to NSNotificationCenter, where interested view controllers have registered for that notification.
I always talked about view controllers here, but the same is true for other objects, e.g. views.
Posted in iOS

Studio Monitor Speakers for Your Airport Express Airplay

For all you Airport Express and Airplay users out there: If you want to attach speakers to your Airport Express directly, active speakers are the solution. Obviously, all those computer speaker systems could be used (from Logitech etc.).

However, there is an interesting alternative: Use studio monitor speakers. You will get crystal clear sound and a lot of power. The idea of studio monitors is that they reproduce the sound as natural/unmodified as possible. The cheapest, but very good choice could be: Behringer 3030A or 3031A. You can get them e.g. here and here. Both shops offer 30 day money back if you are not satisfied. The difference between 3030A and 3031A is the size, and with it comes the deepest frequency that the speaker can reproduce, and also the maximum sound level. I would recommend the 3030A. With this size you could still put them on your desk to compose music with Ableton Live, and the kick bass rocks. If they don’t go deep enough for you, you can combine with a subwoofer. Or exchange with 3031A, because you have this 30 days money back guarantee. With the 3031A, you can easily give parties in bigger rooms.

There are also “more professional” studio monitors available, e.g. M-Audio BX5 / BX8 or KRK Rokit RP5 / RP8, but they cost much more, and I can tell you that Behringer sound fantastic.

Multi-Sided Platform Pattern to Describe Mobile Internet Business Models

I highly recommend reading the book Business Model Generation. Not only that the design of the book is really refreshing and makes it fun to read, but it also just focusses on main facts that you need to describe your business model and illustrates them well.

What I like especially is that it formalizes Multi-Sided Platforms, a business model pattern that is used in many Internet mobile businesses today: Two or more distinct but independent groups of customers are brought together, and such platforms are of value to one group of customers only if the other groups of customers are also present. The platform creates value by facilitating interactions between different groups. A multi-sided platform grows in value to the extent that it attracts more users, also known as network effect. Economists call this platform multi-sided markets.

A very prominent example for a multi-sided platform is Google’s business model: It’s value proposition is to provide extremely targeted text advertising over the Web (AdWords), extending the reach further through AdSense through which ads are displayed on other, non-Google Web sites. Customers are Web surfers, advertisers and content creators: Three independent groups of customers, but value is brought to one through presence of the others. Three value propositions exist respectively: Free search, targeted ads, and monetizing of content.

Another example for multi-sided platforms are the video games consoles Wii and Xbox. Both are double-sided platforms. While Wii addresses casual gamers (“family” console) and game developers, Xbox addresses hardcore gamers and game developers. But the business models are substantially different: Wii’s consoles are relatively inexpensive, and customers are attracted through the novel motion-controlled “fun factor”, while Xbox machines are sold with loss because of the expensive hardware. With the Wii, Nintendo earns money from both – console gamers which buy the hardware and game developers through royalties – while Microsoft only from game developers. Additionally, both produce and sell games on their own.

The Business Model Canvas, which is the main focus of the book Business Model Generation, provides a shared language for describing, visualizing, assessing, and changing business models. Together with the described multi-sided platform pattern, this book gives you a powerful tool to construct and visualize your business model of your mobile service business idea in a fresh and easy-to-explain way.

Overlay with Gradient and Transparency

If you want to add a gradient to a UIView with transparency, so that you can e.g. put it on top of a UIImageView as container for some text, and you can rely on iOS 3.0+ being available, you might use a layer for this.

You can safely rely on iOS 4.0+ being installed on people’s iPhone and iPad nowadays. Already back in January, 84% of iPhones were running iOS 4 according to Chitika, and even iOS 5 was already installed on 33% of all iOS devices after less than one week of availability according to Localystics.

Include QuartzCore/QuartzCore.h to your source file, and you can create a gradient overlay from solid black to full transparency this way:

UIView *overlayContainer =
  [[[UIView alloc] initWithFrame:
    CGRectMake(0, 0, kSizeWidth, kSizeHeight)]
    autorelease];
overlayContainer.backgroundColor = [UIColor clearColor];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = overlayContainer.bounds;
gradient.colors = [NSArray arrayWithObjects:
  (id)[[UIColor blackColor] CGColor],
  (id)[[UIColor clearColor] CGColor], nil];
[overlayContainer.layer insertSublayer:gradient atIndex:0];
[self.view addSubview:overlayContainer];
Posted in iOS