Best ios questions in December 2011

Xcode 4 build schemes screwed up everytime I change branches in Git

14 votes

In Xcode 4, when I'm working when an iOS project, the Scheme drop down menu in Xcode's toolbar normally displays a scheme for iPhone X.X Simulator, iPad X.X Simulator and iOS Device.

When changing branches after having done something that affects the *.xcodeproj/project.pbxproj file, all my schemes disappear from the scheme drop down. If I close the project and reopen it, they come back. This is extremely annoying.

Here's what I'm doing:

  • Create a new iOS related project
  • Stage + Commit everything in the master branch
  • Create & switch to a new branch
  • Add a new class to your project and Save All (CMD+S+option) or just build the project to save everything.
  • Commit that change
  • Switch back to the master branch

At this point, my schemes are screwed and I have to close the project and reopen it to get them back.

Here's what they look like at the beginning: enter image description here

Here's what they look like after following the steps I listed: enter image description here

Does anyone know of a way around this or is this just a bug in Xcode? I submitted a bug report to Apple about it months ago and have not received a response. I've also received no response to a question about it in the developer forums.

Update: If you have a project with multiple targets, only the schemes for the selected target get screwed up after switching branches.

Update: Here's my .gitignore

# the build
build

# temp nibs and swap files
*~.nib
*.swp

# OS X folder attributes
.DS_Store

# user-specific XCode stuff
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
*.xcuserstate
project.xcworkspace/
xcuserdata/

This happens every time for me. It's most certainly a bug. I just click in the build target version box (5.0, etc) and then out again and it resets itself. No need to open and close the project.

Objective-C: format numbers to ordinals: 1, 2, 3, .. to 1st, 2nd, 3rd

13 votes

In Objective C, is there any way to format an integer to ordinals 1 => "1st", 2 => "2nd" etc... that works for any language? So if the user is French he will see "1er", "2ieme" etc..

Thanks a lot!

Edit: This is for an iOs app

Have you taken a look at TTTOrdinalNumberFormatter which is in FormatterKit? It works great, and I'm pretty sure it's exactly what you're looking for.


Here's an example taken from the kit:

TTTOrdinalNumberFormatter *ordinalNumberFormatter = [[TTTOrdinalNumberFormatter alloc] init];
[ordinalNumberFormatter setLocale:[NSLocale currentLocale]];
[ordinalNumberFormatter setGrammaticalGender:TTTOrdinalNumberFormatterMaleGender];
NSNumber *number = [NSNumber numberWithInteger:2];
NSLog(@"%@", [NSString stringWithFormat:NSLocalizedString(@"You came in %@ place!", nil), [ordinalNumberFormatter stringFromNumber:number]]);

Assuming you've provided localized strings for "You came in %@ place!", the output would be:

* English: "You came in 2nd place!"
* French: "Vous êtes venu à la 2eme place!"
* Spanish: "Usted llegó en 2.o lugar!"

Is it right having ViewControllers with a lots of code?

10 votes

I'm still quite new to Cocoa and Objective-C (<1 year). My App now has some 50+ classes, but some of the ViewControllers get quite crowded with code, like 700 lines or more.

My question is: is it fine to have a "large" ViewController or are there patterns for splitting up code into fractions? A lots of the code is implementing delegate methods, thats why I don't have an idea how to move it away.

I know, I can structurize with pragma marks though.

Thanks for any input.

One of the most common causes of large view controllers that I have seen, is lack of separation b/w Model and Controller in MVC architecture. In other words, are you handling your data in your view controllers?

If yes, rip out the model component from VC and put it into separate class. This will also force your thinking towards a better design.

For reference, In View Controller:

  • Handling of all changes in the UIView and the UI elements contained within.
  • All animation, transitions and CALayer operations.

In Model:

  • All processing of data, including sorting, conversion, storage, etc.

App file size differences in Android and iOS

8 votes

Working with both app distributions services (android market and Apple App store) I have discovered a mystery.

The file size of an app is in general larger for an Apple app than for a Android app. I can't seem to find any explanation for the differences, and it seems to be an untouched subject.

I have tried allot of different apps and the difference seems to vary between a couple of MB to 6-8 MB. So the question is, how come the file size is larger for Apple apps? What is the extra MB used for?

Examples:

BBC:

Android: 918K - https://market.android.com/details?id=bbc.mobile.news.ww

Apple: 6.7 MB - http://itunes.apple.com/dk/app/bbc-news/id364147881?mt=8

Due to some spam prevention, I'm unable to link directly to the rest.

