Archive

Archive for the ‘iPhone’ Category

Kiwi as a static framework or Universal Library

January 27, 2012 Leave a comment

A problem commonly encountered when using open-source iOS frameworks is the lack of a fully-functional framework facility in xCode. Part of the issue is that Apple does not allow dynamic linking on iOS devices, the other is that there are two different architectures that need to be supported by libraries targeting both armv6 (up to iPhone 3G) and armv7 devices (iPhone 3GS and later). On top of that, we also need a binary that will run on the simulator (x86).

The easiest solution to the library problem in XCode is using project dependencies to build libraries in the configuration you need them. When taking a source dependency is not desirable, you are pretty much left to your own if the OSS project doesn’t provide binaries.

Fortunately enough, it’s not too difficult to build your own universal frameworks. Below are the steps I use for building a version of Kiwi:

  1. Grab the Universal Framework XCode templates from https://github.com/kstenerud/iOS-Universal-Framework
  2. Install the Fake framework flavor (although the Real framework flavor should work as well)
  3. Create a new xCode project with the Fake framework template
  4. Add all source files of Kiwi (make sure to check the Copy to destination group folder box)
  5. Select the Kiwi static library target, project editor, build phases, Copy Headers, select all headers in the Project Group, right click and select move to Public
  6. Select the Kiwi static library target, project editor, build phases, link binary with libraries and add SenTestingKit.framework
  7. Build
  8. Go to the  Project Navigator (Cmd-1) and select Products Kiwi.framework. Right-Click and select “Show in Finder”
  9. You should see two folders: Kiwi.framework and Kiwi.embeddedframework – Kiwi.framework is the one we need
  10. Copy the Kiwi.framework folder into your lib folder
  11. Open the project you want to use Kiwi.framework in and select your target, project editor, build phases, link binary with libraries, click + and add Kiwi.framework from your lib folder

That’s it. Takes less than two minutes once you know the trick.

Categories: iPhone, Objective-C, Tools

Continous Deployment for Apps via testflightapp

January 26, 2012 Leave a comment

The benefits of continous integration are widely known. By extending the ideas of continous integration to the full software lifecycle, continous delivery becomes an inevitable practice. Especially in the context of managing a beta program for mobile devices, to most of which I as a developer have no physical access, the ability to have fully automated deployments is crucial.

Testflightapp.com provides a great service to iOS developers by managing app provisioning and deployments. They do also provide easy to use instrumentation facilities.

Continous deployment with testflightapp.com is a breaze, all you need your build-server to do is interact with a straightforward web-api to upload your ipa packages.
Here’s the script I’m using for RowMotion:

#!/bin/bash
# 

# testflightapp.com tokens
API_TOKEN="YOUR_API_TOKEN"
TEAM_TOKEN="YOUR_TEAM_TOKEN"

PRODUCT_NAME="RowMotion"
ARTEFACTS="$PWD/Artefacts"

SIGNING_IDENTITY="iPhone Distribution"
PROVISIONING_PROFILE="$PWD/id/RowMotionAdHoc.mobileprovision"

# calculated vars
OUT_IPA="${ARTEFACTS}/${PRODUCT_NAME}.ipa"
OUT_DSYM="${ARTEFACTS}/${PRODUCT_NAME}.dSYM.zip"

# kill artefacts directory
rm -rf $ARTEFACTS
mkdir $ARTEFACTS

# compile
echo "##teamcity[compilationStarted compiler='xcodebuild']"
xcodebuild -workspace RowMotion.xcworkspace -scheme RowMotion -sdk iphoneos5.0 -configuration Release build archive
buildSucess=$?

if [[ $buildSucess != 0 ]] ; then
echo "##teamcity[message text='compiler error' status='ERROR']"
echo "##teamcity[compilationFinished compiler='xcodebuild']"
exit $buildSucess
fi

echo "##teamcity[compilationFinished compiler='xcodebuild']"

#ipa
echo "##teamcity[progressMessage 'Creating .ipa for ${PRODUCT_NAME}']"

DATE=$( /bin/date +"%Y-%m-%d" )
ARCHIVE=$( /bin/ls -t "${HOME}/Library/Developer/Xcode/Archives/${DATE}" | /usr/bin/grep xcarchive | /usr/bin/sed -n 1p )
DSYM="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/dSYMs/${PRODUCT_NAME}.app.dSYM"
APP="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/Products/Applications/${PRODUCT_NAME}.app"

