Joris Kluivers

I like to build software.

iTunes Connect Updates

By now all registered iOS developers should have received the following email:

We are excited to announce that all financial reports and future payments will be presented on iTunes Connect in the new Payments and Financial Reports module. This new module replaces the Financial Reports module and features new ways to view your financial information, including:

  • A consolidated single monthly payment for all your proceeds worldwide, reducing bank fees and costs*.

  • Clearer presentation of amounts earned, amounts owed, and a reconciliation between the reported sales and the amounts paid.

  • A Dashboard view of financial information including last payment, amount owed, and latest monthly earnings.

  • Rolling transaction history showing the cumulative balance of amounts earned, taxes, and payments by reporting currency.

  • Graphical views of unit sales and payment trends.

  • Consistent scheduling and timing of reports and payments each month.

  • Improved messaging if your bank returns payments we’ve issued.

*This assumes you have a single bank account setup for all payments worldwide.

In addition, we’ve reduced the thresholds required for you to be paid, increasing the likelihood you’ll receive proceeds each month.

You can find more detail on all the new features and changes in the user guide, which is available within the new Payments and Financial Reports module, or visit the Frequently Asked Questions section of ITunes Connect for more information.

From now on proceeds from all regions will be payed at once in a single transfer. This should lower banking costs and help reach the payment threshold more quickly. The iTunes Connect interface also got a slight update (with quick summaries) improving over the sparse interface from before. However even with the current changes I won’t give up on advanced reporting by AppViz and appfigures.com.

MPMoviePlayerController: Handle With Care

Playing videos in an iPhone application requires the usage of the MPMoviePlayerController. This class does require some special care when using it multiple times in a row. By default playing a second movie during a single application run will result in black screen with only sound being played. Other cases will result in the second movie being played with a flickering screen.

The Symptom

The second time a video plays you either see a black or flickering screen.

The Solution

  • Make sure you carefully release the player each time after use.
  • Calling stop before release to prevent the black screen
  • Set the initialPlaybackTime to -1 before release to prevent flickering

The sample code below applies all the above in a small example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- (void) playMovie {
    MPMoviePlayerController *player = [[MPMoviePlayerController alloc]
        initWithURL:[NSURL URLWithString:@"somefilepath"]];

    if (player) {
        self.moviePlayer = player;
        [player release];

        [[NSNotificationCenter defaultCenter]
            addObserver:self
            selector:@selector(moviePlayerDidFinish:)
            name:MPMoviePlayerPlaybackDidFinishNotification
            object:nil];

        // configure player
        // [..]

        [self.moviePlayer play];
    }
}

- (void)moviePlayerDidFinish:(NSNotification*)notification {
    [[NSNotificationCenter defaultCenter]
        removeObserver:self
        name:MPMoviePlayerPlaybackDidFinishNotification
        object:nil];

    // to prevent a black screen on second play
    [self.moviePlayer stop];
    // to prevent flickering on second play
    self.initialPlaybackTime = -1;

    self.moviePlayer = nil;
}

Perform Image Operations the Thread Safe Way

Search for scaling an image and google will return several answers, of which 90% are somewhat similar. A category on UIImage that returns the modified (scaled) image using UIGraphicsBeginImageContext and family. However this is a very naive implementation that won’t work reliable on threads other than the main one.

Creating Temporary Files in a Safe Location

While working on an application to record sounds I was in need for a temporary file location to write the recorded audio to. I wrote a simple method to return an URL to a non existing file in the temporary directory. A file with a name based on the template recording-XXXXXX.caf will be generated in the directory specified by NSTemporaryDirectory(), where XXXXXX will be replaced to create a unique name.

Subclass UIAlertView to Customize the Look of an Alert

Update: I’ve posted about a better way to create custom alerts.

The iPhone SDK provides the class UIAlertView to display alerts to the user. These alerts are used by Apple for incoming text messages for example. Application developers can use the same notification style to display any custom notification. An alert appears in a special window level on top of all other content. User input to the underlying content is ignored until the alert is dismissed.

In one of my recent projects a view had to be displayed on top of all other content. While some features like the spotlight dim effect and blocking of user input could be reused, in this case the blue UIAlertView style did not fit my needs. Instead of creating my own view from scratch I decided to reuse what UIAlertView had to offer and strip out all unnecessary features.

This page will explain what is needed to create a custom alert like the blood spatter displayed below.