British Airways

Android: 1.2 MB

Apple: 7.9 MB

Northern Bank

Android: 2.1 MB

Apple: 6.4 MB

Bank of America

Android: 727K

Apple: 2.1 MB

I could go on... If anyone can provide a statistics of file size for the two app distributions, confirming or disproving my theory. - I would appreciate it allot.

The binary executable in an iOS app is encrypted, and thus compresses very poorly or not at all. The binary executable in an iOS app is compiled with some library code statically linked, which can often make it larger than interpreted Dalvik byte code for similar stuff. iPhone apps tend to contain more high quality graphics content and artwork for multiple screen resolutions including the relatively large iPad display.

Get an array of future NSDates

8 votes

I have a date picker.

After choosing a time from this I would like to get the dates of the next 64 Mondays.

How would I go about writing a method to take a date and return an NSArray of NSDates for the next 64 Mondays from that date

for e.g. I picked time 6:45 pm from date picker then I want to fetch next 64 mondays with there time set to that time.

Example (ARC):

NSDate *pickerDate = [NSDate date];
NSLog(@"pickerDate: %@", pickerDate);

NSDateComponents *dateComponents;
NSCalendar *calendar = [NSCalendar currentCalendar];

dateComponents = [calendar components:NSWeekdayCalendarUnit fromDate:pickerDate];
NSInteger firstMondayOrdinal = 9 - [dateComponents weekday];
dateComponents = [[NSDateComponents alloc] init];
[dateComponents setDay:firstMondayOrdinal];
NSDate *firstMondayDate = [calendar dateByAddingComponents:dateComponents toDate:pickerDate options:0];

dateComponents = [[NSDateComponents alloc] init];
[dateComponents setWeek:1];

for (int i=0; i<64; i++) {
    [dateComponents setWeek:i];
    NSDate *mondayDate = [calendar dateByAddingComponents:dateComponents toDate:firstMondayDate options:0];
    NSLog(@"week#: %i, mondayDate: %@", i, mondayDate);
}

NSLog output:
pickerDate: 2011-12-09 20:38:25 +0000
week#: 0, mondayDate: 2011-12-12 20:38:25 +0000
week#: 1, mondayDate: 2011-12-19 20:38:25 +0000
week#: 2, mondayDate: 2011-12-26 20:38:25 +0000
week#: 3, mondayDate: 2012-01-02 20:38:25 +0000
-the remaining 60 here-

Is it faster to create UITableViewCell programmatically or load one from a nib?

8 votes

Time profiler shows the most time consuming operation in my app is loading UITableViewCells from nib files. The most expensive of which involves loading a UITableViewCell with a 4KB image.

I am loading the UITableViewCell from the nib with the following code:

    [[NSBundle mainBundle] loadNibNamed:@"UITableViewCellPortrait" owner:self options:NULL];
    cell = portraitCell;
    self.portraitCell = nil;

Has anyone compared the difference between creating a view programmatically or loading a UITableViewCell from a nib?

EDIT:
I compared the time profile of repeated runs of loading the UITableViewCell from a nib and creating the view programmatically. My test involved alternating between two UITableViews about 10 times in the span of 3-5 seconds. In each test, loading the UITableViewCell programmatically was substantially faster, between 2x to 6x faster.

Can anyone corroborate these results?

EDIT: I updated the nib loading code to only load the nib file once and use a cached version for subsequent calls.

    if (self.UITableViewPortaitNib == nil) {
        self.UITableViewPortaitNib = [UINib nibWithNibName:@"UITableViewCellPortrait" bundle:[NSBundle mainBundle]];
    }

    self.UITableViewPortaitNib instantiateWithOwner:self options:NULL];
    cell = portraitCell;
    self.portraitCell = nil;

I also used the automation instrument to create more consistent runs and the results still suggest loading UITableViewCells programmatically is faster than loading UITableViewCells for a nib. The average running time for loading UITableViewCells from a nib was around 90ms, while the average running time for creating the UITableViewCell programmatically was 50ms.

Try creating a UINib object once and then sending it instantiateWithOwner:options: each time you need to create a new cell. From the UINib Class Reference:

For example, if your table view uses a nib file to instantiate table view cells, caching the nib in a UINib object can provide a significant performance improvement.

How can I get breakpoints/logs/increased visibility when my Main Thread blocks?

8 votes

In the never-ending quest for UI responsiveness, I would like to gain more insight into cases where the main thread performs blocking operations.