/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${APP}" -o "${OUT_IPA}" --sign "${SIGNING_IDENTITY}" --embed "${PROVISIONING_PROFILE}"

#symbols
echo "##teamcity[progressMessage 'Zipping .dSYM for ${PRODUCT_NAME}']"
/usr/bin/zip -r "${OUT_DSYM}" "${DSYM}"

# prepare build notes
NOTES=`hg tip`

#upload
echo "##teamcity[progressMessage 'Uploading ${PRODUCT_NAME} to TestFlight']"

/usr/bin/curl "http://testflightapp.com/api/builds.json" \
-F file=@"${OUT_IPA}" \
-F dsym=@"${OUT_DSYM}" \
-F api_token="${API_TOKEN}" \
-F team_token="${TEAM_TOKEN}" \
-F notes="${NOTES}" \
-F notify="True" \
-F distribution_lists="Private"

Make sure to adapt the script to your requirements. One trick I’m fond of is automatically providing SCM information in the build notes (the step with executing hg tip does just that).
For deployments I’m using two lists, a private one to which all builds will be published, and a public one to which I can selectively deploy. What’s so great about testflightapp.com is that it will automatically send emails to notify my testers about the new build and will then allow me to monitor installs.

iOS: Detect Personal Hotspot

July 22, 2011 2 comments

When you want to detect the type of available connections on an iPhone, the best resource you can find on the web is the sample code from Erica Sadun’s excellent iPhone Cookbook book (which I can wholeheartedly recommend). The sample code can be found on github (look into 02 and 03): https://github.com/erica/iphone-3.0-cookbook-/tree/master/C13-Networking

While the solution presented is great, it fails to work on an iPhone 4 that has the Personal Hotspot feature enabled. In this scenario, the iPhone will create a network interface called “ap0” that bridges through to “en0” (WiFi) and “pdp_ip0” (3G) . Since “en0” will not be marked as AF_INET interface in this scenario, the approach Erica outlined will fail here. Here’s a dump of the available interfaces, their loopback and AF_INET status and their assigned address:

2011-07-22 12:59:07.120 RowMotion[286:707] name: lo0, inet: 0, loopback: 0, adress: 24.3.0.0
2011-07-22 12:59:07.126 RowMotion[286:707] name: lo0, inet: 0, loopback: 0, adress: 0.0.0.0
2011-07-22 12:59:07.129 RowMotion[286:707] name: lo0, inet: 1, loopback: 0, adress: 127.0.0.1
2011-07-22 12:59:07.134 RowMotion[286:707] name: lo0, inet: 0, loopback: 0, adress: 0.0.0.0
2011-07-22 12:59:07.137 RowMotion[286:707] name: en0, inet: 0, loopback: 1, adress: 6.3.6.0
2011-07-22 12:59:07.141 RowMotion[286:707] name: ap0, inet: 0, loopback: 1, adress: 6.3.6.0
2011-07-22 12:59:07.145 RowMotion[286:707] name: pdp_ip0, inet: 0, loopback: 1, adress: 255.7.0.0
2011-07-22 12:59:07.149 RowMotion[286:707] name: pdp_ip0, inet: 1, loopback: 1, adress: 10.217.22.129
2011-07-22 12:59:07.154 RowMotion[286:707] name: pdp_ip1, inet: 0, loopback: 1, adress: 255.7.0.0
2011-07-22 12:59:07.157 RowMotion[286:707] name: pdp_ip2, inet: 0, loopback: 1, adress: 255.7.0.0
2011-07-22 12:59:07.161 RowMotion[286:707] name: pdp_ip3, inet: 0, loopback: 1, adress: 255.7.0.0
2011-07-22 12:59:07.165 RowMotion[286:707] name: en1, inet: 0, loopback: 1, adress: 6.3.6.0
2011-07-22 12:59:07.168 RowMotion[286:707] name: bridge0, inet: 0, loopback: 1, adress: 6.7.6.0
2011-07-22 12:59:07.172 RowMotion[286:707] name: bridge0, inet: 1, loopback: 1, adress: 172.20.10.1

See that last line? Yep, that’s the bridge interface we need to use to communicate with other devices on our “personal hotspot”. Here’s how to ammend Erica’s code to make personal hotspots transparent:

