amro's blog

  • rss
  • archive
  • Using GCD to Wait on Many Tasks

    I recently needed a way to perform an unknown number of asynchronous http requests and wait until they were all done before proceeding. dispatch_groups are a neat feature of Grand Central Dispatch (GCD) that made this easy to do.

    There are a couple of ways to use dispatch_groups but the basic idea is the same: create a dispatch_group, give it some tasks, and wait for it to finish those tasks.

    First, let’s create a group:

    dispatch_group_t group = dispatch_group_create();

    There are two ways to add tasks to our dispatch_group. You can either call dispatch_group_async with the group, a dispatch_queue and block to run or manually call dispatch_group_enter.

    Calling dispatch_group_async looks something like this:

    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Do stuff on a global background queue here
    });

    Or you can manage tasks manually by calling dispatch_group_enter and dispatch_group_leave in pairs:

    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Do stuff on a global background queue here
        dispatch_group_leave(group);
    });

    Using dispatch_group_enter/dispatch_group_leave is handy when you’re using libraries that provide asynchronous operation (e.g. AFNetworking).

    The last thing to do is wait for all of the tasks to finish. The preferred way to do this is to use dispatch_group_notify:

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // Do stuff after all tasks are finished
    });

    dispatch_group_notify is nice because it does not block the thread it’s called from. If you have a reason to block the current thread, use dispatch_group_wait instead:

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    // Do stuff after all tasks are finished

    A full example looks like this:

    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Do stuff on a global background queue here
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // Do more stuff on a global background queue here
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // Do stuff after all tasks are finished
    });

    One important note about dispatch objects: If your project’s deployment target is less than 6.0, you need to manage memory with dispatch_retain and dispatch_release for any dispatch objects you create (groups, queues, semaphores). ARC takes care of managing memory for dispatch objects when your deployment target is 6.0+ (10.8+ for OS X).

    • 1 month ago
  • Installing Ruby 1.9.3 on Ubuntu from Source

    Just a note for myself since most of the tutorials seem to leave out libyaml or something.

    sudo apt-get install gcc g++ build-essential libssl-dev libreadline5-dev zlib1g libyaml-dev zlib1g-dev linux-headers-generic libsqlite3-dev
    wget ftp://ftp.ruby-lang.org//pub/ruby/1.9/ruby-1.9.3-p194.tar.gz

    tar -xvzf ruby-1.9.3-p194.tar.gz
    cd ruby-1.9.3-p194/ && ./configure —prefix=/usr/local && make && sudo make install

    Posted via email from amro’s blog

    • 1 year ago
  • How to Retain Your Employees

    Genuinely give a shit. That’s the TL;DR but I’ll elaborate. High turnover, especially at startups, is often the result of burn out. Here are my thoughts on preventing burnout.
    Here’s the thing, your employees care about your business. Even the lazy ones. But they don’t want to fight fires all the time. Set the expectation that they should be intense while they’re at work and have a life afterward[1]. Instead, set reasonable goals. Figure out what’s most important and give them reasons to want to work hard for you. What incentives? Money. Food. Feedback[2]. Sure, any of those, and probably lots of other things. 

    Employees don’t want to feel like “resources.” They want to feel human and do their part to make the cogs turn. Training employees will cost you in the long run so give current employees good reasons to stick around. Don’t be stingy. Give employees enough money to make them feel valued. That means good raises, bonuses, and so on [3]. While money isn’t everything, the perception of forward movement goes a long way.
    Food is great because it’s a great way to make people feel cared for without spending tons of money, especially during crunch time. At my day job, they buy us lunch when it rains or when new people join. Sometimes it’s fancy food and other times it’s pizza. But it’s always appreciated.

    Feedback is free. Let employees know what you think of their work. If they’re doing a great job then praise their work. If they’re struggling then coach[4] them and help them improve. That’s often easier than finding new employees to replace the ones you fire.
    It’s not your job to make your employees happy but it is your job to provide a great work environment, set expectations, and encourage employees to be intense at work without burning out.

    [1] Sometimes work outside of typical hours is required. That’s fine. What’s not fine is for that to be the norm.
    [2] You should also give critical feedback when your employees screw up. Employees need mentorship as much as they need praise.
    [3] Giving extra money isn’t always possible. Profitable companies (or companies with tons of VC dough) can do a better job at this. And obviously it should be a sound business decision (as defined by the resources you have at your disposal).
    [4] Note that coaching and negativity are not the same thing. Coaching means telling them what they’re doing right and pointing out where they can improve. Be constructive and critical. Don’t be negative.

    Posted via email from amro’s blog

    • 1 year ago
  • Nest

    I bought a nest thermostat a while back. I wanted it because of one particular feature: the ability to set the temperature in my home from my iPhone and iPad (or an Android device, web browser). Installation was a piece of cake — a couple of screws and four wires. Setup was simple and the web and mobile apps are well done. Plus it promises to save one money and is software upgradable (wee!). It’s an incredible little device.
    Fast forward to a few days ago, when the nest reported that it couldn’t detect the fan wire. It also read the current temperature in the house a few degrees higher than actual (confirmed with two other thermometers). We had just installed a whole house humidifier, through which the fan wire runs, so I thought fan wire issue might be related to that. Nope. Then the nest dropped off my wireless network and gave a low battery warning. This is odd because my nest has been working without issue for weeks. I tried the obvious (charging via usb, resetting to factory settings, etc.) but nothing seemed to help. My house was now around 64 degrees fahrenheit (the nest claimed 84!) late on Sunday. Hardware stores, where one might buy a temporary thermostat, are closed.

    So I called support. I was on hold for longer than I liked (perhaps 20 minutes?), then a guy named David picked up. David was exactly the kind of guy you want on the other side of a telephone call in a situation like this. I described the symptoms and he immediately knew what was up — a bad update (v1.1.2) had been downloaded by my nest and couldn’t be installed. The nest was repeatedly trying to install this update, which ran the battery down and caused my problem. David was able to look at detailed logging to see that my nest had indeed downloaded said bad build, and essentially issued a command for my nest to download a new fixed version of the same build.
    At this point, I charged the nest via usb once more and put it back on the base an hour later. I set it to heat my home, made sure it was connected to my network, and left it alone. A few minutes later all was well. The temperature nest was reading was closer to normal and entirely normal by morning). So not only did they have someone there to take my call late on a Sunday night, but they also had enough data to know exactly what my problem was *and* push an update to fix it the same night. Should this have happened at all? No. Did they resolve my issue promptly? Very much so. Nest has excellent support.

    An aside — the nest is a mass storage device. It shows up as a drive with 40MB free space and has a single visible file — a plist file containing the serial number and some other mundane info. The plist is curious (it definitely shows the nest’s Apple roots, so to speak).

    Posted via email from amro’s blog | Comment »

    • 1 year ago
  • Uh oh. The boy just Climbed out of his crib for the first time.

    • 1 year ago
    • 1 year ago
  • Springboard Style Wiggles

    So you figured out how to setup a UILongPressGestureRecognizer and now you want to make a view “wiggle” back and forth similar to the iOS Springboard app. This is actually pretty simple with Core Animation.
    First, setup the view you want to wiggle. The code below assumes it’s called “view.” I’ve found that setting kWiggleAnimationAngle to 0.04 works well.

    In your gesture recognizer’s handler:
    //Start at negative kWiggleAnimationAngle so we animate to positive kWiggleAnimationAngle
    view.layer.transform = CATransform3DMakeRotation(-kWiggleAnimationAngle, 0, 0, 1.0);

    //Setup a transform that will rotate our view to positive kWiggleAnimationAngle
    CATransform3D transform = CATransform3DMakeRotation(kWiggleAnimationAngle, 0, 0, 1.0);
    //Setup our animation with the transform
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@”transform”];
    animation.toValue = [NSValue valueWithCATransform3D:transform];
    animation.repeatCount = HUGE_VALF;
    animation.duration = 0.1;
    animation.autoreverses = YES;
    [view.layer addAnimation:animation forKey:@”wiggle”];

    We’re also setting a few important properties:
    - setting repeatCount to HUGE_VALF tells the animation to play indefinitely
    - duration is the length of the animation (in one direction)
    - autoreverses tells Core Animation to automatically play the animation in reverse once it’s finished
    Finally we add the animation to our view’s layer and that’s that. Well, sort of, when we’re ready to stop the animation we need to do the following:

    //Remove the animation from our view
    [view.layer removeAnimationForKey:@”wiggle”];
    //Rotate the view back to its default position
    view.layer.transform = CATransform3DMakeRotation(0.0, 0, 0, 1.0);

    Resources: Apple’s Core Animation Programming Guide, WWDC 2011 Videos, Almost There Stackoverflow Post
    Notes: I generally dislike in-app Springboards but sometimes they fit the bill.

    Posted via email from amro’s blog | Comment »

    • 1 year ago
  • The case for a real ‘Apple TV’? (Taken with instagram)

    The case for a real ‘Apple TV’? (Taken with instagram)

    • 1 year ago
  • Little man wearing his Star Wars shirt. 16 months old today. (Taken with instagram)

    Little man wearing his Star Wars shirt. 16 months old today. (Taken with instagram)

    • 1 year ago
  • Watching Buzz Aldrin speak. Last WWDC session. (Taken with instagram)

    Watching Buzz Aldrin speak. Last WWDC session. (Taken with instagram)

    • 1 year ago
© 2008–2013 amro's blog
Next page
  • Page 1 / 5