I'm looking for some sort of "debugging mode" or extra code, or hook, or whatever, whereby I can set a breakpoint/log/something that will get hit and allow me to inspect what's going if my main thread "voluntarily" blocks for I/O (or whatever reason, really) other than for going idle at the end of the runloop.

In the past, I've looked at runloop cycle wall-clock duration using a runloop observer, and that's valuable for seeing the problem, but by the time you can check, it's too late to get a good idea for what it was doing, because your code is already done running for that cycle of the runloop.

I realize that there are operations performed by UIKit/AppKit that are main-thread-only that will cause I/O and cause the main thread to block so, to a certain degree, it's hopeless (for instance, accessing the pasteboard appears to be a potentially-blocking, main-thread-only operation) but something would be better than nothing.

Anyone have any good ideas? Seems like something that would be useful. In the ideal case, you'd never want to block the main thread while your app's code is active on the runloop, and something like this would be very helpful in getting as close to that goal as possible.

So I set forth to answer my own question this weekend. For the record, this endeavor turned into something pretty complex, so like Kendall Helmstetter Glen suggested, most folks reading this question should probably just muddle through with Instruments. For the masochists in the crowd, read on!

It was easiest to start by restating the problem. Here's what I came up with:

I want to be alerted to long periods of time spent in syscalls/mach_msg_trap that are not legitimate idle time. "Legitimate idle time" is defined as time spent in mach_msg_trap waiting for the next event from the OS.

Also importantly, I didn't care about user code that takes a long time. That problem is quite easy to diagnose and understand using Instruments' Time Profiler tool. I wanted to know specifically about blocked time. While it's true that you can also diagnose blocked time with Time Profiler, I've found it considerably harder to use for that purpose. Likewise, the System Trace Instrument is also useful for investigations like this, but is extremely fine grained and complex. I wanted something simpler -- more targetted to this specific task.

It seemed evident from the get-go that the tool of choice here would be Dtrace. I started out by using a CFRunLoop observer that fired on kCFRunLoopAfterWaiting and kCFRunLoopBeforeWaiting. A call to my kCFRunLoopBeforeWaiting handler would indicate the beginning of a "legitimate idle time" and the kCFRunLoopAfterWaiting handler would be the signal to me that a legitimate wait had ended. I would use the Dtrace pid provider to trap on calls to those functions as a way to sort legitimate idle from blocking idle.

This approach got me started, but in the end proved to be flawed. The biggest problem is that many AppKit operations that are synchronous, in that they block event processing in the UI, but actually spin the RunLoop lower in the call stack. Those spins of the RunLoop are not "legitimate" idle time (for my purposes), because the user can't interact with the UI during that time. They're valuable, to be sure -- imagine a runloop on a background thread watching a bunch of RunLoop-oriented I/O -- but the UI is still blocked when this happens on the main thread. For example, I put the following code into an IBAction and triggered it from a button:

NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: @"http://www.google.com/"] 
                                                   cachePolicy: NSURLRequestReloadIgnoringCacheData
                                               timeoutInterval: 60.0];    
NSURLResponse* response = nil;
NSError* err = nil;
[NSURLConnection sendSynchronousRequest: req returningResponse: &response error: &err];

That code doesn't prevent the RunLoop from spinning -- AppKit spins it for you inside the sendSynchronousRequest:... call -- but it does prevent the user from interacting with the UI until it returns. This is not "legitimate idle" to my mind, so I needed a way to sort out which idles were which. (The CFRunLoopObserver approach was also flawed in that it requred changes to the code, which my final solution does not.)

I decided that I would model my UI/main thread as a state machine. It was in one of three states at all times: LEGIT_IDLE, RUNNING or BLOCKED, and would transition back and forth between those states as the program executed. I needed to come up with Dtrace probes that would allow me to catch (and therefore measure) those transitions. The final state machine I implemented was quite a bit more complicated than just those three states, but that's the 20,000 ft view.

As described above, sorting out legitimate idle from bad idle was not straightforward, since both cases end up in mach_msg_trap() and __CFRunLoopRun. I couldn't find one simple artifact in the call stack that I could use to reliably tell the difference; It appears that a simple probe on one function is not going to help me. I ended up using the debugger to look at the state of the stack at various instances of legitimate idle vs. bad idle. I determined that during legitimate idle, I'd (seemingly reliably) see a call stack like this:

#0  in mach_msg
#1  in __CFRunLoopServiceMachPort
#2  in __CFRunLoopRun
#3  in CFRunLoopRunSpecific
#4  in RunCurrentEventLoopInMode
#5  in ReceiveNextEventCommon
#6  in BlockUntilNextEventMatchingListInMode
#7  in _DPSNextEvent
#8  in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
#9  in -[NSApplication run]
#10 in NSApplicationMain
#11 in main

So I endeavored to set up a bunch of nested/chained pid probes that would establish when I had arrived at, and subsequently left, this state. Unfortunately, for whatever reason Dtrace's pid provider doesn't seem to be universally able to probe both entry and return on all arbitrary symbols. Specifically, I couldn't get probes on pid000:*:__CFRunLoopServiceMachPort:return or on pid000:*:_DPSNextEvent:return to work. The details aren't important, but by watching various other goings on, and keeping track of certain state, I was able to establish (again, seemingly reliably) when I was entered and left the legit idle state.

Then I had to determine probes for telling the difference between RUNNING and BLOCKED. That was a bit easier. In the end, I chose to consider BSD system calls (using Dtrace's syscall probe) and calls to mach_msg_trap() (using the pid probe) not occurring in periods of legit idle to be BLOCKED. (I did look at Dtrace's mach_trap probe, but it did not seem to do what I wanted, so I fell back to using the pid probe.)

Initially, I did some extra work with the Dtrace sched provider to actually measure real blocked time (i.e. time when my thread had been suspended by the scheduler) but that added considerable complexity, and I ended up thinking to myself, "If I'm in the kernel, what do I care if the thread is actually asleep or not? It's all the same to the user: it's blocked." So the final approach just measures all time in (syscalls || mach_msg_trap()) && !legit_idle and calls that the blocked time.

At this point, catching single kernel calls of long duration (like a call to sleep(5) for instance) is rendered trivial. However, more often UI thread latency comes from many little latencies accumulating over multiple calls into the kernel (think of hundreds of calls to read() or select()), so I thought it would also be desirable to dump SOME call stack when the overall amount of syscall or mach_msg_trap time in a single pass of the event loop exceeded a certain threshold. I ended up setting up various timers and logging accumulated time spent in each state, scoped to various states in the state machine, and dumping alerts when we happened to be transitioning out of the BLOCKED state, and had gone over some threshold. This method will obviously produce data that is subject to misinterpretation, or might be a total red herring (i.e. some random, relatively quick syscall that just happens to push us over the alert threshold), but I feel like it's better than nothing.

In the end, the Dtrace script ends up keeping a state machine in D variables, and uses the described probes to track transitions between the states and gives me the opportunity to do things (like print alerts) when the state machine is transitioning state, based on certain conditions. I played around a bit with a contrived sample app that does a bunch of disk I/O, network I/O, and calls sleep(), and was able to catch all three of those cases, without distractions from data pertaining to legitimate waits. This was exactly what I was looking for.

This solution is obviously quite fragile, and thoroughly awful in almost every regard. :) It may or may not be useful to me, or anyone else, but it was a fun exercise, so I thought I'd share the story, and the resulting Dtrace script. Maybe someone else will find it useful. I also must confess being a relative n00b with respect to writing Dtrace scripts so I'm sure I've done a million things wrong. Enjoy!

It was too big to post in line, so it's kindly being hosted by @Catfish_Man over here: MainThreadBlocking.d

Sort Colors (Objective-C)

8 votes

I'm doing this sort of thing:

- (NSArray*)colors {
    float divisor = .3333;
    NSMutableArray *retVal = [NSMutableArray array];
    for (float one=0; one <= 1.0f; one += divisor) {
        for (float two = 0; two <= 1.0f; two += divisor) {
            for (float three = 0; three <= 1.0f; three += divisor) {
                UIColor *color = [UIColor colorWithRed:one green:two blue:three alpha:.5];
                // also bad
                // UIColor *color = [UIColor colorWithHue:one saturation:two brightness:three alpha:.5];
                [retVal addObject:color];
            }
        }
    }
    return retVal;
}

and, as I suspected, the colors come out horribly out of order (to the eye). The reds are not with the reds, purples not with the purples, etc.

Is there no easy way to create a list of diverse colors, nicely grouped according to human criteria like, "that looks blue?"

This worked quite well. It will NOT help the fact that you have a lot of repeated colors. See below:

NSArray *sorted = [[dict allValues] sortedArrayUsingComparator:^NSComparisonResult(UIColor* obj1, UIColor* obj2) {
    float hue, saturation, brightness, alpha;
    [obj1 getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];
    float hue2, saturation2, brightness2, alpha2;
    [obj2 getHue:&hue2 saturation:&saturation2 brightness:&brightness2 alpha:&alpha2];
    if (hue < hue2)
        return NSOrderedAscending;
    else if (hue > hue2)
        return NSOrderedDescending;

    if (saturation < saturation2)
        return NSOrderedAscending;
    else if (saturation > saturation2)
        return NSOrderedDescending;

    if (brightness < brightness2)
        return NSOrderedAscending;
    else if (brightness > brightness2)
        return NSOrderedDescending;

    return NSOrderedSame;
}];

You can access the components (HSBA) like this in iOS 4.x:

    CGFloat *components = (CGFloat *)CGColorGetComponents([color CGColor]);
    float hue = components[0];
    float saturation = components[1]; // etc. etc.

To avoid repeating colors: you can put the elements in an NSMutableDictionary, keyed on something like their hue-saturation-brightness (each rounded to the nearest .10)... then you get the array from THAT, and then sort.

iOS Stream Audio from one iOS Device to Another

7 votes

I get a song from the device iTunes library and shove it into an AVAsset:

- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    NSArray *arr = mediaItemCollection.items;

    MPMediaItem *song = [arr objectAtIndex:0];

    NSData *songData = [NSData dataWithContentsOfURL:[song valueForProperty:MPMediaItemPropertyAssetURL]];
}

Then I have this Game Center method for receiving data:

- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID

I'm having a LOT of trouble figuring out how to send this AVAsset via GameCenter and then have it play on the receiving device.

I've read through: http://developer.apple.com/library/ios/#documentation/MusicAudio/Reference/AudioStreamReference/Reference/reference.html#//apple_ref/doc/uid/TP40006162

http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html#//apple_ref/doc/uid/TP40009767-CH2-SW5

http://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html

http://developer.apple.com/library/mac/#documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/Introduction/Introduction.html

I am just lost. Information overload.

I've implemented Cocoa With Love's Audio Stream code, but I can't figure out how to take the NSData I receive through GameCenter and shove it into his code. http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html

Can someone please help me figure this out? So again the part I need help with is simply breaking up song data into packets (or however it works), then iterating through those packets and sending it through gamekit, then parsing that data AS it comes in on the receiving device as PLAY it AS it comes in.

The API you need to look at is "Audio Queue Services".

Right, here goes for a basic overview of what you need to do.

When you playback audio, you set up a queue or a service. That queue will ask for some audio data. Then, when it has played all that back, it will ask for some more. This goes on until you either stop the queue, or there's no more data to playback.

The two main lower level APIs in iOS are Audio Unit and Audio Queue. By lower level, I mean an API that is a bit more nitty gritty than saying "just play back this mp3" or whatever.

My experience has been that Audio Unit is lower latency, but that Audio Queue is more suited to streaming audio. So, I think for you the latter is a better option.

A key part of what you need to do is buffering. That means loading data sufficiently so that there are no gaps in your playback. You might want to handle this by initially loading a larger amount of data. Then you are playing ahead. You'll have a sufficiently large buffer in memory whilst simultaneously receiving more data on a background thread.

The sample project I would recommend studying closely is SpeakHere. In particular look at the classes SpeakHereController.mm and AQPlayer.mm.

The controller handles things like starting and stopping AQPlayer. AQPlayer represents an AudioQueue. Look closely at AQPlayer::AQBufferCallback. That's the callback method that is invoked when the queue wants more data.

You'll need to make sure that the set up of the queue data, and the format of the data you receive matches exactly. Checkout things like number of channels (mono or stereo?), number of frames, integers or floats, and sample rate. If anything doesn't match up, you'll either get EXC_BAD_ACCESS errors as you work your way through the respective buffers, or you'll get white noise, or - in the case of wrong sample rates - audio that sounds slowed down or sped up.

Note that SpeakHere runs two audio queues; one for recording, and one for playback. All audio stuff works using buffers of data. So you're always passing round pointers to the buffers. So, for example during playback you will have say a memory buffer that has 20 seconds of audio. Perhaps every second your callback will be invoked by the queue, essentially saying "give me another second's worth of data please". You could think of it as a playback head that moves through your data requesting more information.

Let's look at this in a bit more detail. Differently to SpeakHere, you're going to be working with in memory buffers rather than writing out the audio to a temporary file.

Note that if you're dealing with large amounts of data, on an iOS device, you'll have no choice but to hold the bulk of that on disk. Especially if the user can replay the audio, rewind it, etc., you'll need to hold it all somewhere!