// Matt Brown's get WiFi IP addy solution
// http://mattbsoftware.blogspot.com/2009/04/how-to-get-ip-address-of-iphone-os-v221.html
+ (NSString *) localWiFiIPAddress
{
    BOOL success;
    struct ifaddrs * addrs;
    const struct ifaddrs * cursor;
    
    success = getifaddrs(&addrs) == 0;
    if (success) {
        cursor = addrs;
        while (cursor != NULL) {
            
            NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
            
            NSLog(@"available network interfaces: name: %@, inet: %d, loopback: %d, adress: %@", name, cursor->ifa_addr->sa_family == AF_INET, (cursor->ifa_flags & IFF_LOOPBACK) == 0, [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)]);
            
            // the second test keeps from picking up the loopback address
            if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) 
            {
                if ([name isEqualToString:@"en0"] || [name isEqualToString:@"bridge0"])  //  Wi-Fi adapter, or iPhone 4 Personal hotspot bridge adapter
                    return [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)];
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
    }
    return nil;
}

+ (BOOL) activeWLAN
{
    return ([self localWiFiIPAddress] != nil);
}

+ (BOOL) activePersonalHotspot
{

    // Personal hotspot is fixed to 172.20.10
    return ([self activeWLAN] && [ hasPrefix:@"172.20.10"]);
}

+ (BOOL) activeWLAN
{
    return ([self localWiFiIPAddress] != nil);
}

+ (BOOL) activePersonalHotspot
{
    // Personal hotspot is fixed to 172.20.10
    NSString* localWifiAddress = [self localWiFiIPAddress];
    return (localWifiAddress != nil && [localWifiAddress hasPrefix:@"172.20.10"]);
}

I hope this will find it’s way into the sample code soon. Pull request is pending.

Objective-C Pitfall: Synthesized Properties without backing field

June 29, 2011 2 comments

This is just a quick and short post about an Objective-C pitfall I have encountered today. When using synthesized properties, you do normally supply a backing field:

@property (nonatomic, readwrite, retain) Message* message = message_;

This will synthesize a getter and setter, that will use message_ as its backing field. Since I found out one can go clever and ommit the backing field, so a simple line like this will work too:

@property (nonatomic, readwrite, retain) Message* message;

However, now we get into a bit of trouble when accessing the property. Contrary to the behavior in Java or C#, you now get something different when accessing 

self.message

 vs.

message

. While the former will use the synthesized getter, the latter will use the synthesized backing field directly. This is a bit unexpected (I thought the backing field would be anonymous). So, my general advice would be to always use backing fields in your synthesized backing fields, so you don’t accidentally forget a “self.”. (This is water on the mills of people that advocate _not_ using the dot syntax for properties).

 

 

Categories: iPhone, Objective-C

GoodReader and Mercurial for the Ultimate Student Workflow

June 8, 2011 Leave a comment

Being the proud owner of a shiny new iPad2 for the last month or so, I found it to be a valuable companion at University. No, not for browsing stackoverflow, keeping up with RSS and E-Mail, but for managing lecture slide decks, assignments etc.

In the past semester, I started managing my documents in a mercurial repository that is synced against my private mercurial server installation. This made it easier for me to keep my multiple devices synchronized (who would need that iCloud thing…). My first attempts at using the iPad for these tasks was using iBooks. iBooks is not bad, but its so utterly limited that it sucks really hard from times to times. Especially annoying is that it has absolutely no file management capabilities whatsoever.

I found GoodReader to be a great alternative. It has excellent file management and supports annotating pdfs. But the best thing is its support for synchronizing your files:

  1. Make sure your iPad is connected to the same network as your host computer
  2. Launch GoodReader, open the WiFi sync mode via the WiFi symbol
  3. Mount http://yourIpad’sIpAdress:8080 has a network folder
  4. Open a terminal, cd into your mount point  and run hg clone /yourCentralRepository
  5. The next time you want to sync run hg pull -U
It takes less than 5 minutes to set up, and is a pretty damn smart workflow!
Categories: iPhone, Tools

iOS Development Continous Integration Setup

June 7, 2011 Leave a comment

After almost a year of absence, I’m in the middle of getting back to iOS Development. Since my departure from the Apple ranch, a lot has changed and new developer tools have emerged. Professional software development has become significantly easier on this platform, but I feel the tooling still isn’t on par with what other ecosystems provide.