While we could transform the alert into anything we want, I’ve chosen to keep it simple. Our blood spatter alert consists of two main parts: a background image and a text label. As you can see in the comparison above we will ignore any buttons and the default text. A new initialization method will be used to provide our JKCustomAlert with the information needed.

1
- (id) initWithImage:(UIImage *)backgroundImage text:(NSString *)text;

By using our own initializer the default title and message are not set. If you show the alert at this point it will be empty and small but still using the default appearance.

To change the appearance from the default to our own background image drawRect: needs to be overridden. We do not call the super drawRect method to prevent UIAlertView from drawing the default appearance. All we do is draw our background image.

1
2
3
4
5
6
- (void) drawRect:(CGRect)rect {
    // do not call the super drawRect

    CGSize imageSize = self.backgroundImage.size;
    [self.backgroundImage drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
}

The last thing to do is to size our JKCustomAlert to fit our background image. The show method is responsible for resizing and animating the alert. We first call the super method to start the animation and override the view size right after that by setting the bounds to the size of the image.

1
2
3
4
5
6
7
8
- (void) show {
    // call the super show method to initiate the animation
    [super show];

    // resize the alert view to fit the image
    CGSize imageSize = self.backgroundImage.size;
    self.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
}

The text label is added to our subview using addSubview: to be displayed. Positioning of the text label is done in the layoutSubviews selector. This is all normal procedure and shouldn’t be that hard.

Remember that because we do not provide the user with a button the application will have to dismiss the alert manually using the dismissWithClickedButtonIndex:animated: selector otherwise the app will be stuck while displaying our alert.

Of course a custom alert like shown above can also used to create an alternative to the private class UIProgressHUD (used by Apple).

Sample Project

Download CustomAlert.zip (23kb)

Emulating the Google Maps Curl Animation

The curl animation is probably most well known from the iPhone maps application. The effect is used there to partially curl up the map to reveal the settings beneath. While the partial curl effect can’t be recreated entirely using the public iPhone SDK, it is possible to use the animation for other purposes.

How it works

The curl animation provided by the public iPhone SDK can only be used as a transtion. A transition is an animation that’s displayed in between changes to a container UIView. These changes would be adding or removing subviews for example. In case of the maps application the container view initially displays a map view. The changes made involve removing the map and adding the settings view. The curl effect curls the view state before the changes and reveals the same view reflecting the state after the changes. If no changes are made during the curl transition the transition would simply curl the current content and reveal the same content again.

A curl transition can be initiated by wrapping the changes to the container view in an UIView animation context:

1
2
3
4
5
6
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5f];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:containerView cache:NO]
[mapView removeFromSuperview];
[contianerView addSubview:settingsView];
[UIView commitAnimations];

Zip.framework Version 0.1

Today I released my first version of Zip.framework. The framework aims at providing functionality to work with archives directly in Objective-c. A small example:

1
2
3
ZipArchive *zip = [[ZipArchive alloc] initWithFile:@"/path/to/archive.zip"];
FILE *file = [zip entryNamed:@"some/file.txt"];
// do some reading on file
So no need to extract to intermediate files using command line tools or any sign of NSTask anymore. This first version only supports reading, writing to zip files is planned for future versions.

The framework is available as binary or source version. To get the complete Xcode project use svn checkout http://zip-framework.googlecode.com/svn/tags/version-0.1 zip-framework.

Code is released under the (new)BSD license.

Comments

d.largen
I am new to objective c /cocoa development and I an having trouble getting your framework into my project. Could you help me out?
Joris Kluivers
There have been some updates, but mainly to fix some memory bugs. Reading should work correctly now. No support for writing planned anytime soon.

I intend to expand on the reading first, like support for password protected files
jens
Are there any updates to your framework so far, i.e. write support?

Leopard Developer Features

Matt Legend Gemmell posted a fairly long overview of all Leopard developer improvements. Since I didn’t receive my Leopard DVD yet and Apple still needs some time to post new documentation this is what I waited for!

API improvements I find interesting:
  • The Automator framework to run automator workflows from within my own applications
  • Core Data and Sync Services now work together which makes syncing data stored in Core Data much easier
  • Source lists and rule editors


It looks like Apple finally opened up a lot of API’s they were using all along in Tiger which we now can use too. With Leopard it looks like OS X matured a long way for developers with way better API’s. All improvements let developers create applications that look much more like the Apple applications (think iLife and SafarI) while in Tiger we had to create all Apple like features (think HUD windows) ourselves. We are now even officially allowed to use some Images that are used everywhere in applications by Apple (like the gear icon in almost every preference window).