Anyway, assuming that AQPlayer will be reading from memory, we'll need to alter it as follows.

First, somewhere to hold the data, in AQPlayer.h:

void SetAudioBuffer(float *inAudioBuffer) { mMyAudioBuffer = inAudioBuffer; }

You already have that data in an NSData object, so you can just pass in the pointer returned from a call to [myData bytes].

What provides that data to the audio queue? That's the call back method set up in AQPlayer:

void AQPlayer::AQBufferCallback(void *                  inUserData,
                            AudioQueueRef           inAQ,
                            AudioQueueBufferRef     inCompleteAQBuffer) 

The method that we'll use to add part of our data to the audio queue is AudioQueueEnqueueBuffer:

AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL);

inAQ is the reference to the queue as received by our callback. inCompleteAQBuffer is the pointer to an audio queue buffer.

So how do you get your data - that is the pointer returned by calling the bytes method on your NSData object - into the audio queue buffer inCompleteAQBuffer?

Using a memcpy:

memcpy(inCompleteAQBuffer->mAudioData, THIS->mMyAudioBuffer + (THIS->mMyPlayBufferPosition / sizeof(float)), numBytesToCopy);

You'll also need to set the buffer size:

        inCompleteAQBuffer->mAudioDataByteSize =  numBytesToCopy;   

numBytesToCopy is always going to be the same, unless you're just about to run out of data. For example if your buffer is 2 seconds worth of audio data and you have 9 seconds to playback, then for the first four callbacks you will pass 2 second's worth. For the final callback you will only have 1 second's worth of data left. numBytesToCopy must reflect that.

    // Calculate how many bytes are remaining? It could be less than a normal buffer
    // size. For example, if the buffer size is 0.5 seconds and recording stopped
    // halfway through that. In which case, we copy across only the recorded bytes
    // and we don't enqueue any more buffers.
    SInt64 numRemainingBytes = THIS->mPlayBufferEndPosition - THIS->mPlayBufferPosition;

    SInt64 numBytesToCopy =  numRemainingBytes < THIS->mBufferByteSize ? numRemainingBytes : THIS->mBufferByteSize;

Finally, we advance the playback head. In our callback, we've given the queue some data to play. What happens next time we get the callback? We don't want to give the same data again. Not unless you're doing some funky dj loop stuff!

So we advance the head, which is basically just a pointer to our audio buffer. The pointer moves through the buffer like the needle on the record:

    SELF->mPlayBufferPosition += numBytesToCopy;

That's it! There's some other logic but you can get that from studying the full callback method in SpeakHere.

A couple of points I must emphasis. First, don't just copy and paste my code above. Absolutely make sure you understand what you are doing. Undoubtably you'll hit problems and you'll need to understand what's happening.

Secondly, make sure the audio formats are the same, and even better that you understand the audio format. This is covered in the Audio Queue Services Programming Guide in Recording Audio. Look at Listing 2-8 Specifying an audio queue’s audio data format.

It's crucial to understand that you have the most primitive unit of data, either an integer or a float. Mono or stereo you have one or two channels in a frame. That defines how many integers or floats are in that frame. Then you have frames per packet (probably 1). Your sample rate determines how many of those packets you have per second.

It's all covered in the docs. Just make sure everything matches up or you will have some pretty strange sounds!

Good luck!

Profiling memory leaks with Instruments- huge difference between iPhone 4 and iOS 5 Simulator

7 votes

When profiling my app with Instruments (looking for memory leaks), I get extremely different results with the iOS 5 iPhone Simulator from those I get with my iPhone 4 running iOS 5. The first picture shows the results from the profiling with the real device, and the second is with the simulator:

Real device:

Real device


iOS 5 Simulator:

Simulator

This profile is taken up to the same point in the app in both cases: completion of viewDidLoad in the rootViewController's view lifecycle. I have waited in both of them for the total allocated memory to stable out. As you can see in the device graph, there are some extreme fluctuations occurring at about 00:10, which aren't present in the Simulator. On the real device, total allocated memory, at around 00:08, jumps from 1MB to 3.5 MB then back down to 1.5 MB and finally jumps to 4.74, where it stabilizes. The allocated memory for the Simulator is much more linear, with it climbing steady and quickly to around 2.35 MB where it stabilizes.

Another thing to note is the presence of 2.25 MB of allocated memory present on the device but not the Simulator from malloc and 700+ KB from CFNumber. As I am relatively new to using Instruments and profiling, I'm not exactly sure if this is normal. A quick Google search turned up nothing definitive. That 2.25 MB and 700 KB more than make up for the difference in memory allocation. To balance things, there are more entries for malloc with different amounts of memory present in the Simulator test not present in the device test.

