1

Objective-C: UIButtons and Event Propagation / for(;;){

UIBUttons that won’t stop event propagation

Today I needed to add a few UIButtons to an interface I had created as a Storyboard. However I am heavily using touchesBegan, touchesMoved, and touchesEnded. UIButtons swallow touch events like that and won’t allow them pass through into my touches<Condition> code. That was a problem for me. You could subclass a UIButton and use it, but I am rather fond of placing some elements myself into a Storyboard. I found a nice solution online. Before the implementation in your view controller, add this code (I think I found it on StackOverflow somewhere):

#pragma mark PassTouch

@interface UIButton (PassTouch)
@end

@implementation UIButton (PassTouch)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    [self.nextResponder touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    [self.nextResponder touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    //[self.nextResponder touchesEnded:touches withEvent:event];
}
@end
...

This was a lot easier than subclassing a button, etc. The only thing is that all of your UIButtons are now going to pass events along. I commented that one line out in touchesEnded for the button since that bit was interfering with some of my code. Handy stuff that.

A for loop that won’t quit

I wanted to use a while loop for something (just a random number that wouldn’t be a repeat of the previous number). I stumbled upon some documentation that showed something I haven’t seen before. This is a style thing really as there are other ways to achieve the same and commonly needed results.

    int rndValue;
    for(;;){
        rndValue = 0 + arc4random() % ([songsArray count] - 0);
        if(rndValue != currentRandomTrack){
            currentRandomTrack = rndValue;
            break;
        }
    }

Check out that for loop. Until that condition is met to break, that for loop will run until someone kills the battery. Just another way to do it, but I hadn’t seen it before so I thought I’d pass it along. Pretty cool looking with the Snidley Whiplash eyes in there.

That’s all – have a great weekend.

Popularity: 1%

0

WWDC 12

Happy.
I’m really excited to be attending WWDC this year. The last time I was in San Francisco for anything was for FlashForward I think. I’ve been to a few MacWorld conferences and have enjoyed a SteveNote from just behind the press pool (close).

I feel lucky to have been able to get a ticket since they sold out so quickly. I’m lucky to be on the East coast and also lucky someone at work was talking with someone early in the morning who noticed tickets went on sale before I got my SMS message about it. I definitely would have missed out if not for that.

Pilgrimage.
Jeff LaMarche used to help run a bus pilgrimage to Apple on the Sunday before things kicked off, but it looks like this isn’t happening this year. If anyone has heard of something else please leave a comment. I was thinking of renting a car but it’s a pretty long drive (2 hours?) to arrive someplace where I’d know not where to go or where to park, etc. It would be tough to do during the week and miss out on a lot. Perhaps I’ll just have to pass on it.

Anyway, my Twitter account: @eric_dolecki

Popularity: 1%

2

Not adding fuel to the Flash fire

Image of tree branches

I’m not going to add any flames or speculation for what the recent choices Adobe has made in regards to mobile Flash, Flex, AIR, or JavaScript/HTML5. There is already plenty of that out there and it’s hard to know what is FUD, what the Adobe FAQ answers truly mean moving forward, or if some people just like taking shots at Flash because they think it sucks. Go read that at your leisure and make of it what you will.

If you’re at all concerned with Flash falling by the wayside, you have a few options that I can think of

 

  • Hope that nothing changes for you and you can keep putting Flash-assisted cash in your bank account. Assume that nothing is changing or that it won’t affect you.
  • Start to learn some JavaScript techniques and general HTML5 approaches to make up for any Flash application drop off. Start branching your toolbox just a little bit in case a client starts harping about HTML5 because it’s in the news more lately.
  • Start jamming on AIR for Android and iOS so you can offer something up to those platforms in a round-about way without committing to hunkering down and learning totally new stuff.
  • Start jamming on Android Java and iOS Objective-C so you can offer up some native goodness to those platforms. Leave the optimization headaches and late-adopter OS-version capabilities to other developers.

I am always in favor of rounding out your capabilities as broadly as you can. Push yourself a bit more. Flash has been a mainstay technology for a great many of us for quite a long time. Some of us got our start and remain profitable (employable) being one-trick Flash ponies. Some of us have branched out and used Flash as a springboard to other languages and platforms.

Things change in this technology field, and you have to be open to that change if you want to stay on top of the game. And remain in high demand. It’s my personal belief that if you haven’t started to branch out yet because you’ve got AS3 nailed and you love it, I’d suggest you start branching now. It will only help you as a developer anyway… when you pick up bits of other languages you’ll improve all around in how you approach coding projects in any language. You’ll start to think more broadly about what you’re doing.

I’ve been tooling with Android and iOS (both natively) for some time now and I can almost pump out apps in the same amount of time that they took in AS3/Flex. So now I can offer native Android, native iOS, Mac OS X, Flex, AS3, and AIR as options. I haven’t done the AIR for mobile yet because I don’t like having some magic sauce do magic things underneath me. I do value the superior portability of platform it can bring though.

Once you branch you’ll see how similar many languages are to one another. Same ideas just different syntax and approaches – so having AS3 under your belt will get you a jump start on other languages.

Branch out… it’s a ton of fun!

Popularity: 2%

0

iOS: collect and parse local project files

Do you have a bunch of HTML files that are local to your iOS project? Would you like to run through them and parse out keywords for your own search method? While I won’t go into the indexing and searching (separate topic), digging through your own stuff dynamically is actually pretty easy when you put a few pieces together. I give you a method which finds all the HTML pages in your application.

- (void)indexAllHTML
{
    NSArray *pages = [[NSBundle mainBundle] pathsForResourcesOfType:@".html" inDirectory:nil];
    for(int i=0; i<[pages count]; i++){
        NSString *path = [pages objectAtIndex:i];
        NSString *pageData = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
        NSArray *foo = [path componentsSeparatedByString:@"/"];
        NSString *shortPath = [foo lastObject];
        //Perform your indexing magic here
    }
}

Popularity: 1%

1

Check out this Lion System Preference window

Pretty odd isn’t it? Had to quit it and relaunch it.

Popularity: 2%

2

Devastated

Today I feel absolutely sick, like countless others. Today passed one of my absolute heroes. Steve Jobs was the sole reason I got into tech to begin with… my father having lost his new Apple ][+ to me and long nights of coding on my own.

I can’t even properly put into words what this man did for me and for others. I was shocked that the end came so quickly.

After many tears all I can say is thank you. Thank you. Thank you.

Update

I only hope that Apple continues to innovate and produce amazing products moving forward. I think a large part of the allure of working for Apple is centered around the fact that they had a task master in charge of decision making and projects. He was critical of people who didn’t perform well. He pushed people beyond their normal limits to develop great products. They loved and hated him at the same time. They loved for what he made them realize. They hated him during production and development because he didn’t take crap as a solution. He took risks, abandoning technologies in lieu of better solutions.

Apple doesn’t (didn’t) market test like other companies do – he had a knack of knowing himself what he wanted and that almost always turned out for the best. If it past the Steve Jobs smell test, it was good enough to pursue. I don’t think you can replace his mind or his drive currently within the walls of Apple. I hope that his spirit lives on in a strong way at the company I love so much.

Genius only comes around a few times every few centuries. He took a company on the edge of disaster and turned it into the best company in the world. How many companies has he made possible?

I never met the man, but was fortunate enough to have attended a keynote in the front row when the iPod was first released. He made my own career possible. He was an amazing man. Beyond technology. Here’s to the crazy ones.

My son and daughter use our iPhones and iPad regularly – they got it from the beginning and love those devices. They learn, play games, interact with information, etc. Steve made that possible.

I’ll be okay at some point. I’ll be able to breathe. Right now I feel a little lost. I grew up with this man and his company. He impacted me to such a degree that I am taking this emotionally very hard. I feel for his family and for all those who knew him. The world just grew a little dimmer and I don’t know if that point of light could ever be replaced. I feel a bit lost.

Popularity: 2%

2

Poll: Mac OS X Lion

It hasn’t been long, but I wanted to poll some visitors to see where they have landed mentally in regards to this Mac OS X Lion operating system.

This poll expires at the end of the month since it’s timely.

Popularity: 2%

25

Keyboard shortcut to Launchpad on OS X Lion

By default when running OS X Lion there isn’t a keyboard shortcut to Launchpad. You could use a trackpad or a magic mouse, but what if you don’t want to buy one? Keyboard shortcut.

Launchpad is something I could use to avoid going to the dock for anything (Alfred has been updated and works with Lion). So if I don’t want to depend on Alfred (which totally rocks), Launchpad is great for finding an application when I forget it’s name or isn’t properly indexed by Alfred yet.

Go to System Preferences > Keyboard > Keyboard Shortcuts. Click on Launchpad & Dock. You’ll see that Show Launchpad is selected but there is no shortcut associated with it. In a fit of usability awkwardness (very un-Apple), it’s not clear how to set the shortcut. Double-click to the right of the row below the dock hiding shortcut, and an input field will appear. Perform your shortcut input there (I chose to use CMD-OPT-L). It’s set and will trigger now.

I’m not sure what genius thought that double clicking into a white area would be discoverable, but there you go. Launchpad on demand.

Popularity: 100%

0

Window shadowing has changed in Lion

Screen Shot
And I think I like it. Much larger and bolder effect.

Popularity: 2%

0

Optimize a search in an NSMutableDictionary

A data blender

This post will likely be updated a few times as I learn on the fly and relay experience gained information. If anyone is reading this.

I have a situation where I need to search through an NSMutableDictionary in the hopes of getting a fuzzy match to happen. The NSMutableDictionary in question is populated by items on an iOS device’s onboard music library. Currently I am testing with 1,777 items. That doesn’t seem like a huge amount, but running a traditional for…in loop takes about 6 seconds to run through the whole thing.

Here is my original loop code without surrounding method context (it’s simply lifted out to make things easier):

for (id key in songsDictionary) {
                NSString *thisSong = key;
                int suppliedCount = [stringValue length];
                int keyCount = [thisSong length];
                if(suppliedCount > keyCount){
                    match= [StringDistance stringDistance:thisSong :stringValue];
                } else {
                    match= [StringDistance stringDistance:stringValue :thisSong];
                }
                //Get the very best match there is to be found for song.
                if(match < currentFoundValue){
                    currentFoundValue = match;
                    test = [songsDictionary objectForKey:thisSong];
                    dis = [NSArray arrayWithObject:test];
                    collection = [[MPMediaItemCollection alloc] initWithItems:dis];
                }
            }

This takes about 6 seconds to process and get through. Now, someone suggested I try something else. So I looked at enumerateKeysAndObjectsWithOptions. I had to change my code a little bit (outside the loop) so they were block compliant. I never heard of that before, but basically you just prefix your vars with __block. That’s two underscores and lowercase block. So my MPMediaItem *test became __block MPMediaItem *test. Simple enough when you know about it, I had to Google after the compiler yelled at me, then I figured it out. Anyway, I tried this method and it’s shaved off MAYBE a second from the total time. Not a great optimization, but it’s something.

int suppliedCount = [stringValue length];
            [songsDictionary enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id key, id obj, BOOL *stop) {
                NSString *thisSong = key;
                int keyCount = [thisSong length];
                if(suppliedCount > keyCount){
                    match = [StringDistance stringDistance:thisSong :stringValue];
                } else {
                    match = [StringDistance stringDistance:stringValue :thisSong];
                }
                if(match < currentFoundValue)
                {
                    currentFoundValue = match;
                    test = [songsDictionary objectForKey:thisSong];
                    dis = [NSArray arrayWithObject:test];
                    collection = [[MPMediaItemCollection alloc] initWithItems:dis];
                }
            }];

Now, someone else told me to try something else too. This part I have not done yet. I will quote them but won’t give named credit as I didn’t ask them permission to use their name.

Simple example. Init a NSMutableDictionary. For each string, compute a hash key as the sum of all chars composing it (in a short or int), divide it by 8 (that’s quick). This way, all the words that differ by just one char being exchanged (metathesis), or look more or less the same, will get an identical hash code.

In your mutable dictionary, use the hash key as the key, the object being an NSMutableArray where you put all the strings that share the same hash key. Then use the contents of this NSMutableArray as proposals for your user. That should be really fast. Refine the process if you need more grain.

You can try to use that (enumerateKeysAndObjectsWithOptions), but, basically, it is the same problem: you enumerate all entries in your dictionary and compute your string distance for each, which is cumbersome. The algorithm I propose you is way faster, because you don’t have to recompute this distance each time you search. But, once again, the crude way to compute a hash code might not suit your needs.

So now I am looking into trying this technique out and see what it produces. It’s going to be a bit of extra code to slap in there, but since I’m rocking SVN I can just blow it out if it doesn’t work correctly.

Update:

I think that I finally understand what that quote above is actually telling me to do. I wasn’t exactly clear before.

  • Compute a key for the song during NSMutableDictionary creation that’s based on the number of characters in the string. This could be an int for example.
  • All songs with the same length of characters in it’s string would be ganged up under the auspices of that key… the object for that key (let’s say for example the key is 20) would be an NSMutableDictionary whose key would be song title and object be an MPMediaItem.
  • So now when searching one doesn’t need to rip through every single item, but intelligently narrow down which (or which few if one employs a close but not exact match allowance) group of potential matches to dig through, saving oodles of time.

Instead of tearing up code to give this a go, I plan on just adding another step in the data generation method and optionally use it’s architecture to see how it speeds things up without degrading accuracy.

Fun stuff :)

Update2: 

That’s not what he was exactly on about. (I need clarification because I don’t quite get the intricacies quite yet).

> a song search for “Cold Wind to Valhalla” … char count of 21, look in the dictionary for key of int 21 (or close), and check it (probably another dictionary) for it’s key of the title to get the MPMediaItem.

Not quite. “Cold Wind…” you add all the ascii codes of the chars – you may want to lowercase the string before, so it is case insensitive, thus you hash key would be :
key = 21 [length of your string] << 24 + (‘c’ + ‘o’ + ‘l’ + ‘d’ + ‘ ‘ + …) % (2^24 – 1).

You then look up all the keys whose upper byte is 21 ((keys >> 24) == 21) and then selected the one whose hash key (hashkey & 0x00ffffff) is the nearest to (key & 0x00ffffff).

Update 2:

Wow did I get a lot of help. After a lot of massaging and patting, the search that took 6 seconds each time now takes 500ms to 1000ms. That’s a HUGE improvement!!! I don’t have the time to post up how it works just yet, but it’s a great solution. Thank you Vincent!

Popularity: 3%

Pages ... 1 2