10.10.2012

How iOS 6 Messed Up Pre-iOS 6 Applications

Probably one of the most annoying things for iOS users when iOS 6 came out is that their downloaded apps are not working with the new iOS version. Most of the apps in the AppStore (or any other download sites) were written to run in an optimal level with iOS 5, and maybe also with iOS 4. Software developers are not clairvoyant you know (... well maybe some but not all). So, if the app they created for iOS 5 is no longer functional in iOS 6, it is not completely--they are still liable for some errors because of their carelessness, of course--their fault. They won't know the changes to the SDK until, well, it's too late... (I just had my app publiiiiiiiiiiiiiiiiiiieeeeeeeshedaaaaargggh!!! - one random unhappy iOS developer)

Anyway, so why are some apps not working or why are they crashing a lot? The answer, my friends, are the deprecated methods/functions (whatever you call them). Here are some of the common problems and the possible solutions to them:


Problem 1:

My app crashes every 5 minutes!

Causes:

viewDidUnload
Called when the controller’s view is released from memory. (Deprecated in iOS 6.0. Views are no longer purged under low-memory conditions and so this method is never called.)

viewWillUnload
Called just before releasing the controller’s view from memory. (Deprecated in iOS 6.0. Views are no longer purged under low-memory conditions and so this method is never called.)

Solution:

Use applicationDidReceiveMemoryWarning: to handle low-memory conditions.

applicationDidReceiveMemoryWarning:
Tells the delegate when the application receives a memory warning from the system.


Problem 2:

My app is not changing its orientation when I rotate the device!

Cause:

shouldAutorotateToInterfaceOrientation:
Returns a Boolean value indicating whether the view controller supports the specified orientation. (Deprecated in iOS 6.0. Override the supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation methods instead.)

Solutions:

Use shouldAutorotate, supportedInterfaceOrientations, preferredInterfaceOrientationForPresentation.

shouldAutorotate
Returns whether the view controller’s contents should auto rotate.

supportedInterfaceOrientations
Returns all of the interface orientations that the view controller supports.

preferredInterfaceOrientationForPresentation
Returns the interface orientation to use when presenting the view controller.


Problem 3:

My app launched but is not showing anything!

Causes:

modalViewController
The controller for the active presented view—that is, the view that is temporarily displayed on top of the view managed by the receiver. (read-only) (Deprecated in iOS 6.0. Use presentedViewController instead.)

presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user. (Deprecated in iOS 6.0. Use presentViewController:animated:completion: instead.)

dismissModalViewControllerAnimated:
Dismisses the view controller that was presented by the receiver. (Deprecated in iOS 6.0. Use dismissViewControllerAnimated:completion: instead.)

Solutions:

Use presentedViewControllerpresentViewController:animated:completion:, and dismissViewControllerAnimated:completion:.

presentedViewController
The view controller that is presented by this view controller, or one of its ancestors in the view controller hierarchy. (read-only)

presentViewController:animated:completion:
Presents a view controller.

dismissViewControllerAnimated:completion:
Dismisses the view controller that was presented by the receiver.



9.22.2012

[iOS] Saving the Singleton Object's State to File

Here's a way to save a singleton object's state into a file.
TestSingleton.h:
@interface TestSingleton : NSObject

@property (nonatomic, retain) NSString *testString;

+ (id)sharedInstance;
- (BOOL)saveState;

@end

TestSingleton.m:
#import "TestSingleton.h"

static TestSingleton *sharedInstance = nil;

@interface TestSingleton()

@property (nonatomic, retain) NSString *file;

@end

@implementation TestSingleton

@synthesize testString = _testString;
@synthesize file = _file;

- (void)dealloc
{
    [_testString release];
    [_file release];
    [super dealloc];
}

+ (id)sharedInstance
{
    @synchronized(self){
        if(sharedInstance == nil){
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *testFile = [documentsDirectory stringByAppendingPathComponent:@"testfile.sav"];
            Boolean fileExists = [[NSFileManager defaultManager] fileExistsAtPath:testFile];
            
            if(fileExists) {
                sharedInstance = [NSKeyedUnarchiver unarchiveObjectWithFile:testFile];
            }
            else{
                sharedInstance = [[super allocWithZone:NULL] init];
            }
            sharedInstance.file = testFile;
        }
    }
    return sharedInstance;
}

