UIScrollView examples

Leave a comment

Here’s two ways to embed/use a UIScrollView for your iOS application.

1. Embedded UIScrollView from storyboard.

Say you have a really large image

and you want the user to be able to scroll around your phone with it.

One way (if you are using storyboards) is to add a UIImageView to your ViewController. Select the UIImage and change it’s ViewMode from Scale to fit -> Top Left).

And then embed your image in a ScrollView by going Editor -> Embed In -> ScrollView.

If you Shift-Right-Click on your image you should see a ScrollView element there now.

Now the only left is to set the content size of our scroll view area to be the same size as our big image.

You can do this by dragging over the scrollView and imageView as properties and then setting the content size in viewDidLoad like this:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.scrollView.contentSize = self.imageView.image.size;
}

Now everything should scroll.

That’s probably the easiest way to setup a scrollable image.

2. Draw scrollview outside of ViewController and add after.

Now option#1 was good for scrolling images, but what if your scrollable design area is bigger than your Xcode ViewController area?

Now you don’t want the scrollable area nested in your view, because you won’t be able to see your design.

This option always you to keep your UIScrollView outside your view for design, and then add it after in the viewController like so:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // set the content size to be the size our our whole frame
    self.scrollView.contentSize = self.scrollView.frame.size;
    
    // then set frame to be the size of the view's frame
    self.scrollView.frame = self.view.frame;
    
    // now add our scroll view to the main view
    [self.view addSubview:self.scrollView];
}

Big advantage of this option is it lets you see your design in Xcode in it’s entirety. Note this option was done with xibs – not storyboards (I havent figure out how to do this with storyboards yet).

But there you go. Two options for creating scrollviews.

A big thanks to Jeremy Gale (@jeremygale) for showing me option#2 with xibs (very handy).

Happy scrolling!

How to display iOS notification banner objective-c

Leave a comment

Ever wondered how to make that banner notification show up at top of an iPhone?

Here’s how you do it.

1. Define a local notification.

ViewController.m

- (void)viewWillAppear:(BOOL)animated {
    [self setupLocalNotifications];    
}

- (void)setupLocalNotifications {
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    
    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    
    // current time plus 10 secs
    NSDate *now = [NSDate date];
    NSDate *dateToFire = [now dateByAddingTimeInterval:5];
        
    NSLog(@"now time: %@", now);
    NSLog(@"fire time: %@", dateToFire);

    localNotification.fireDate = dateToFire;
    localNotification.alertBody = @"Time to get up!";
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.applicationIconBadgeNumber = 1; // increment
    
    NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys:@"Object 1", @"Key 1", @"Object 2", @"Key 2", nil];
    localNotification.userInfo = infoDict;
    
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}

This basically setup a local notification to fire 5 seconds in the future from when the app view comes on screen.

2. Register.

We register for the notification and look for it in AppDelegate.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
    UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    
    if (notification) {
        [self showAlarm:notification.alertBody];
        NSLog(@"AppDelegate didFinishLaunchingWithOptions");
        application.applicationIconBadgeNumber = 0;
    }
    
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    [self showAlarm:notification.alertBody];
    application.applicationIconBadgeNumber = 0;
    NSLog(@"AppDelegate didReceiveLocalNotification %@", notification.userInfo);
}

3. Display the alert.

AppDelegate.m

- (void)showAlarm:(NSString *)text {
	UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alarm" 
                                                        message:text delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
	[alertView show];
}

This gets called from the AppDelegate whenever the notification is recieved. Here we are popping up an alert, but this could manifest itself as an alert or banner (more on that in a second).

How to test

Fire up the app, put your app in the background (via the home button), wait 5 seconds, and voila, you should see this

or this

User chooses how to display

Now if you go through this example and don’t see a banner showing up at the top of your screen (you get an alert instead) it’s one of two things.

1. Banners don’t show up on simulators.

To see the banner you need to connect a real iPhone up to Xcode and run the example there.

2. Users choose how to display alerts.

In iOS5 there are two notification styles: alert or banner. Users choose which they would like at see in application settings (this is on a per app basis).

And as of now there is not way to choose or set this default up for them progammatically (though I believe the default is banner).

Good luck and happy notifying!

Links that help

http://stackoverflow.com/questions/8229385/set-default-ios-local-notification-style-for-application

How to pass blocks as variables in objective-c

2 Comments

Here’s some code that takes a block called success.


   AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        
        // city
        NSString *city = [JSON valueForKeyPath:@"location.city"];
        NSString *currentTemp = [JSON valueForKeyPath:@"current_observation.temp_c"];
        
        // create a weather object
        Weather *weather = [[Weather alloc] init];
        weather.city = city;
        weather.currentTemperature = [currentTemp intValue];

        // notify!
        NSDictionary *dictionaryWithWeather = 
        [NSDictionary dictionaryWithObject:weather forKey:WEATHER_KEY];
        [[NSNotificationCenter defaultCenter] postNotificationName:WEATHER_KEY 
object:self userInfo:dictionaryWithWeather]; 
        
    } ...

Cool. But what if I want to pull out that ‘success’ code out into a variable and pass it to the calling method. Here’s what it looks like.

First define a typedef for the block:

typedef void (^success)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON);

