<?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>iCab Blog &#187; Tips &amp; tricks</title>
	<atom:link href="http://www.icab.de/blog/category/tips-tricks/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.icab.de/blog</link>
	<description>iCab related stuff; Mac, iPhone and Cocoa programming</description>
	<lastBuildDate>Mon, 17 Oct 2011 15:03:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>elementFromPoint() under iOS 5</title>
		<link>http://www.icab.de/blog/2011/10/17/elementfrompoint-under-ios-5/</link>
		<comments>http://www.icab.de/blog/2011/10/17/elementfrompoint-under-ios-5/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 14:58:07 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[iPhone & iPod Touch]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips & tricks]]></category>
		<category><![CDATA[Web Technology]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[UIWebView]]></category>
		<category><![CDATA[WebKit]]></category>

		<guid isPermaLink="false">http://www.icab.de/blog/?p=214</guid>
		<description><![CDATA[The JavaScript call elementFromPoint(x,y) can be used to find the element of a web page at a certain coordinate. If you have used this call in the past on a web page or in a native iOS App which was developed for iOS 4.x or older, you&#8217;ll notice that your web page or App might [...]]]></description>
			<content:encoded><![CDATA[<p>The JavaScript call elementFromPoint(x,y) can be used to find the element of a web page at a certain coordinate. If you have used this call in the past on a web page or in a native iOS App which was developed for iOS 4.x or older, you&#8217;ll notice that your web page or App might fail when used under iOS 5. Under iOS 5 the elementFromPoint(x,y) call finds different elements or even returns null instead of an element. It looks like the call is now broken. But this is not the case, in fact, under iOS 5 it works correct the first time, it was broken before.</p>
<p>elementFromPoint(x,y) was defined to return the element at the given coordinates within the view port (the visible area) of the web page, or null (if the coordinates are outside of the viewport). The coordinates are measured relative to the origin of the view port. This is how iOS 5 finally works.</p>
<p>Before (iOS 4.x and older), elementFromPoint(x,y) completely ignored the view port. It measured the coordinates relative to the origin of the document. And even elements outside of the visible area could be found. This behavior seems to make much more sense than the new iOS 5 behavior, but according to the official JavaScript specification, it&#8217;s not the correct behavior.</p>
<p>The different behavior between iOS 5 and older iOS versions can cause some serious problems. The coordinate systems are no longer compatible, so when the web page or App has to run under old an new iOS versions, it is necessary to find out the correct coordinate system that is used.</p>
<p>In a native iOS App you could simply check the iOS version, and based on its value you can decide which coordinate system you need to use when calling elementFromPoint(x,y). But when writing a web page, this is not so easy: the iOS version is not exposed to the web page (it might be part of the UserAgent information, but because almost all browser do allow to use a fake userAgent information, this information is not reliably at all). Also on the Mac and on other platforms different WebKit releases might be used which do use different coordinate systems for the elementFromPoint(x,y) call as well. Therefore it makes sense to find a way to identify the coordinate system independent of the iOS version, and if necessary correct the coordinates.</p>
<p>At first when we compare the two coordinate systems, we notice that the coordinates are offset by the scroll location. If we scroll the web page so that the top left corner of the page is visible, both coordinate systems are the same. The origin of the view port is identical to the origin of the web page. And the scroll offset is also 0 in both directions. If you scroll down 100 px, the origin (the coordinate (0,0)) of the viewport is located at the coordinate (0,100) of the web page. So the scroll offset is exactly the offset between the two coordinate systems. Therefore, transforming one coordinate system into the other is very easy. We only need to add or subtract the actual scroll offsets.</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">
function documentCoordinateToViewportCoordinate(x,y) {
  var coord = new Object();
  coord.x = x - window.pageXOffset;
  coord.y = y - window.pageYOffset;
  return coord;
}

function viewportCoordinateToDocumentCoordinate(x,y) {
  var coord = new Object();
  coord.x = x + window.pageXOffset;
  coord.y = y + window.pageYOffset;
  return coord;
}
</pre>
<p>These JavaScript functions take a coordinate of one system and transform them into a coordinate of the other system.</p>
<p>But in order find out if and which of the functions we need to use, we have to find out, in which coordinate system the call elementFromPoint(x,y) expects the coordinates. To do this we use the fact that elementFromPoint() returns null when the coordinates are outside of the view port, when it expects coordinates measured relative to the viewport (as noted above, when the coordinates are relative to the origin of the document, elementFromPoint() will always return an element, even when outside of the visible area, so we can distinguish between the two cases).<br />
Good test coordinates would be (0, window.pageYOffset + window.innerHeight -1) and (window.pageXOffset + window.innerWidth -1, 0), for vertical scrolling and horizontal scrolling. As noted above, when no scrolling is done, both coordinate systems are identical, and we don&#8217;t need to take care about anything. But if the page is scrolled, we need to check which system is used. The test coordinates take the actual scroll offset and add the width or height of the visible area (this is the innerWidth and innerHeight of the &#8220;window&#8221; object) and subtract 1. This makes sure that the coordinate addresses the very last pixel line or column of the visible area measured relative to the document origin. This is always a valid document-based coordinate which lies within the document boundaries (a coordinate outside of the document boundaries would return null even with the elementFromPoint() call for the document-based coordinate system). If the page is scrolled by at least one single pixel, the test coordinates would lie outside of the viewport, when interpreted as relative to the viewport, so elementFromPoint() would return null. When elementFromPoint() would interpret them relative to the document, these coordinates are always valid and would always return an element. And this is how we can easily detect, which coordinate system elementFromPoint() is using.</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">
function elementFromPointIsUsingViewPortCoordinates() {
  if (window.pageYOffset > 0) {     // page scrolled down
    return (window.document.elementFromPoint(0, window.pageYOffset + window.innerHeight -1) == null);
  } else if (window.pageXOffset > 0) {   // page scrolled to the right
    return (window.document.elementFromPoint(window.pageXOffset + window.innerWidth -1, 0) == null);
  }
  return false; // no scrolling, don't care
}
</pre>
<p>We can combine this to one custom elementFromPoint() function that is using a document-based coordinate system as input and will internally do all the magic for us:</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">
function elementFromDocumentPoint(x,y) {
  if (elementFromPointIsUsingViewPortCoordinates()) {
    var coord = documentCoordinateToViewportCoordinate(x,y);
    return window.document.elementFromPoint(coord.x,coord.y);
  } else {
    return window.document.elementFromPoint(x,y);
  }
}
</pre>
<p>And the counterpart for viewport-based coordinates:</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">
function elementFromViewportPoint(x,y) {
  if (elementFromPointIsUsingViewPortCoordinates()) {
    return window.document.elementFromPoint(x,y);
  } else {
    var coord = viewportCoordinateToDocumentCoordinate(x,y);
    return window.document.elementFromPoint(coord.x,coord.y);
  }
}
</pre>
<p>So instead of using elementFromPoint() directly, you simply use elementFromViewportPoint() or elementFromDocumentPoint() instead, depending of the coordinates you have to deal with. It will then work correct in old and new WebKit releases.</p>
<p>Please note: if you use the code of my older blog post &#8220;<a href="http://www.icab.de/blog/2010/07/11/customize-the-contextual-menu-of-uiwebview/">Customize the contextual menu of UIWebView</a>&#8221; in your projects, you need to update this as well, because it also uses the elementFromPoint() call. But this should be really easy to do.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.icab.de/blog/2011/10/17/elementfrompoint-under-ios-5/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Adding JavaScript files as &#8220;Resources&#8221; to an XCode project</title>
		<link>http://www.icab.de/blog/2011/08/02/adding-javascript-files-as-resources-to-an-xcode-project/</link>
		<comments>http://www.icab.de/blog/2011/08/02/adding-javascript-files-as-resources-to-an-xcode-project/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 18:53:21 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[iPhone & iPod Touch]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips & tricks]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[XCode]]></category>

		<guid isPermaLink="false">http://www.icab.de/blog/?p=202</guid>
		<description><![CDATA[Because of the limited API of the UIWebView class in the iOS, developers are often forced to use JavaScript in order to implement features which are not supported by the UIWebView class itself. The amount of JavaScript code that is needed can easily reach limits you can&#8217;t manage by using normal strings anymore. So you [...]]]></description>
			<content:encoded><![CDATA[<p>Because of the limited API of the UIWebView class in the iOS, developers are often forced to use JavaScript in order to implement  features which are not supported by the UIWebView class itself. The amount of  JavaScript code that is needed can easily reach limits you can&#8217;t manage by using normal strings anymore. So you would like to write the JavaScript code in separate files, organized by task, like you would do this for Objective C classes. In the sample code in my blog posts I&#8217;ve done this as well. Though this is not very complicated, there are nevertheless a lot of developers having problems with this. This is why I would like to explain more detailed, what you need to do, and why there are these difficulties.</p>
<p>In general, when you have to use JavaScript code to do certain tasks on a web page, you need to inject this code into the web page when it is loaded. The UIWebView provides a delegate method &#8220;webViewDidFinishLoad:&#8221; which is called whenever a web page has finished loading. This is the correct location to inject your JavaScript code into the web page. And to inject JavaScript code into a web page you can use the method &#8220;stringByEvaluatingJavaScriptFromString:&#8221; of the UIWebView class.</p>
<p>In most cases you can just use the view controller which manages your UIWebView object as delegate for the UIWebView. When defining the view hierarchy and the view controller in Interface Builder, you can set the delegate for the UIWebView directly within Interface Builder, so you even don&#8217;t need to write any code for this. But you can also set the delegate in code, for example in the &#8220;viewDidLoad&#8221; method of the view controller. And in addition, the delegate (the view controller) has to implement the &#8220;webViewDidFinishLoad:&#8221; method, in order to get notified when the web page has finished loading.  Please note that the &#8220;loadRequest:&#8221; method of UIWebView loads the page asynchronously, so when  this method returns you can not assume that anything from the page has already loaded. Which means it is essential that you wait until the method &#8220;webViewDidFinishLoad:&#8221; is called.</p>
<p>The following example shows how this can be done in a view controller implementation (this example assumes that the JavaScript code is stored in a file &#8220;JavaScriptFile.js&#8221; within the resources of your App):</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">- (void)viewDidLoad
{
  // If not done in the InterfaceBuilder, you need to set the delegate for the UIWebView object
  // so that you're notified when the page has loaded (via "webViewDidFinishLoad:")
  [webView setDelegate:self];

  // ...
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
  // Loading and injecting your JavaScript code into the webView, so you can actually use it
  // in the context of the web page that was loaded...
  NSString *path = [[NSBundle mainBundle] pathForResource:@"JavaScriptFile" ofType:@"js"];
  NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
  [webView stringByEvaluatingJavaScriptFromString:jsCode];

  // ...
}</pre>
<p>This is more or less everything you need to care about when programming JavaScript helper functions and injecting them into the web view objects. You can use the   method &#8220;stringByEvaluatingJavaScriptFromString:&#8221; to call your helper functions afterwards and getting the results from your JavaScript functions as Cocoa string.</p>
<p>But there&#8217;s another detail you need to care about which is related to XCode itself. And this seems to be something many users are not aware of and what can cause your App to fail.</p>
<p>When building an App, XCode is doing this is several phases, like compiling the source code files, linking the object files and frameworks and copying all resources into the App bundle. The problem here is that XCode recognizes a JavaScript file as &#8220;Source Code&#8221; and therefore adds this file into the &#8220;Compile Sources&#8221; phase. But this is not correct in our case because the JavaScript file can not be compiled and linked to the object code of our App. The JavaScript file will be executed in the context of a web page within the UIWebView, so it&#8217;s not part of the &#8220;native&#8221; executable code of the App. The JavaScript code must be treated as &#8220;Resource file&#8221; and added as Resource file into the App bundle. Then we can load the file as resource within the App and inject its content to the web view.</p>
<p>XCode lets you inspect and edit the build phases of your project. Usually you don&#8217;t need to care about this because XCode is doing everything correct automatically. But not when adding JavaScript files. So you have to make sure that all JavaScript files which are listed in the &#8220;Compile Source&#8221; phase are moved to the &#8220;Copy Bundle Resources&#8221; phase. If you forget this, the JavaScript file won&#8217;t be copied to the resources of the App and when the App is running, it won&#8217;t be able to find and load the JavaScript files. So, always make sure that the JavaScript files are listed in the correct build phase.</p>
<p>The following screenshots will show you, where you find the &#8220;build phase&#8221; settings in your XCode project. The red circles indicate where you need to click to open lists or tables to find the settings.</p>
<p>This shows the location in XCode 3.x:<br />
<a href="http://www.icab.de/blog/wp-content/uploads/xc3.jpg"><img class="alignnone size-full wp-image-203" title="XCode 3" src="http://www.icab.de/blog/wp-content/uploads/xc3-small.jpg" alt="" width="181" height="241" /></a></p>
<p>And this shows the location in XCode 4.x:<br />
<a href="http://www.icab.de/blog/wp-content/uploads/xc4.jpg"><img class="alignnone size-medium wp-image-205" title="XCode 4" src="http://www.icab.de/blog/wp-content/uploads/xc4-small.jpg" alt="" width="475" height="268" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.icab.de/blog/2011/08/02/adding-javascript-files-as-resources-to-an-xcode-project/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Scaling images and creating thumbnails from UIViews</title>
		<link>http://www.icab.de/blog/2010/10/01/scaling-images-and-creating-thumbnails-from-uiviews/</link>
		<comments>http://www.icab.de/blog/2010/10/01/scaling-images-and-creating-thumbnails-from-uiviews/#comments</comments>
		<pubDate>Fri, 01 Oct 2010 19:58:33 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[iPhone & iPod Touch]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips & tricks]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.icab.de/blog/?p=174</guid>
		<description><![CDATA[In this blog post I would like to show how you can do some common image-related tasks, like scaling an UIImage object or creating a thumbnail image from a UIView. I&#8217;m implementing these features as category for the UIImage class, so these can be used with all UIImage objects without the need to subclass the [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog post I would like to show how you can do some common image-related tasks, like scaling an UIImage object or creating a thumbnail image from a UIView. I&#8217;m implementing these features as category for the UIImage class, so these can be used with all UIImage objects without the need to subclass the UIImage class.</p>
<h3>Scaling UIImages</h3>
<p>Scaling images is important for example when you want to create thumbnail images which are used as an overview for real documents or larger pictures. The standard UIImage class doesn&#8217;t provide a method to scale images, but scaling an image isn&#8217;t very complicated. You can do it with just 4 lines of code&#8230;</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">UIImage *originalImage = ...;
CGSize destinationSize = ...;

UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();</pre>
<p>At first we have to create and start an image context with the size of the resulting image. All drawing operations which take place after the UIGraphicsBeginImageContext() call will be done in the newly created image context. This means, we are no longer drawing on the screen. All we need to do now is to draw the original image in the size of the final image. The drawing takes place in the newly created image context. Afterwards we can use UIGraphicsGetImageFromCurrentImageContext() to get an image from the image context. Finally we need to call UIGraphicsEndImageContext() to make sure that the system will release the image context again, because we don&#8217;t need it anymore. And of course the drawing will take place on the screen again after calling this function.</p>
<h3>Creating an UIImage from a UIView</h3>
<p>If you need an image from the content of a UIView object (like a whole web page that is displayed in a UIWebView object) or even a complex hierarchy of UIView objects so you can save it as PNG or JPEG image or use it as thumbnail image, you can do this also with just a few lines of code&#8230;</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">UIView *view = ...;

CGSize size = [view bounds].size;
UIGraphicsBeginImageContext(size);
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();</pre>
<p>The code is very similar to the code from above to scale the image. But instead of drawing an image into the new image context, we use the &#8220;renderInContext:&#8221; method to draw the content of the view (which includes its subviews) into the image context. The resulting image will have the same size as the original UIView.</p>
<h3>Retina Display</h3>
<p>With the new iPhone 4 and the 4th generation iPod Touch, the iOS does also support high resolution screens. But the larger screen resolution is not used to display more content, instead it is used to display a sharper image with more details. Basically the iOS uses the same coordinate system on all screens with a size of  480&#215;320 points. The only difference of the retinal displays is that there&#8217;re additional pixels between these points. Most drawing functions of the iOS automatically use these additional pixels to draw sharper and more detailed content. But there are exceptions when the iOS can not create more details itself. For example for bitmap images (UIImage objects), there&#8217;s no way to automatically generate a more detailed image for the retina displays. So iOS 4.0 introduces a new &#8220;scale&#8221; property for images. This property can be 1.0 (the default value) which is used for standard resolution and 2.0 for the more detailed retina resolution with twice as much details. If the &#8220;scale&#8221; property has a value of 1.0, one pixel of the image will be drawn on 2*2 (= 4 pixels) on the retina display, if the &#8220;scale&#8221; property has a value of 2, one image pixel is drawn on one screen pixel.</p>
<p>The above code will work with all iOS releases (including iOS 3.x which is the latest version that can be used on the first generation iPhone and iPod Touch devices), but it will always use the default &#8220;scale&#8221; property of 1.0 for images. Which means the code can not improve the image quality on the new retina displays. In order to get more detailed images on retina displays, we need to use &#8220;UIGraphicsBeginImageContextWithOptions()&#8221; instead of &#8220;UIGraphicsBeginImageContext()&#8221;, so we can define the &#8220;scale&#8221; property for the new image context as well.  But &#8220;UIGraphicsBeginImageContextWithOptions()&#8221; is only available since iOS 4, so we have to check if we can use this function. If it is not available or if the device does not have a retina display, we still need to use the default scaling of 1.0 &#8230;</p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
     if ([[UIScreen mainScreen] scale] == 2.0) {
        UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
     } else {
        UIGraphicsBeginImageContext(size);
    }
} else {
    UIGraphicsBeginImageContext(size);
}</pre>
<h3>Combining everything into a Objective-C Category</h3>
<p>Now it&#8217;s time to combine all of the above and create a category for the UIImage class. I&#8217;m implementing three simple methods to create a new UIImage from a UIView or UIImage object.</p>
<ul>
<li>&#8220;<strong>imageWithImage:scaledToSize:</strong>&#8221; creates an image from a UIImage and scales it to a given size</li>
<li>&#8220;<strong>imageFromView</strong>:&#8221; creates an image from a UIView</li>
<li>&#8220;<strong>imageFromView:</strong>&#8221; creates an image from a UIView and scales it to a given size.</li>
</ul>
<p><span style="color: #993300;">MyImage.h:</span></p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">@interface UIImage (MyImage)
+ (UIImage*)imageFromView:(UIView*)view;
+ (UIImage*)imageFromView:(UIView*)view scaledToSize:(CGSize)newSize;
+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize;
@end</pre>
<p><span style="color: #993300;">MyImage.m:</span></p>
<pre style="padding-left: 0.7em; border-left: 1px solid #030; color: #003300; font-size: 0.9em;">#import "MyImage.h"

@implementation UIImage (MyImage)

+ (void)beginImageContextWithSize:(CGSize)size
{
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        if ([[UIScreen mainScreen] scale] == 2.0) {
            UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
        } else {
            UIGraphicsBeginImageContext(size);
        }
    } else {
        UIGraphicsBeginImageContext(size);
    }
}

+ (void)endImageContext
{
    UIGraphicsEndImageContext();
}

+ (UIImage*)imageFromView:(UIView*)view
{
    [self beginImageContextWithSize:[view bounds].size];
    BOOL hidden = [view isHidden];
    [view setHidden:NO];
    [[view layer] renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    [self endImageContext];
    [view setHidden:hidden];
    return image;
}

+ (UIImage*)imageFromView:(UIView*)view scaledToSize:(CGSize)newSize
{
    UIImage *image = [self imageFromView:view];
    if ([view bounds].size.width != newSize.width ||
            [view bounds].size.height != newSize.height) {
        image = [self imageWithImage:image scaledToSize:newSize];
    }
    return image;
}

+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
    [self beginImageContextWithSize:newSize];
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    [self endImageContext];
    return newImage;
}
@end</pre>
<h3>Optimizations</h3>
<p>Scaling images can temporarily require lots of additional memory, depending of the size of the images. The original image is first drawn in an image context. This image context must provide a bitmap buffer internally in which the drawing takes place. This buffer needs some memory. Also when the final image is created from this image context, some more memory is required. Only afterwards it is possible to free up the memory again by releasing the image context and maybe the original image.</p>
<p>For retina displays, the bitmap buffers for images where the &#8220;scale&#8221; property has a value of 2.0 are four times larger as for non-retina displays (scale = 1.0). So a single full screen image requires approximately 2.5 MB of memory. And because multiple bitmap buffers are required while scaling, the memory requirements can be much higher than without retina display.</p>
<p>This is not a big deal for the iPhone 4 which has much more main memory (512 MB) than all other devices. But for the 4th generation iPod Touch, the increased memory usage for the image buffers for the retina display is a problem. The 4th generation iPod Touch only has 256 MB of main memory, so it&#8217;s almost always running on its memory limits.</p>
<p>So to reduce the memory usage when creating a small thumbnail image from a UIView (which means you&#8217;re only interested in a scaled-down(!) image from a UIView), you should first create an image from the UIView with a &#8220;scale&#8221; property of 1.0. This will reduce the memory usage for the newly created image from the view. And because you&#8217;re about to scale down this image, it doesn&#8217;t matter that it doesn&#8217;t have all the details it would have with scale=2.0. When you then scale down this image using a &#8220;scale&#8221; property of 2.0, the final (smaller) image can still can get all the details it needs from the image you&#8217;ve created before.</p>
<p>If you have to create many images form large UIViews, you may consider to try to reduce the memory requirements this way (especially for iPod Touch with its limited amount of RAM). If you only need to deal with a few smaller views, you probably don&#8217;t need to care about this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.icab.de/blog/2010/10/01/scaling-images-and-creating-thumbnails-from-uiviews/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Moving objects within an NSMutableArray</title>
		<link>http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/</link>
		<comments>http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 17:17:28 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[iPhone & iPod Touch]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips & tricks]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.icab.de/blog/?p=105</guid>
		<description><![CDATA[In this blog post I&#8217;d like to address a common task in iPhone Apps: letting the user reorder entries of a list that is managed by a UITableView. In many cases this would internally simply result in moving an object within an array from one index to another index. The standard array classes of Cocoa don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>In this blog post I&#8217;d like to address a common task in iPhone Apps: letting the user reorder entries of a list that is managed by a UITableView. In many cases this would internally simply result in moving an object within an array from one index to another index. The standard array classes of Cocoa don&#8217;t have a method for this task, so we simply implement our own. But there are a few &#8220;traps&#8221; and concepts we should be aware of (like &#8220;abstract classes&#8221;, &#8220;categories&#8221;), and which I like to mention here as well.</p>
<p>When developing Apps for the iPhone and iPod Touch, it&#8217;s likely that you&#8217;re using UITableView objects to display the content of your App. UITableView is one of the most important Views of the iPhone OS and used for all kinds of lists and data that can be provided as list. In most cases you would store your data in an NSArray or NSMutableArray object and each row of the table represents an item of this array. In case your app allows the user to reorder the table entries, you would have to implement the following delegate method of the UITableView class:</p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">- (void)tableView:(UITableView *)tableView
         moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
                toIndexPath:(NSIndexPath *)toIndexPath</pre>
<p>This delegate method is called whenever the user has enabled the &#8220;edit&#8221; mode of the table and has moved a table entry to another location. Within this method, you have to reorder the items of your own data storage (the array) so that the new representation of the table matches the order of the items within your array again. But if you look at the methods of the NSMutableArray class, you won&#8217;t find a method to do this directly. There&#8217;s no method to move an object of the array from one index to another. But because this is a task which we need very often (almost all iPhone Apps do have tables and in many cases it makes sense that the users of our App should be able to reorder the table entries), we will add a new method to the NSMutableArray class which is doing this, so we don&#8217;t have to implement the same code over and over again.</p>
<p>Subclassing NSMutableArray to add the new method would be possible, but is not the way I would choose here. NSMutableArray is an <strong>abstract class</strong> and a subclass would not inherit the data storage of the parent class. This means when subclassing, we would have to create and maintain our own data storage and would also have to implement all of the basic methods to set and get array items. Many of the basic data storage classes of the Cocoa Frameworks are abstract classes, so be aware when you plan to subclass these classes. Remember that you have to provide your own data storage if you do so.</p>
<p>But Objective-C provides other ways to add methods to an existing class, so subclassing is not necessary. We can define a <strong>category</strong> for the new method. A category can be used to add new methods to existing classes without subclassing them. This has the benefit that these new methods are even available for objects which are created by code which we can&#8217;t control, like objects created and returned by the system frameworks. But the downside is that a category can not add any additional member variables or additional data storage to the class. The reason is simple, the memory that is occupied by an object of the base class must remain the same. The other frameworks and code which doesn&#8217;t know about the new methods are still allocating only the memory for the base class when they create a new object. So a category can only add new behavior (methods), but no new data (member variables).</p>
<p>For our task, a category is just what we need: we don&#8217;t need additional variables or data storage, we just need to implement a new behavior (method) to move an array object from one index to another index. We name this new method &#8220;moveObjectFromIndex:toIndex:&#8221;</p>
<p>The implementation of the category would look like this:</p>
<p><span style="color: #993300;">MoveArray.h:</span></p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">@interface NSMutableArray (MoveArray)

- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to;

@end</pre>
<p><span style="color: #993300;">MoveArray.m:</span></p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">#import "MoveArray.h"

@implementation NSMutableArray (MoveArray)

- (void)moveObjectFromIndex:(NSUInteger)from toIndex:(NSUInteger)to
{
    if (to != from) {
        id obj = [self objectAtIndex:from];
        [obj retain];
        [self removeObjectAtIndex:from];
        if (to &gt;= [self count]) {
            [self addObject:obj];
        } else {
            [self insertObject:obj atIndex:to];
        }
        [obj release];
    }
}
@end</pre>
<p>The code is very simple: we first remove the object from its original location and insert it at the new location or add it to the end of the array when the new location is beyond the array bounds. As you can see, though we do not subclass NSMutableArray, we can still use the &#8220;self&#8221; keyword just like we would have done this in a subclass. Also note when defining a category there&#8217;s no block where you can define member variables (within &#8220;{&#8230;}&#8221; like you can do this when subclassing), but instead you can only give the category a name (in this case &#8220;(MoveArray)&#8221;). This is because you can&#8217;t change the memory allocation for the class (see above).</p>
<p>Now, whenever we need to move an array object from one index to another (in a NSMutableArray object), we can simply call</p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">[array moveObjectFromIndex:from toIndex:to];</pre>
<p>As you can see, though we haven&#8217;t sub-classed NSMutableArray, the new method is called exactly in the same way as any other methods of the NSMutableArray class. This makes categories a very powerful and flexible feature.</p>
<p>For our initial UITableView  example, implementing the UITableView delegate method &#8220;tableView:moveRowAtIndexPath:toIndexPath:&#8221; would be very simple now. In most cases we could just do the following:</p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">- (void)tableView:(UITableView *)table
               moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
                      toIndexPath:(NSIndexPath *)destinationIndexPath
{
    [array moveObjectFromIndex:[sourceIndexPath row]
                       toIndex:[destinationIndexPath row]];
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Calling iCab Mobile from within Safari on the iPhone</title>
		<link>http://www.icab.de/blog/2009/09/07/calling-icab-mobile-from-within-safari-on-the-iphone/</link>
		<comments>http://www.icab.de/blog/2009/09/07/calling-icab-mobile-from-within-safari-on-the-iphone/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 21:03:20 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[iCab]]></category>
		<category><![CDATA[iPhone & iPod Touch]]></category>
		<category><![CDATA[Tips & tricks]]></category>
		<category><![CDATA[iCab Mobile]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Safari]]></category>

		<guid isPermaLink="false">http://www.icab.de/blog/?p=53</guid>
		<description><![CDATA[Almost all apps on the iPhone can easily open a URL in Safari. But normally you can&#8217;t open a URL from within Safari in other apps, for example in iCab Mobile (V 1.7). But with a &#8220;bookmarklet&#8221; (a special bookmark which is based on JavaScript code) you can do this as well. Here&#8217;s how the [...]]]></description>
			<content:encoded><![CDATA[<p>Almost all apps on the iPhone can easily open a URL in Safari. But normally you can&#8217;t open a URL from within Safari in other apps, for example in iCab Mobile (V 1.7).</p>
<p>But with a &#8220;bookmarklet&#8221; (a special bookmark which is based on JavaScript code) you can do this as well. Here&#8217;s how the bookmark URL for the bookmarklet should look like:</p>
<pre style="padding-left:0.7em; border-left: 1px solid #030; color: #003300; font-size:0.9em">    javascript:location.href='web'+location.href.substring(4);</pre>
<p>Because you can&#8217;t create Bookmarks from scratch in Safari on the iPhone, you should just create a bookmark of a random page and change its URL to the above line and the title to &#8220;Open in iCab Mobile&#8221;.</p>
<p>If you open this bookmarklet from within the Safari bookmarks, the currently displayed web page is passed to iCab Mobile and opened there.</p>
<p>The bookmarklet simply changes the URL scheme from &#8220;http&#8221; to &#8220;web&#8221; and from &#8220;https&#8221; to &#8220;webs&#8221;. And because iCab Mobile supports the &#8220;web&#8221; and &#8220;webs&#8221; schemes as a replacement for &#8220;http&#8221; and &#8220;https&#8221;, the iPhone OS will pass these modified URLs to iCab Mobile.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.icab.de/blog/2009/09/07/calling-icab-mobile-from-within-safari-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
	</channel>
</rss>