Nonetheless, where there’s will there’s a way. In this Series of posts, I’m going to outline the setup I’m currently running. I’ll point to resources that helped me along the way and will describe how to combine the pieces to make it all fit together. I don’t plan publishing in any particular order and since business goes first, I am going to write when I find the time for it.

All posts of the series will be put into the category iOS Continous Integration Series, which also is the best place to find them.

The setup will consist of:
The Dev’s Private Cloud (aka a HyperV Server) hosting:
– Teamcity CI Server
– Build Agents
– Mercurial via hgweb.cgi

OCUnit
Kiwi for Acceptance Testing
OCMock as Isolation framework
GCov for Code Coverage

Planned Posts:

Running Ubuntu Server in HyperVi
Setting up a TeamCity Server on Ubuntu
Setting up a Mercurial Server
iOS Testing Frameworks revisited
Running OCUnit on a build agent
Connecting OCUnit to Teamcity
Integrating OCMock
Using Kiwi for Acceptance Testing
Retrieving Coverage information with GCov
XCode Alternatives

iPhone resetting experience

December 3, 2009 Leave a comment

My iPhone has started to behave somewhat “laggy” recently, taking too long waking up from standby when pressing a button, repeated hangs when using the virtual keyboard to write  emails etc.

My device also had accumulated a lot of “history” in terms of apps I don’t use any longer but was too lazy to delete and has been jailbreaked once.So I decided it would be the easiest to just reset the firmware, went into iTunes and hit the restore button.

iTunes proceeded taking a full backup of my decvice and restored the firmware afterwards, which took an hour approximately. After I reactivated the iPhone, iTunes asked me if I wanted to restore my personal settings and sync my apps, leaving me to choose what apps should go on the device again and let me even sort them on the springboard from within iTunes (makes it so much easier!). After that I synced my music and pictures and I was pretty impressed with the result:

  1. No hacking required, everything easily click-through
  2. All my apps data was conserved (notes, gps trails etc.)
  3. All my email settings was still there
  4. My music was all there
  5. My photos were all there

The complete procedure took me probably half an hour, rest of the time waiting for iTunes to finish 🙂

Categories: iPhone

GHUnit: Writing Custom Assert Macros

October 24, 2009 Leave a comment

When I evaluated unit testing frameworks for iPhone development, One of the reasons why I chose GHUnit was that it has more sophisticated Assert Macros than other available frameworks. Despite this fact, there are still some Asserts that I missed, so I simply took the time to write my own.

Unlike test frameworks in the .NET or Java ecosystem, all Objective-C Frameworks provide preprocessor macros to realize assertions instead of providing a static class with Assert methods. A typical assert macro looks like the following:


#define GHAssertEquals(a1, a2, description, ...) \
do { \
	@try {\
		if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \
			[self failWithException:[NSException ghu_failureInFile:@"Type mismatch"...]; \
		} else { \
			if (![a1encoded isEqualToValue:a2encoded]) { \
				[self failWithException:[NSException ghu_failureInEqualityBetweenValue...]; \
			} \
		} \
	} \
	@catch (id anException) {\
		[self failWithException:[NSException ghu_failureInRaise...]; \
	}\
} while(0)

The body of the macro consists of a do{} while(false) loop, which is used to provide local scope for variables needed to implement the assertion. It is clear that code executed only once, even though a loop construct is used. The macro first checks necessary preconditions, in this case argument types. This is necessary due to the nature of a macro being a simple text substitution rather than a true method call that the compiler checks argument types for (that’s why I don’t like assertions being implemented as macros but would rather like to see assert methods). Next is the actual assertion. The type check and the actual assertion are both wrapped in a try{} catch(){} block, so any errors occurring in the macro code let the test fail also (a real macro would have a lot of code for preparing exception descriptions etc.).

I consider the GHUnit macros as a very useful set of primitve’s that can be combined to construct more complicated assertions:


#define GHFileAssertNotEmpty(file) \
do { \
	GHAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:file], nil); \
	NSString* written = [NSString stringWithContentsOfFile:file]; \
	GHAssertNotNil(written, nil); \
	GHAssertGreaterThan((int)[written length], 0, nil); \
} while (0)

Note that I don’t need to take care of all the nasty details that are needed to write a proper primitive macro as outlined above. The only disadvantage with a macro like the one above is localizing the failed assertion, as the exception thrown might not be directly obvious from the code using the macro. It is not a real disadvantage of the method itself but rather inherent to all macros. XCode right-click Jump to Definition comes to the rescue here.