You can figure out the typedef method signature by looking at the underlying code, and then just sticking the word typdef in front of it. Note ‘success’ is the name of typdef here.

Then define a variable for the block:

    success requestSuccess;

Nothing magical. But I want you to see what assigning a variable to a block looks like. It looks like any other variable assignment.

Then instantiate your method and define the contents of the block.

    requestSuccess = ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        // city
        NSString *city = [JSON valueForKeyPath:@"location.city"];
        NSString *currentTemp = [JSON valueForKeyPath:@"current_observation.temp_c"];
        
        // create a weather object
        Weather *weather = [[Weather alloc] init];
        weather.city = city;
        weather.currentTemperature = [currentTemp intValue];

        // notify!
        NSDictionary *dictionaryWithWeather = 
        [NSDictionary dictionaryWithObject:weather forKey:WEATHER_KEY];
        [[NSNotificationCenter defaultCenter] postNotificationName:WEATHER_KEY 
object:self userInfo:dictionaryWithWeather];        
    };

Then replace the code you pulled out with the call to the block variable:

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        
        requestSuccess(request, response, JSON);
        
    } 

Voila! Cleaner more readable code.

How to pragmatically segue from one view to another with button press from storyboard iOS

Leave a comment

Usually in iOS we setup buttons in our ViewControllers, and then segue to new ViewControllers by clicking and control dragging the button to the new ViewController we want to transition to.

But what if you add a custom button to your UI, and you no longer have the the ability to control drag to your new ViewController. How do you tell the button which view to pop up?

Answer: Instantiate the view from the story board, and pragmatically pop your view controller from there.

Here’s where I manually at my own button to the NavBar:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStylePlain target:self action:@selector(gotoAlarmSettings)];
    self.navigationItem.rightBarButtonItem = anotherButton;

}

And then here is how you instantiate a view from the storyboard:

- (IBAction)gotoAlarmSettings {
    AlarmViewController *alarmView = [self.storyboard instantiateViewControllerWithIdentifier:@"foobar"];
    [self.navigationController pushViewController:alarmView animated:YES];
}

Note: You set the identifier for your viewController in the story board (else they won’t connect).

 

If you don’t do it this way, and you instead just popup it up regularly like this:

    AlarmViewController *alarmView = [[AlarmViewController alloc] init];

The transition will work, but you will get a black screen for your view.

Accidentally dragged directory to desktop and couldn’t move back – how to fix

Leave a comment

I found this annoying. I accidentally dragged a file from my favorites Finder to my desktop and I couldn’t drag it back.

I fixed it by going to the command line and manually moving the file by going like this:

> cd <dir where folder lives> 
> mv <folder> <newLocation>  

For me I needed to move my ‘Developer’ folder from the ‘Desktop’ dir back to /usr/jr so I did this:

> cd Desktop 
> mv Developer ..  

How to parse JSON objective-c

2 Comments

Say you make a call to a web service of some kind and you get a response that looks like this:

"forecast":  {
    "txt_forecast":  {
        "date": "6:00 AM MDT",
        "forecastday":  [
                         {
                             "period": 0,
                             "icon": "mostlycloudy",
                         },

And you want to get some nested element like ‘icon’. Here’s one way you can do it:


success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
                                             
NSString *icon = [json 
valueForKeyPath:@"forecast.txt_forecast.forecastday.icon"];
}

The network library AFNetworking (highly recommended) returns a json object which is a NSDictionary.

You can treat this dictionary like any other NSDictionary and grab subelements using ‘valueForKeyPath’
Thanks Dave Anderson and Paul Thorsteinson for showing me this.

How to include non ARC file in your ARC project

Leave a comment

Many iOS libraries out there are non ARC. When you include them in your project and try to compile you’ll get errors like:

release is unavailable

To include non ARC files in your ARC project do the following:

Click on your project in the Navigator.

Pick your target.

Click ‘Build Phases’

Click ‘Compile Sources’

Select all the files you want to flag as non ARC

Hit return

Type ‘-fno-objc-arc’

What this basically does is it sets a flag and marks those files as non ARC (so the compiler won’t try to compile them as ARC).

Hit compile and those errors should go away.

Thank you to David Anderson for this tip.

Git workflow

4 Comments

I’ve just started working with a team on git and I wanted a visual of what was going on every time I made a change and needed to checkin some code.

Xcode end of line short cut key conflicting with mission control

Leave a comment

The end of line short cut key (Command + ->) conflicts with mission control move commands.

To turn off mission control go into  System Preferences -> Keyboard -> Mission Control and uncheck ‘Move right a space’.

Updating iOS application – this bundle is invalid error

Leave a comment

If you go to update your app in the app store and you see this error message:

This bundle is invalid. The key CFBundleVersion in the Info.plist file must contain a higher version than that of the previously uploaded version.

Do this. Go to your plist file.

And changed the ‘Bundle versions string, short’ and ‘Bundle version’ from 1.0 to whatever you told in iTune Connect (1.1 for me).

Then when you go back and redo your archive distribution it should now successfully validate.

Links that help

http://agilewarrior.wordpress.com/2012/04/02/how-to-distribute-ad-hoc-build-with-xcode-4/
http://stackoverflow.com/questions/4933093/cfbundleversion-in-the-info-plist-upload-error

Older Entries

Follow

Get every new post delivered to your Inbox.

Join 40 other followers