Also, I found that when a second UIViewController is pushed onto the UINavigationController stack, allocated memory jumps to about 8.5-9 MB on the real device, but only about 4.5 to maybe 4.5 megabytes tops on the Simulator.

I know it is to be expected that the device would perform much differently from the Simulator, but should memory allocation not be pretty similar because the same code is being run on both devices? I would understand if this is a performance profiling, but for memory allocation, it seems that the numbers should be pretty similar. Can anyone shed some light as to whether this is normal or not?

This behavior is to be expected. Technically, when you run profiling with the simulator you are measuring stats based on your desktop's hardware. Even if you're just profiling allocations you can't expect them to work similarly because a lot of software optimizations/algorithms/etc are based on the hardware it's running on.

Unfortunately, Apple doesn't have an iOS emulator. You're better of profiling with the device though, as emulators tend to still be unreliable and slow (e.g. Android emulator).

iOS Localizable.strings file for XIB files?

6 votes

I'm translating an iOS project into Portuguese and I've created a pt.lproj/Localizable.strings file, and I've added NSLocalizedString() into the source code. It all works! With one slight problem - the strings within XIB files don't get translated... I know this is by design though.

I've seen that the ibtool command can be used to rip strings from an XIB file called x and put it into a file called x.strings... but my question is, is there a way to pull the strings from ALL the xib files and put them all into one .strings file (e.g. Localizable.strings? or even another one called XIBs.strings would be fine?)

Thanks in advance guys :D!

You have two options how to translate xib files. One is you connect the UI elements to outlets and set your strings in your viewDidLoad method using the NSLocalizedString macros.

The second option is to provide a separate xib for each language your app supports. You don't have to create them manually, you can use the ibtool command (i assume your source language is English and target is Portugese):

ibtool --strings-file pt.lproj/Example.strings en.lproj/Example.xib –write pt.lproj/Example.xib

To collect strings found in your project you can use genstrings command - however i recommend using this python script to collect all your strings - it can nicely handle the situation when you need to add/remove strings to your app without having to translate and/or manually merge all previous strings

Edit

Oh and i found the article that i learned this trick from

Using Grand Central Dispatch outside of an application or runloop

6 votes

In the GCD documentation it's quite clear that to submit work to the main queue, you need to either be working within an NSApplication (or UIApplication) or call dispatch_main() to act as a run loop of sorts. However, do I need to do anything to setup the global concurrent queue?

Basically what I am asking is: If I write a plain simple C program, do I need to perform any special setup before I go dispatch_get_global_queue() and start giving it work?

No, you don't need any additional setup. But you need to call dispatch_main() to start the GCD dispatcher.
As dispatch_main() never returns, this will also prevent your main function from reaching it's return.

Example for a minimal C program that uses GCD & a global queue (based on http://wiki.freebsd.org/GCD):

#include <dispatch/dispatch.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, 5LL * NSEC_PER_SEC);
    dispatch_after(dispatchTime, globalQueue, ^{
        printf("Dispatched on global queue\n");
        exit(0);
    });
    dispatch_main();
    return (0);
}

To compile this, use:

clang -Wall -Werror -fblocks -L/usr/local/lib -I/usr/local/include -o test test.c

UIView atop the Keyboard similar to iMessage App

6 votes

currently I'm attempting to basically implement and exact copy of Apples iMessage App.

That means I need a UITextView that is docked at the bottom of the screen, and moves up when it becomes firstResponder. - That's pretty easy actually. There's a bazillion ways to do that and two of the most common are of course animating the view upwards or downwards if a notification was received. The other is to do it via the inputAccessoryView. Sadly some of the features the one has, the other doesn't. And they seem to be mutually exclusive.

The big problem is rotation.

I've digged through roughly at least seven different github projects, all of them re-implementing the same functionality/behavior, that I'm trying to achieve, but literally all of them failing miserably.

HPGrowingTextView for instance, which the official Facebook/FacebookMessenger/(and possibly WhatsApp) Apps makes use of, is one big piece of junk-code. Take your iDevice, open the Facebook App, go the the Chat, pop the keyboard and rotate your device. If you pay attention you'll notice the input-bar jumping slightly and leaving some blank space between the keyboard's frame and its own. Then take a look at Apples implementation in iMessage when the keyboard is shown. It's perfect.