- (BOOL)saveState
{
    return [NSKeyedArchiver archiveRootObject:self toFile:sharedInstance.file];
}

- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_testString forKey:@"test"];
}

- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if(self){
        _testString = [[NSString alloc] initWithString:[aDecoder decodeObjectForKey:@"test"]]; 
    }
    return self;
}

@end


Now, in the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    TestSingleton *singleton = [TestSingleton sharedInstance];
    NSLog(@"PREVIOUS STATE: %@", singleton.testString);
    //Update testString
    singleton.testString = [[NSDate date] description];
    NSLog(@"NEW STATE: %@", singleton.testString);
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    //This will save the state of the singleton object when the object tries to go the background
    [[TestSingleton sharedInstance] saveState];
}

9.14.2012

String Representation of Date from UIDatePicker

In iOS, there's this UI element that allows the user to select the date and time. This is called the Date Picker.

Here's a way of getting the text from the iOS' Date Picker:


/*_datePicker is the current UIDatePicker object. Set the mode of the date picker. In this example, setting the time is disabled.*/
[_datePicker setDatePickerMode:UIDatePickerModeDate];
/*Initialize a NSDateFormatter object. This object will get the string representation of the NSDate object.*/
_dateFormatter = [[NSDateFormatter alloc] init];
/*Set the locale of the NSDateFormatter object.*/
NSLocale *locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_EN"] autorelease];
[_dateFormatter setLocale:locale];
/*Set the date style and the time style of the formatter. Note that the next two lines of code are important. Without them, when NSDateFormatter's instance function/method - stringFromDate: is used, the returned string is empty. It is not stated in the NSDateFormatter class reference that the default value of dateStyle and timeStyle are set to NSDateFormatterNoStyle but I think they are.*/
[_dateFormatter setDateStyle:NSDateFormatterLongStyle];
[_dateFormatter setTimeStyle:NSDateFormatterNoStyle];

...

/*This is the code for getting the string representation of the selected date*/
NSString *selectedDate = [_dateFormatter stringFromDate:_datePicker.date];


Note: Automatic Reference Counting (ARC) is not used in this example.

2.13.2012

How To Make GDataXMLNode Work

To use GDAtaXMLNode, both the .h and .m files must be added to your code. Then do the following:
  1. Select the project.
  2. Select Build Phases tab.
  3. Expand Link Binary With Libraries. Click +.
  4. Locate libxml2.dylib then click Add.
  5. Select Build Settings tab.
  6. Under Search Paths > Header Search Paths, Select Debug then click on the little white circle with the blue plus sign inside.
  7. On the value field, enter "/usr/include/libxml2" without the quotation mark.
  8. Click the icon with two little black triangles, which is on the left of the little white circle with blue minus sign inside, then select Any architecture.
  9. Repeat step 8, select Any SDK.
  10. Under Search Paths > Header Search Paths, Select Release then click on the little white circle with the blue plus sign inside.
  11. Repeat steps 7 to 9 for Release.
If your code is using Automatic Reference Counting (ARC) do the following:
  1. Select Build Phases tab.
  2. Expand Compile Sources.
  3. Select GDataXMLNode.m then press Enter.
  4. On the small input box that pops-out, enter -fno-objc-arc.
And you are done! :)

1.31.2012

Objective-C: Creating a Random Number and Storing To NSString

I wanted to generate a random number and convert it to NSString:

NSString *myRandomNumber = [NSString stringWithFormat: @"%u", arc4random()];

1.18.2012

How to SVN Checkout through Mac Terminal

I am currently learning iOS development and one of the things I need to do is checkout the current code for our iOS project. As of the moment, after clean installing the OS of my workstation which is a MacBook Pro, I haven't installed any application yet other than Xcode. So to checkout the code, I used the Terminal. The checkout is very simple:

  1. Open Terminal through Launchpad > Utilities
  2. On Terminal, type svn co https://your.svn.url --username your_username --password your_password

Note: --username is optional. --password is conditional: username must be present.