Categories: GHUnit, iPhone, Open Source, Testing

GHUnit: Parallel test execution performance implications

October 23, 2009 Leave a comment

As my unit test suite for the iRow project starts to grow, I am running into issues regarding test execution speed. I have maintained a clear distinction between integration and unit tests, so there are no external (possibly slow) resources such as disc i/o (including nib’s) or Sqlite databases involved.

I usually run my unit test suite in the Simulator. Having set GHUnit to automatically run my tests on startup this makes it as simple as hitting cmd-r (Xcode Build&Run). It takes some time to update the app in the Simulator, usually around 1-3 secs but I haven’t found this to be an issue as I usually take the time to do some formatting on the code I am currently working on. GHUnit makes it also very convenient to select a subset of tests  that shall be run and persists these settings between builds, so I don’t have to browse through a hundred of tests if one was failing.

Even though only running a subset of tests, it clearly took to long for me (measured 4-5 secs with stopwatch from app startup). This number also had no coincidence with what GHUnit reported as test execution time (around 0.2 secs). Browsing the GHUnit code to see where the time is wasted, I noticed that GHTestCase default implementation of the

– (BOOL)shouldRunOnMainThread

method , which GHUnit uses to determine if the runner needs to spawn off a child thread for executing this testcase, always returns false. Creating a thread is a costly operation in terms of overhead, the necessary synchronization to retrieve test results another. That’s why I suggest deriving all your testcases from a baseclass (which inherits GHTestCase) to have a central point of control about unit test execution (via shouldRunOnMainThread). This yields another positive effect for integration testing. My integration tests often need to be run on the main thread because they require certain input dispatched to the main threads runLoop only.

This is how my implementation of the shouldRunOnMainThread method looks like:

– (BOOL)shouldRunOnMainThread

{

#ifdef IROW_INTEGRATION_TESTING

return TRUE;

#endif

#ifndef IROW_INTEGRATION_TESTING

return TRUE;

#endif

}

The IROW_INTEGRATION_TESTING symbol is defined in  the integration test project’s prefix header. I think it is a pretty simple but effective solution to control test execution.

Executing all tests on the main thread brought astonishing results: Test time is down to 0.1.secs (measured with stopwatch).  However, it might be interesting to run tests on different threads from time to time to detect possible unintended side effects regarding global state. If tests seem to fail randomly if run multiple times in a row, this is a good indicator for such problems.

Cocoa Memory management conventions

October 15, 2009 Leave a comment

Apple uses reference counting as the default memory management technique in its frameworks. Augmented with an autorelease pool that keeps track of the current stack frame and releases objects when the current stack frame exits, it is a reasonable balance between the performance of manual memory management and the comfort of garbage collection I am usually used to working on .NET projects.

However, reference counting establishes the need for ownership conventions that define who is responsible for releasing an object and under what circumstances I can assume a reference to be valid. Unfortunately, I have found these conventions hard to remember every time I created an object, because there are many of them (at least if you have just started Objective-C programming). Thought as a memo to myself, here follows the (hopefully complete) list of conventions:

Creating Objects:

  • Objects retrieved via methods whose name begins with “alloc” or “new” or contains “copy” are retained. The caller is responsible for releasing the object.
  • CoreFoundation Objects retrieved via C functions whose name contains “Create” or “Copy” are retained. The caller is responsible for releasing the object.
  • In any other case, the caller is not responsible for releasing the object e.g. receiving a string from [NSString stringWithFormat:] returns an autoreleased object.

Loading Objects from NIB Files:

  • Objects in the nib file are created with a retain count of 1 and then autoreleased.
  • UIKit reestablishes connections between the objects using setValue:forKey:, which uses the available setter method or retains the object by default if no setter method is available
  • If there are any top-level objects you not stored in outlets, the caller must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.

Receiving Objects

  • The conventions governing receiving objects follow from the rules governing object creation
  • A received object can be assumed valid throughout the scope of the caller
  • If a caller wants to retain an object in another scope (e.g. storing it in a private field) he must call -retain and is responsible for releasing the object when done with it

This guide is probably not complete, however it contains the most important rules. For additional detail please see the resources below.

Sources:

Categories: Design, iPhone
%d bloggers like this: