305Converting float to string %4.2f

printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416); floats: 3.14 +3e+000 3.141600E+000

303singleTap: and private API

Very funny and strange case of rejection. I made a method called 'singleTap', that is - as the name suggests - receiving events after a single tap occurs. During the development process the function was not used and commented out, but an oversight let to the notification being left it. And then the message from Apple:

"3.3.1 Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs." The following non-public API is included in your application: singleTap:

Hmm. Clearly I did not use a private API, apparently I just happened to call a function the same name as a private API function... Wondering if there is a list of reserved function names, which is triggered a rejection?

Solution? I commented out the superflicial notification AND renamed the function to 'oneTap'. Just in case.

I am starting to believe the stories about the Apple store.

289Simulating Keyboard & Mouse Events. And Key-Modifier Events

Creating and Posting a Keyboard Event:

CGEventRef sDown, sUp;
sDown = CGEventCreateKeyboardEvent (
            NULL,
            (CGKeyCode)1,
            true
);
CGEventSetFlags(sDown, kCGEventFlagMaskShift);  

// setting flags with special function. 
// Setting it via CGCreateKeyboardEvent
// would work only for the first time it's run

CGEventPost(kCGHIDEventTap, sDown);

sUp = CGEventCreateKeyboardEvent (
            NULL,
            (CGKeyCode)1,
            false
);
CGEventPost(kCGHIDEventTap, sUp);

CFRelease(sDown);
CFRelease(sUp);

That leaves the door open for applying the same to mouse events:

CGEventRef mouseEvent;
mouseEvent = CGEventCreateMouseEvent (
            NULL,
            kCGEventMouseMoved,
            CGPointMake(100, 100),
            kCGMouseButtonLeft
);
CGEventPost(kCGHIDEventTap, mouseEvent );

Magical. Isn't it.

Of course, in pre-10.6 days it would have looked like that:

CGPostKeyboardEvent (0,5,true);
CGPostKeyboardEvent (0,5,false);

287[^//]NSLog

Looking Projectwide for NSLog's:

Shift-Apple-F: [^//]NSLog

All the NSLogs, which don't have // infront of them.

Update: This might be a more elegant way to get rid of the NSLogs. 447

280UIKit: Saving Images to Photo Album

Saving Images to the Shared User Photo Album using the UIKIT UIImageWriteToSavedPhotosAlbum() function:

void UIImageWriteToSavedPhotosAlbum (
    UIImage *image,
    id completionTarget,
    SEL completionSelector,
    void *contextInfo);

Usage:

UIImageWriteToSavedPhotosAlbum(
    [theImage retain], 
    self, 
    @selector(image:didFinishSavingWithError:contextInfo:), 
    nil);

// callback when saving is done...
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    NSLog(@"finished saving");
    [image retain];
}

No 100% sure if the image has to be retained. It also seems to work without retaining and releasing it...

It takes about 3 seconds to save a 480x320 image on an iPhone 3GS. Feels a bit long...

275UIWebView – checking when user clicks a link

- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType {

// intercepting web click in the webView
NSLog(@"%@,  %i", [request.URL absoluteString], navigationType);

}

Don't forget to set <UIWebViewDelegate>

269Caching on Objective-C with NSURLCache

A quick reminder on how caching works in Objective-C.

Initially there is one cache, NSURLCache administrates it.

Get the object:

NSURLCache *cache = [NSURLCache sharedURLCache]

[cache memoryCapacity];
[cache setMemoryCapacity: 1024*1024*1]; // in byte
[cache currentMemoryUsage];

Don't worry about the disk aka the flash memory in iPhone, it's not accessible.

A bit of strange behaviour, either a bug in the software or in my brain: When changing ViewControllers the memoryCapacity seems to reset itself to 0, although previous caches remain intact. Re-setting the memoryCapacity back to the original level seems to solve this. (The cache is not overwritten.)

Using the Cache The whole point of using the cache is to not download online material over again. The following steps make for a happy cache:

//URLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];

The delegate response would allow you to alter the about-to-be-cached-data, leaving it in is not necessary:

- (NSCachedURLResponse *)connection:(NSURLConnection *)c
willCacheResponse:(NSCachedURLResponse *)response {
    NSLog(@"willCacheResponse");
    return response;
}

All in all, not that much to take it. Finding out, that the memoryCapacity gets reset was the most time-consuming bit. For another example, of how to roll your own cache, look at URLCache example.

265Like explode(), only componentsSeparatedByString:

PHP explode(", " , "One, Two, Three");

Objective-C NSArray *listItems = [@"One, Two, Three" componentsSeparatedByString:@", "];

259The mystery of self.* – resolved?

self If you want to access a property of self using accessor methods, you must explicitly call out self as illustrated in this example:
self.age = 10; 
If you do not use self., you access the instance variable directly. In the following example, the set accessor method for the age property is not invoked:
age = 10;

p57, The Objective-C 2.0 Programming Language Language (v2008-06-09) p22, The Objective-C 2.0 Programming Language Language (v2009-10-19)

So basically it's a shortcut to:

int* a = [self age];
[self setAge:12];

(providing there is a setter/getter for age.)

254NSNotification Trinity

1

 [[NSNotificationCenter defaultCenter] 
addObserver:self selector:@selector(selectorName:) name:@"methodName" object:nil];

2

[[NSNotificationCenter defaultCenter] 
postNotificationName:@"selectorName" object:self userInfo:nil];

3

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}