BuySellAds.com

Our DNA is written in Objective-C
Jump

Category Archive for ‘Q&A’ rss

Accessing the iOS System Log

Peter Reinhardt asks:

The app AppSwitch displays the console entries from NSLog logging in the iphone app. I tried to figure out how they do it but couldnt find an API. Do you have an idea?

Intriguing question! My first gut reaction was that the guys from AppSwitch must have some magic sauce as I didn’t know of a way to access the console log on device like the Xcode organizer is able to. My first response was that probably they are doing some stderr bending as is possible with c++. But then I bought the app to see their trick with my own eyes.

In this blog post I’ll show you how that’s done.

Read more

JSON versus PLIST, the Ultimate Showdown

Communicating with web services you have to decide on a way to transport the date back and forth. Recently – with the help of the popular Twitter-API – JSON seems to have come ahead in the race. Other contenders are property lists and XML. Property Lists (PLISTs) are available in XML-Text and a binary (“old”) format and are widely supported in the Apple APIs which makes them a joy to work with.

JSON files on the other hand are easy to be generated server-side as they are basically just concatenated text, much less verbose than pure XML. The binary alternative might also be a contender when it comes to performance in transmission and parsing, provided some component is installed on the server to generate them.

In this blog article we are trying to answer the question once and for all what you should use in your own apps.

Read more

Bars Like the New York Times App

Elias Sanchez asks:

Hello Oliver. Quick? Do you have any tips in making a toolbar appear/disappear? Trying to mimic what the NYT app does when looking at an article. Is it using Core Animation perhaps? Can’t find anything out there. Any ideas? ThxU

Looking at the NYT App you can see that they do quite a bit of manipulation of the bars of which there are 3: Tab Bar, Navigation Bar and sometimes a Tool Bar.

For beginning iOS Developers it might seem daunting to combine all of these for the effect that the NYT App achieves. In this article I give you an analysis of what they did so that you have their techniques at your disposal, too.

Read more

How to become GREAT at iOS Development

I’m interested in getting your questions because answering them helps me structure the material in my head. And there’s a saying that “what you teach you learn”, because of that.

Devin Snipes, an aspiring young iOS Developer asks:

Hello Dr. Touch,

My name is Devin Snipes, I’m 15 years old and I’m an iPhone Developer. I’ve been following your work for a little less than a year, and I’ve grown to love it. Your work is amazing, and I hope to someday be as good as you are in programming for the iOS platform. I currently have a few iPhone applications on the AppStore, but nothing compared to yours.

I’d like to ask you a few questions that will hopefully give me more insight on your developmental skills and how I can improve on my skill.

Well, “You catch more flies with honey than vinegar”. If somebody asks so nicely I’ll usually try to respond with something useful.

1. How did you become so great at programming for the iPhone?

I’m doing it full time only since last December. And before that I was looking at code on most days for a couple of hours. Do you know the rule of 10,000? It says that if you want to be world-class in any field you have to invest 10,000 hours in total. Before I got into developing for the iPhone I was collecting programming time for many years. So I probably reached 10,000 a while ago. But that’s not strictly Cocoa time. At 10 hours a day it takes you around 3 years to reach 10,000. So I’m probably around 5,000 hours doing iPhone stuff.

Read more

Drawing on UIImages

Jayesh asks:

Thanks for your article on UIImage from UIView.

Need one more favor; I am in situation where I want to draw line or area (e.g. rectangle) on UI Image (e.g. Blue print) and save it again.

Basically I will show image and put circle / rectangle on image showing area in blue print and save it.

How should I do that? Can you please suggest approach, sample codes etc?

So the task is to take a UIImage, make it writable in some way and then make a new image out of that for later use. Off the top of my head, I can immediately think of two ways to do that: with UIKit and with CoreGraphics. CoreGraphics has a slight advantage, being lower level, of being thread-safe. But for a simple graphical addition to an existing image I see nothing wrong with UIKit. As usual you should only do very quick operations with UIKit because it requires to be run on the main thread which is the only thread updating the user interface.

Read more

Service Announcement: Upgrading iOS 4 GM

A not-to-be-named friend asked me:

I would like your opinion the GM build. Should I (not sure how) remove it and then load the new iOS 4.0? I know it wouldn’t have the game center, but I don’t use that anyway. I am afraid if I don’t remove, the software will expire (happened on beta 4 and then I couldn’t use the phone (or back up first) until I could load the latest.

If you’re one of those developers that managed to install the iOS 4.0 Gold Master right after Uncle Steve announced it, then you might wonder if you should update to the really final release that came out just now.

Wait! That’s a trick question…!

Read more

Timing is Everything

zeke817 asks:

Hey guys just wondering how to put a timer in the appdelegate. I need a timer to keep playing on through multiple views instead of just playing on 1 view. Any help apperciated

Using timers is pretty simple. There are plenty examples around and it’s not difficult to understand. Having said that, I am responding to this question for three reasons:

  1. my posts on my blog have been pretty scarce recently due to lots of programming for customer projects
  2. I think I should at least document how I am using timers so that I can refer people to this post when the question arises again and again.
  3. Explaining a simple thing to somebody else is the best way to train clarity in teaching.

Generally speaking timers are not instantiated but scheduled. The difference is that the SDK/OS takes care of their memory management and we only have to worry about whether or not we want them to fire. So we don’t need to ever release a timer, instead we invalidate it.

Read more

“Are You a Cocoa Crack?” Quiz (2)

It’s been more than half a year since I published the first installment of this Quiz aimed at Cocoa Cracks. Back then people seemed to like the challenges I presented. So I collected a few more nuggets. If you ever stumbled on an crash or strange result that you did not expect, then mail it to me.

These questions will show if you are really the Cocoa Crack you like to believe to be. To see the answer highlight the answer text with your mouse. No peeking! Respond in the comments how many you got correct.

Quiz: Warm Up. Your UI designer gave you a PNG with the instruction “just tile this in the background” of a UIView. Do you have to subclass UIView, overriding the drawRect of the view and performing drawImage for all tiles? Or is there a simpler method?

Answer: You create a UIImage by loading the PNG and then create a “color” from it with [UIColor colorWithPatternImage:image]. Then you apply this as the background color of the view.


Quiz: Suddenly your app crashes and when the debugger opens it first loads lots of stack frames. All you did is override a property like shown below. What’s the bug? Bonus Question: where’s the memory leak?

- (void) setTextColor:(UIColor *)newTextColor
{
	if (newTextColor != textColor)
	{
		[textColor release];
 
		if (newTextColor)
		{
			self.textColor = [newTextColor retain];
		}
		else // default
		{
			self.textColor = [[UIColor whiteColor] retain];
		}
		bubbleView.highlightedTextColor = textColor;
	}
}

Answer: You have an endless recursion. self.textColor is a simplified way to write [self setTextColor:]. So this method keeps calling itself until the stack is full and your app gets terminated. The leak is calling retain on an assignment to a retaining property. But if you fix the crashing bug by removing both self then there is no leak.


Quiz: You want to draw two lines in a drawRect, a horizontal black line and a white line 1 pixel below it. So you write the following code. But instead of the intended result you get this picture in magnification, the black is dark gray and the white is a lighter shade of gray. Why is that and how would you fix it?

CGContextRef currentContext = UIGraphicsGetCurrentContext();
 
// Draw a black line at the top and a white line 1 pixel below
 
CGContextSetLineWidth(currentContext, 1);
 
CGContextSetRGBStrokeColor(currentContext, 0.0, 0.0, 0.0, 1.0); // Black
CGContextMoveToPoint(currentContext, 0, 0); // top left
CGContextAddLineToPoint(currentContext, rect.size.width, 0); // to top right
CGContextStrokePath(currentContext);
 
CGContextSetRGBStrokeColor(currentContext, 1.0, 1.0, 1.0, 1.0); // White
CGContextMoveToPoint(currentContext, 0, 1); // left
CGContextAddLineToPoint(currentContext, rect.size.width, 1);
CGContextStrokePath(currentContext);

Answer: Core Graphics does not work on pixels directly, that’s why you use floating point numbers for coordinates. It works on coordinates and the resulting bitmap is always rendered. Half of the line width is always applied half a unit to each side of the line. To remedy this you need to move the coordinates of the lines by half a unit up or down.

(Thanks to Michael Kaye for sending this in)


Quiz: You have a UITableView and would like for it to have rounded corners. What’s the fastest way to achieve that? Which header is necessary?

Answer: You can have any UIView have rounded corners by setting the cornerRadius property of it’s CALayer. The layer of a UIView is actually what’s responsible for drawing the contents of the view. You need: to import <QuartzCore/QuartzCore.h>


Quiz: You have created a UIViewController which shows a UIWebView and has a navigation bar. You want to set the title on the bar to be the same as the title of the HTML document once loading has finished. Would you need to parse the HTML with NSScanner to find the <title> tag and extract it? Or is there a simpler method?

Answer: In the webViewDidFinishLoad: delegate method you retrieve the title via javascript and set it like that. self.title = [webView stringByEvaluatingJavaScriptFromString: @”document.title”];


Quiz: You have written code to load some UIImages in the background (performSelectorOnBackgroundThread or NSInvocationOperation). The loading code calls the method below to resize the loaded image. This has “always working before”, but suddenly you keep getting a EXC_BAD_ACESS on the line marked. You have double checked all retains and even set NSZombieEnabled to YES because usually you get this message if you are using an overreleased object. But that did not fix the problem. What’s the reason for the crash and how would you fix it?

+ (UIImage*)imageWithImage:(UIImage*)image
			  scaledToSize:(CGSize)newSize;
{
	UIGraphicsBeginImageContext( newSize );
	[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];   // &lt;- crash
	UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
 
	return newImage;
}

Answer: UIKit is not thread-safe. Therefore all drawing via UIKit needs to happen on the main thread. The UIGraphicsBeginImageContext works to create the context, but the memory for it is owned to the main thread and trying to access it with drawInRect from another thread is causing this exception. To fix it you need to rewrite this method to create your own bitmap context on the non-main thread so that you then own the memory for it. After creating the bitmap context you draw the image to it with CGContextDrawImage and then create a new CGImage with CGBitmapContextCreateImage. From the CGImage you create a UIImage to return from the method.


Quiz: Off the top of your head: how many methods do you know of having a piece of code contained in one method being performed in the background? Which?

Answer: Correct Answers are: performSelectorOnBackgroundThread and creating an NSInvocationOperation from the selector as those work on an existing method. Creating an NSOperation sub-class or manual threading with NSThread are also valid answers, but those require that you move the code into a new class or need to be well versed with threading voodoo.


So how many answers did you know? Be honest! If you also have a Cocoa riddle like these to contribute please mail them directly to me (oliver@drobnik.com) and I will publish them in this format.

UIImageView + Touch Handling = UIButton

gdscei asks:

“Hello, how can i make an image view work as a button? I want it to be assigned to the ‘reload’ action of WebView.
Can someone give me instructions how to do this?”

Often people start out constructing their UI visually, starting with this line of reasoning “I want to show an image. Ah, UIImageView”. So they create the visual appearance of their UI either by clicking it together in Interface Builder or – if slightly more advanced in their coding skills – creating those image views in code.

So if we create a new view-based project in XCode, we could modify the viewDidLoad of the main view controller like this to show the image:

- (void)viewDidLoad {
    [super viewDidLoad];
 
	UIImageView *imageView = [[UIImageView alloc] initWithFrame:
		CGRectMake(100.0, 100.0, 57.0, 57.0)];
	imageView.image = [UIImage imageNamed:@"Icon.png"];
	[self.view addSubview:imageView];
	[imageView release];
}

The next logical step in reasoning right after displaying the icon is now to get touch handling somehow. And that’s where you will get stuck because UIImageView is a dead end when it comes to reacting to the user’s finger.

Read more

Double Tapping on Buttons

Grinarn asks:

“I got several buttons set up on my view and when the button gets clicked, a detailed view of that item appears.
What I need is another action method like double click or click and hold, to trigger another action.

How can I do this? I just found the events in the IB which seems only supports single touch events.”

Any view in the SDK can receive and process touch events. This gives you the ability to implement any kind of tap or gesture that you might dream up. But for everyday purposes we will find the methods provided by UIControl sufficient. UIControl inherits from UIView which means that it can do everything that views can do, but it adds the Target-Action mechanism.

For this mechanism you can attach a multitude of various events to each control by simply specifying a target (= any object instance), an action (= any selector of the target) and a constant from the following list. “Selector” is only fancy name for method signature, which consists of the method name and the names of the parameters, all with a colon behind them.

General Touch Actions

  • UIControlEventTouchDown
  • UIControlEventTouchDownRepeat
  • UIControlEventTouchDragInside
  • UIControlEventTouchDragOutside
  • UIControlEventTouchDragEnter
  • UIControlEventTouchDragExit
  • UIControlEventTouchUpInside
  • UIControlEventTouchUpOutside
  • UIControlEventTouchCancel

Specific to Editing Controls

  • UIControlEventValueChanged
  • UIControlEventEditingDidBegin
  • UIControlEventEditingChanged
  • UIControlEventEditingDidEnd
  • UIControlEventEditingDidEndOnExit

Generic Constants matching several Actions

  • UIControlEventAllTouchEvents
  • UIControlEventAllEditingEvents
  • UIControlEventApplicationReserved
  • UIControlEventSystemReserved
  • UIControlEventAllEvents

Now generally if you make a button then you would use the UIControlEventTouchUpInside event even though at first you might instinctively go for UIControlEventTouchDown. TouchUpInside is the standard as it allows the user to reconsider and move outside of the button before lifting his finger thus cancelling his action. Otherwise the button would be like a landmine where there is no way back after touching it.

Now there might be cases where you exactly WANT the action to be fired right when you touch the control. Then TouchDown is the right action. You also see a TouchDownRepeat action available, but this always comes in succession after a TouchDown. Therefore some additional trickery is necessary to be able to distinguish between single and double tapping a button.

Read more