Other than that the contentOffset and EdgeInset-hacking that the HPGrowingTextView library makes use of gives me nightmares.

So I wanted to do it myself and start from scratch.

Right now I've got a very slick, elegant and hack-less implementation of a growing UITextView, but one part is missing.

Elegant rotation.

When I simply adjust the frames to their respective new positions in the willRotateToInterfaceOrientation:duration: method, everything ends up working perfectly BUT I have the same problem that HPGrowingTextView(see Facebook App) has. A litte bit of space between the inputview and the keyboard while the rotation takes place.

I found out that when rotating the device to landscape, the portrait keyboard which is currently shown does not "morph" but rather disappears (sends the 'willHide' notification) and a landscape version reappears (sending the 'willShow' notification). The transition is a very subtle fade and possibly some resizing.

I re-implemented my project using the inputAccessoryView to see what happens then and I was pleasantly surprised. The inputAccessoryView rotates in perfect sync with the keyboard. There's no space/gap between the two.

Sadly I have yet to come up with an idea how to have the inputAccessoryView dock to the bottom of the screen and NOT disappear/move out of it alongside the keyboard...

What I don't want are hack-y solutions like,..."lowering the frame slightly in the toInterfaceOrientation's CoordinateSystem and then moving it back up when the didRotateFrom... was called."

I know of one other app that has managed to implement such behavior and it's the "Kik Messenger".

Does anyone have an idea, advice or a link that I haven't seen yet covering that topic?

Thanks a bunch!

Note: Once this problem is solved I will open source the project for everyone to profit because almost every implementation I was able to find over the course of the past few days, is a mess.

I have been successful at solving the problem in quite an elegant manner (I think,...).

The code will be released on Github next week and linked to in this answer.

--

How it's done: I made the rotation work by choosing the inputAccessoryView-way of doing it.

Nomenclature:

  1. 'MessageInputView' is a UIView containing my 'GrowingUITextView' (it also contains a "Send" Button and the background image).
  2. 'ChatView' is the view that belongs to the ChatViewController that displays all the Chatbubbles and has my 'MessageInputView' docked at the bottom.
  3. 'keyboardAccessoryView' is an empty UIView sized: CGRect(0,0,0,0).

I needed to figure out how to have the MessageInputView stick around on the screen when the keyboard was dismissed. That was the tricky part. I did this by creating another view (keyboardAccessoryView) and had my GrowingUITextView use it as its inputAccessoryView. I retained the keyboardAccessoryView because I'd need the reference to it later on.

Then I remembered some of the stuff I did in my other attempt (animating the MessageInputView's frames around the screen whenever a keyboard notification arrived).

I added my MessageInputView as a subview to my ChatView (at the very bottom). Whenever it is activated and the willShow: methods is called by a keyboard notification, I manually animate the MessageInputView's frame to it's designated position up top. When the animation finishes and the completion block executes I remove the subview from the ChatView and add it to the keyboardAccessoryView. This causes another notification to be fired off because the keyboard is re-loaded EVERY time the inputAccessoryView's frame/bounds are changed!. You need to be aware of that and handle it appropriately!

When the keyboard is about to dismissed, I convert my MessageInputView's frame to my ChatView's coordinate system and add it as a subview. Thus it is removed from my keyboardAccessoryView. I then resize the keyboardAccessoryView's frame back to CGRect(0,0,0,0) because otherwise the UIViewAnimationDuration will not match! Then I allow the keyboard to be dismissed and I have my MessageInputView follow it from above and eventually dock at the bottom of the screen.

This is quite a lot of work for very little gain though.

--

Take care.

PS: If someone figures out an easier way to do it (perfectly) let me know.

How can I distribute iOS apps that have been rejected from the App Store?

5 votes

I have made multiple simple but fun apps for iPhone in the past few months and have had them rejected by Apple during the approval process.

I have put many weeks or months of effort in some cases. I just hate to have these apps go to waste without anyone downloading them.

Since those apps of mine are never going to see the light of the day on the App Store, is there a way I can let family and friends download those apps if I host those binaries on my website? Can anyone tell me the process or walk through instructions?

Are they simple enough that if I post them on Facebook most average users are going to get it? Is there already a website out there that lets users like me (with unapproved apps) to host those files for everyone in the world to download them?

Have a look to testflight.

You just need an email that can be accessed on the iPhone and add the specific user to test flight, once he is register you can get the iPhone id and add it to the provisioning profile.

When you create the build and upload it , the users are notified by email and the app is installed remotely by a few clicks.