<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jayway Team Blog &#187; ipad</title>
	<atom:link href="http://blog.jayway.com/tag/ipad/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jayway.com</link>
	<description>Sharing Experience</description>
	<lastBuildDate>Sat, 11 Feb 2012 10:33:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Developers exploratory testing &#8211; Expanding its value</title>
		<link>http://blog.jayway.com/2011/12/17/developers-exploratory-testing-expanding-its-value/</link>
		<comments>http://blog.jayway.com/2011/12/17/developers-exploratory-testing-expanding-its-value/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 16:55:48 +0000</pubDate>
		<dc:creator>Sigurdur Birgisson</dc:creator>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[DET]]></category>
		<category><![CDATA[developers exploratory testing]]></category>
		<category><![CDATA[exploratory testing]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[team]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=11624</guid>
		<description><![CDATA[There is a common practice in our company to perform Developers Exploratory Testing sessions, explained by my colleague Davor here. The cool thing is that this way of performing higher level testing has actually become accepted by our developers, and they really enjoy it. In my current work of developing our organization wide practices for quality, I have [...]]]></description>
			<content:encoded><![CDATA[<p>There is a common practice in our company to perform Developers Exploratory Testing sessions, explained by my colleague Davor <a href="http://www.stickyminds.com/sitewide.asp?function=DETAILSIDX&amp;tvniu=1&amp;sqry=*Z(SM)*J(ART)*R(createdate)*&amp;ObjectId=17003&amp;ObjectType=ART&amp;sidx=1">here</a>. The cool thing is that this way of performing higher level testing has actually become accepted by our developers, and <a href="http://blog.jayway.com/2010/10/11/three-reasons-for-me-as-a-developer-to-love-developer-exploratory-testing/">they really enjoy it</a>.</p>
<p>In my current work of <a href="http://blog.jayway.com/2011/12/01/organization-wide-test-strategy-step1-deriving-our-quality-values/">developing our organization wide practices for quality</a>, I have made a deep dive into how DET is carried out on a regular basis. What I have seen is that DET is accepted and acknowledged as a valuable practice, however it is not really carried out in its full potential. There are many details and aspects of it to work on, especially regarding reporting and follow-up.</p>
<p>The other day I was asked to help one of our teams with a DET session. <span id="more-11624"></span>As they are familiar with the approach, I wanted to expand their view on its potential through light weight note taking and showed them an example of a <a href="https://docs.google.com/document/d/1Ew5B868XB0-S5vq6KfxNi4tck9szJ2zZEXjLq4XpbAs/edit">very basic session template I like to use</a>. I also explained the intentions of having bugs and issues separated as well as how I do with test notes and the summary. We decided to use a whiteboard instead and put stickies with issues and bugs on there for visualization. We spoke about the mission and decided on two different areas to focus on. The app is an iOS app where a new component is used in the app core functionality for iOS5.</p>
<p>The four of us paired into two teams with some different iOS devices and tested for about 45 minutes. We found quite a few issues and bugs that were put on the whiteboard, but not so much notes about which areas we covered. Of course, by looking at the issues you might get a hint of what areas have been covered, but how much? We also quite quickly noted that we had to tag each issue with the test environment (iOS version and device), since they differed quite a lot. Most of the things found were considered bugs to fix, which is also not always the case in all projects or settings. It usually depends on the customer and the relationship to them, as well as having a decision maker on this present during testing. In this project, the scrum master/tech lead which was present knows the customer well enough to make those judgements.</p>
<h3>But what about the learnings?</h3>
<p>After the session debrief I got into a meta-debrief, discussing the outcome compared to my introduction about reporting. At first there was not very much understanding of why having test notes is valuable, but this shifted a little during our discussion. "While our smaller projects change that rapidly, even storing test notes might be waste" is a motivation I will take with me. I explained a common scenario of being asked what was tested and with what configuration. It could also be valuable for future test sessions to know what parts of a functionality was covered and when this was tested before. I also like to emphasize the possibility to explain current functionality which might not be explicitly stated in requirements.</p>
<p>The team was happy with the experience and I got some more input on how to improve the value of our DET sessions. I am not going to abandon the reporting, but I need to find a way of combining the fun part of interacting between pairs through the collaborative setting of the whiteboard. This actually helped getting attention on the issues in the debrief.</p>
<p>And then the developers actually got their own ideas of what a session note taking tool should look like to suit their needs, this is how they sketched it out after the session. I would explore some other possibilities before building our own for example <a href="http://testing.gershon.info/reporter/">RapidReporter</a> or <a href="http://code.google.com/p/sessionweb/">SessionWeb</a>, but it is really cool that the meta-discussion could trigger the further thinking about the problem. Other aspects of the problem with collective knowledge transfers I wrote about <a href="http://happytesting.wordpress.com/2011/06/15/collective-note-taking-more-value-from-your-test-notes/">here</a>.</p>
<p><a href="http://blog.jayway.com/wordpress/wp-content/uploads/2011/12/photo.jpg" rel="lightbox"><img class="aligncenter size-medium wp-image-11626" title="Sketchup of test note taking tool" src="http://blog.jayway.com/wordpress/wp-content/uploads/2011/12/photo-224x300.jpg" alt="" width="224" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2011/12/17/developers-exploratory-testing-expanding-its-value/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rewriting a Public Cocoa Touch API</title>
		<link>http://blog.jayway.com/2010/05/25/rewriting-a-public-cocoa-touch-api/</link>
		<comments>http://blog.jayway.com/2010/05/25/rewriting-a-public-cocoa-touch-api/#comments</comments>
		<pubDate>Tue, 25 May 2010 14:58:07 +0000</pubDate>
		<dc:creator>Fredrik Olsson</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=5638</guid>
		<description><![CDATA[Cocoa Touch added API for presenting a view controller in a popup bubble in iPhone OS 3.2, the responsible class is named UIPopoverController. One would guess that this new class is a subclass of UIViewController, just like UINavigationController is, but that is not the case. One would also guess that in functionality many ideas for [...]]]></description>
			<content:encoded><![CDATA[<p>Cocoa Touch added API for presenting a view controller in a popup bubble in iPhone OS 3.2, the responsible class is named <code>UIPopoverController</code>. One would guess that this new class is a subclass of <code>UIViewController</code>, just like <code>UINavigationController</code> is, but that is not the case. One would also guess that in functionality many ideas for displaying a view controller as modal controller would have been moved over to displaying a view controller as a popover controller, but that is not the case either.</p>
<h3>Modal View Controllers are Easy</h3>
<p>Displaying a modal view controller is quite straight forward as this small example shows:</p>
<pre class="brush:objc">-(void)showDetails:(CWDetails*)details {
  UIViewController* vc = [[CWDetailsViewController alloc] initWithDetails:details];
  [self presentModalViewController:vc animated:YES];
  [vc release];
}</pre>
<h3>Popover View Controllers Can be Complex</h3>
<p>Displaying the same details view controller in a popover on iPad is not quite as straight forward:</p>
<pre class="brush:objc">-(void)showDetails:(CWDetails*)details fromBarButtonItem:(UIBarButtonItem*)item {
  UIViewController* vc = [[CWDetailsViewController alloc] initWithDetails:details];
  self.popoverController = [[[UIPopoverController alloc]
                                  initWithContentViewController:vc] autorelease];
  self.popoverController.delegate = self;
  [self.popoverController presentPopoverFromBarButtonItem:item
                                 permittedArrowDirections:UIPopoverArrowDirectionAny
                                                 animated:YES];
  [vc release];
}

-(void)popoverControllerDidDismissPopover:(UIPopoverController*)popoverController {
  self.popoverController = nil;
}</pre>
<p>As you see presenting a popover requires an extra object instance, this instance is not automatically retained while presenting the popover, like a modal view controller is, so the instance must be saved somewhere. In this example I saved the instance as a property. Notice that I also register as a delegate for the popover in order to remove this instance when the popover is dismissed. Here is another detail that is not obvious; this delegate callback is <strong>only</strong> called if user action dismisses the popover, not if you programmatically dismiss the popover. In the end using popovers quite quickly introduces a lot of code, and also coupling between view controllers for no other reason but to manage the popover instance.</p>
<p>Would it not be nice if you could instead do like this, and be done with it:</p>
<pre class="brush:objc">-(void)showDetails:(CWDetails*)details fromBarButtonItem:(UIBarButtonItem*)item {
  UIViewController* vc = [[CWDetailsViewController alloc] initWithDetails:details];
  [self presentPopoverViewController:vc fromBarButtonItem:item animated:YES];
  [vc release];
}</pre>
<p>In fact what we want is to have these methods added to the public API of <code>UIViewController</code>:</p>
<pre class="brush:objc">@interface UIViewController (CWPopover)

@property (nonatomic, retain, readonly) NSSet* visiblePopoverControllers;

-(void)presentPopoverViewController:(UIViewController*)controller
                  fromBarButtonItem:(UIBarButtonItem *)item
                           animated:(BOOL)animated;
-(void)presentPopoverViewController:(UIViewController*)controller
                           fromView:(UIView *)view
                           animated:(BOOL)animated;

-(void)dismissPopoverController:(UIViewController*)controller animated:(BOOL)animated;
-(void)dismissAllPopoverControllersAnimated:(BOOL)animated;

-(void)setContentSize:(CGSize)size forViewInPopoverAnimated:(BOOL)animated;

@end
</pre>
<h3>But That Requires Rewriting Existing Classes?</h3>
<p>Yes it does, in an ideal world we want new methods and properties on the existing <code>UIViewController</code> class, and all subclasses, just as if Apple had put them there. This can easily be done thanks to the dynamic nature of Objective-C.</p>
<p>The view controller that is going to present other view controllers in a  popover needs to have access to all <code>UIPopoverController</code> instances currently visible. The view controllers that are going to be presented in a popover need to have access to their container <code>UIPopoverController</code>, and for consistency with modal view controller its parent view controller. </p>
<p>Categories can only add and replace methods on an existing class, not modify instance variables. So we need to store this information in another way. I choose to tuck them away in a helper class called <code>CWViewControllerPopoverHelper</code>. With this small interface:</p>
<pre class="brush:objc">@interface CWViewControllerPopoverHelper : NSObject {
@private
    UIViewController* parentViewController;
    UIPopoverController* containerPopoverController;
    NSMutableSet* visiblePopoverControllers;
}
@property (nonatomic, assign) UIViewController* parentViewController;
@property (nonatomic, assign) UIPopoverController* containerPopoverController;
@property (nonatomic, retain) NSMutableSet* visiblePopoverControllers;

@end</pre>
<p>The implementation is just synthesized properties, so no need to duplicate that one here.</p>
<p>So now all we do is to stuff one instance of <code>CWViewControllerPopoverHelper</code> into a global map using the <code>UIViewController</code> as key for each view controller that needs these extra <em>instance information</em>.</p>
<h3>Fetching the Popover Helper</h3>
<p>Let's implement a helper method that lazily creates a <code>CWViewControllerPopoverHelper</code> instance and puts it into the global map when needed. This way any view controller that do not need to support popovers will never be bothered, and those who do manage popovers gets one instance with no fuzz:</p>
<pre class="brush:objc">static NSMutableDictionary* popoverHelpers = nil;

-(CWViewControllerPopoverHelper*)popoverHelper;
{
    NSValue* key = [NSValue valueWithPointer:self];
    if (popoverHelpers == nil) {
        popoverHelpers = [[NSMutableDictionary alloc] initWithCapacity:16];
    }
    CWViewControllerPopoverHelper* helper = [popoverHelpers objectForKey:key];
    if (helper == nil) {
        helper = [[[CWViewControllerPopoverHelper alloc] init] autorelease];
        [popoverHelpers setObject:helper forKey:key];
    }
    return helper;
}</pre>
<h3>Proper Memory Management</h3>
<p>There is one problem with storing the extra information in a global map; no view controller would ever be released from memory, since the map will hold on to the references. No problem, lets not use the actual view controller instance as a key, but a <code>NSValue</code> with the pointer to the instance. This solves the problem of releasing objects, but also means that the map will contain dangling pointers to released objects. We need to remove the dangling pointers whenever a <code>UIViewController</code> is deallocated.</p>
<p>Subclassing is not an option, since it would defeat our purpose of requiring the public API. It turns out we can replace the <code>-[UIViewController dealloc]</code> method with our own, and still call the original implementation. Each class and category that is loaded into the Objective-C run-time will call their own method <code>+[? load]</code> method, it is the public hook for further modifying a class or category before use. We want to use this hook to replace the default deallocation method with our own:</p>
<pre class="brush:objc">+(void)load;
{
    Method m1 = class_getInstanceMethod(self, @selector(dealloc));
    Method m2 = class_getInstanceMethod(self, @selector(cwPopoverDealloc));
    method_exchangeImplementations(m1, m2);
    m1 = class_getInstanceMethod(self, @selector(parentViewController));
    m2 = class_getInstanceMethod(self, @selector(cwPopoverParentViewController));
    method_exchangeImplementations(m1, m2);
}</pre>
<p>As a bonus we also replace <code>-[UIViewController parentViewController]</code>, to return the parent as would be expected for anyone who has ever presented a modal view controller. The implementations of our overrides are just as short and sweet:</p>
<pre class="brush:objc">-(void)cwPopoverDealloc;
{
    [self dismissAllPopoverControllersAnimated:NO];
    NSValue* key = [NSValue valueWithPointer:self];
    [popoverHelpers removeObjectForKey:key];
    [self cwPopoverDealloc];
}

-(UIViewController*)cwPopoverParentViewController;
{
    UIViewController* parent = [self popoverHelper].parentViewController;
    if (parent == nil) {
        parent = [self cwPopoverParentViewController];
    }
    return parent;
}</pre>
<h3>Wrapping Up</h3>
<p>From here on it is just a tedious work to implement all 50 more lines of code needed to actually present the popovers, the first method as an example:</p>
<pre class="brush:objc">-(void)presentPopoverViewController:(UIViewController*)controller
                  fromBarButtonItem:(UIBarButtonItem *)item
                           animated:(BOOL)animated;
{
    UIPopoverController* pc = [[[UIPopoverController alloc]
                                initWithContentViewController:controller] autorelease];
	[self addPopoverViewController:pc passthroughViews:views];
    [pc presentPopoverFromBarButtonItem:item
               permittedArrowDirections:UIPopoverArrowDirectionAny
                               animated:animated];
}</pre>
<p>The rest of the implementation, and a few other nice to have methods can be <a href='http://blog.jayway.com/wordpress/wp-content/uploads/2010/05/UIViewController+CWPopover.zip'>downloaded here</a>.</p>
<h3>Conclusions</h3>
<p>The dynamic nature of Objective-C means that you can rewrite any existing API to suit your needs, without having access to the original source code. Sometimes just to add a new utility function where it belongs; a <em>"sort by first name"</em> method should probably be added to the actual <em>people collection</em> class, not as a spurious utility class.</p>
<p>Or as shown in this example to make a public API more convenient to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2010/05/25/rewriting-a-public-cocoa-touch-api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>iPad, the Future, and the Luxury of Starting Over</title>
		<link>http://blog.jayway.com/2010/01/28/ipad-the-future-and-the-luxury-of-starting-over/</link>
		<comments>http://blog.jayway.com/2010/01/28/ipad-the-future-and-the-luxury-of-starting-over/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 20:02:59 +0000</pubDate>
		<dc:creator>Fredrik Olsson</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[cocoa touch]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[ipad]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://blog.jayway.com/?p=4550</guid>
		<description><![CDATA[A luxury that you seldom have in the world of software development is the luxury of starting over. I am not talking about throwing away everything and start from scratch. But just taking what you have, and all the experiences learned. Apply some major refactoring to make what works really shine, and without care of [...]]]></description>
			<content:encoded><![CDATA[<p>A luxury that you seldom have in the world of software development is the luxury of starting over. I am not talking about throwing away everything and start from scratch. But just taking what you have, and all the experiences learned. Apply some major refactoring to make what works really shine, and without care of dependent clients throw out everything that turned out to be irreparable.</p>
<p>The <a href="http://www.apple.com/ipad/">iPad</a> as presented by Apple on the <a href="http://www.apple.com/ipad/">special january 2010 event</a> is a showcase of how Apple has been given this luxury. Not just once but over and over again. Allowing for iterating, and improving with each restart.</p>
<h3>The origins</h3>
<p>The evolution of the software running the iPad can be traced back along with <a href="http://en.wikipedia.org/wiki/Steve_Jobs">Steve Jobs</a> himself. With the first <a href="http://en.wikipedia.org/wiki/Macintosh">Macintosh</a> from 1984 he was one of the many talented people behind ushering the graphical user interface into the world of normal people. </p>
<p>Not entirely by his own choice he founded <a href="http://en.wikipedia.org/wiki/NeXT">NeXT</a> in 1985, and got the luxury of starting over, equipped with the experience from the Macintosh project. The lessons learned resulted in the NeXT computers in 1989, a system way ahead of it's time, with <a href="http://en.wikipedia.org/wiki/NeXTSTEP">NextStep's</a> object oriented frameworks, before OOP had even caught on with the main stream. Remember this was before <a href="http://en.wikipedia.org/wiki/Windows_3.0">Windows 3.0</a>.</p>
<p>In late 1996 Apple bought NeXT and all their assets, including Steve Jobs as the CEO. Now the experience learned from developing the NeXT computers and the NextStep operating system could be used again. With the luxury of a reset once again, throwing out anything that did not work, and clean up the parts that worked well. The new operating system rising from the ashes would be named <a href="http://en.wikipedia.org/wiki/Mac_OS_X">Mac OS X</a>, and the application development frameworks be called <a href="http://developer.apple.com/cocoa/">Cocoa</a>.</p>
<h3>The tech as used today</h3>
<p>Cocoa is the primary application development framework for Mac OS X to this day. It is an umbrella framework, containing:</p>
<ul>
<li><a href="http://developer.apple.com/mac/library/navigation/index.html#section=Frameworks&topic=Foundation">Foundation</a> - For the non-visual low level components.</li>
<li><a href="http://developer.apple.com/mac/library/navigation/index.html#section=Frameworks&topic=Application%20Kit">AppKit</a> - For the components to create a desktop application with mouse and keyboard</li>
<li><a href="http://developer.apple.com/mac/library/navigation/index.html#section=Frameworks&topic=Core%20Data">Core Data</a> - For managing application data as a graph database.</li>
</ul>
<p>The application development framework for <a href="http://en.wikipedia.org/wiki/IPhone_OS">iPhone OS</a> is called <a href="http://developer.apple.com/iphone/library/navigation/index.html#section=Frameworks&topic=Cocoa%20Touch%20Layer">Cocoa Touch</a>. It is basically all the nice parts from Foundation, and since iPhone OS 3.0 also Core Data. But AppKit is missing, instead replaced by <a href="http://developer.apple.com/iphone/library/navigation/index.html#section=Frameworks&topic=UIKit">UIKit</a>. UIKit are the components needed to create a graphical user interface based on multitouch. Not a dumbed down version of AppKit, but a rewrite that is re-using the experience from AppKit. Refining what works well, removing what did not turn out so well, and adding what could not easily be added to AppKit.</p>
<p>Apple gave themselves the luxury of starting over yet again, not burdened by backward compaitibility. The new form factor of the iPhone can not inspire any realistic hopes for application compatibility with the Mac computers. </p>
<h3>Where can this lead?</h3>
<p>Mac OS X and the Cocoa frameworks where good from a tech standpoint, and for us nerds. But not ready for prime-time by the average user until at least version 10.2, or 10.3 if you are really honest. Many dismissed the first versions of Mac OS X, while others saw the potential. I see the same thing with iPad and iPhone OS, it will be dismissed for now, and others will see a great potential.</p>
<p>I think that the iPad is Apple's vision for the future of computing. Mice to be replaced by multi-touch. The keyword being <strong>multi</strong>-touch. A touch device is to a multi-touch device what a black and white TV is to a modern color HD TV. Sure they both display pictures, the basic idea is there, but the execution is on a different level. In 1984 with the first Macintosh a computer mouse was a novelty. Apple want to replace the secondary input of the mouse, with direct input and manipulation using your very fingers. Making the mouse computer mouse a parenthesis in the history of computing.</p>
<p><strong>The iPhone OS is the successor to Mac OS X.</strong></p>
<p>There I said it. There will never be a Mac OX X 11.0, and probably not a Mac OS X 10.8 either. That line of succession is over, the new blood line to reign is the offspring that is iPhone OS. A fresh start, a luxury in our industry, and also a necessity in order to take the great leaps to the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jayway.com/2010/01/28/ipad-the-future-and-the-luxury-of-starting-over/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

