Archive
UINavigationBar Color of More Tab in iOS 5
If you start a Tabbed Application and use Storyboards in Xcode with iOS 5 a simple project will be created with two tabs. If you add more than 5 Tabs to the Tab Bar Controller a “More” tab will be created automatically.
The NavigationBar in the More Tab and the modal view (edit) are colored with default blue. To change the color of the moreNavigationController you have to do the following steps.
Extend app delegate so that it implements the UIApplicationDelegate and UITabBarControllerDelegate protocols.
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> { UIWindow *window; UITabBarController *tabBarController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) UITabBarController *tabBarController; @end
The app delegate doesn’t know anything about the ViewControllers yet, so it will have to dig through the storyboard to find it. With Interface Builder you always had a reference to the App Delegate in your MainWindow.xib and you could make connections from your top-level view controllers to outlets on the App Delegate. That is currently not possible with storyboards. You cannot make references to the app delegate from your top-level view controllers. So you have to get those references programmatically. You know that the storyboard’s initial view controller is a Tab Bar Controller, so you can look up the window’s rootViewController and cast it.
UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController;
Then you can get the More Tab by the Tab Bar Controller and set a color.
UINavigationController *moreController = tabBarController.moreNavigationController; moreController.navigationBar.tintColor = [UIColor orangeColor];
After that you use the App Delegate as the delegate of the Tab Bar and change the color of the “Edit” View, too.
tabBarController.delegate = self; ...</pre> UIView *editView = [controller.view.subviews objectAtIndex:1]; UINavigationBar *modalNavBar = [editView.subviews objectAtIndex:0]; modalNavBar.tintColor = [UIColor orangeColor]; <pre>
The complete code of AppDelegate.m:
#import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; @synthesize tabBarController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Get top-level view controller reference programmatically tabBarController = (UITabBarController *) self.window.rootViewController; // Set the color of the navigationbar in moretab UINavigationController *moreController = tabBarController.moreNavigationController; // //moreController.navigationBar.barStyle = UIBarStyleBlackOpaque; moreController.navigationBar.tintColor = [UIColor orangeColor]; moreController.navigationBar.hidden = NO; moreController.navigationBar.backgroundColor = [UIColor blackColor]; // Set delegate of the tabBarController to handle the UITabBarControllerDelegate calls tabBarController.delegate = self; return YES; } - (void) tabBarController:(UITabBarController *)controller willBeginCustomizingViewControllers:(NSArray *)viewControllers { // Set the color of the navigationbar if edit was selected UIView *editView = [controller.view.subviews objectAtIndex:1]; UINavigationBar *modalNavBar = [editView.subviews objectAtIndex:0]; modalNavBar.tintColor = [UIColor orangeColor]; } @end
Here you can download the example Project.
Case insensitive comparison and searching NSString
if( [@"Some String" caseInsensitiveCompare:@"some string"] == NSOrderedSame ) { // strings are equal except for possibly case } NSRange range = [@"Some String" rangeOfString:@"string" options:NSCaseInsensitiveSearch]; if (range.location != NSNotFound) { // String found }
Converting NSString to NSDate and vice versa
NSDate *date = [NSdate date]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; // Convert a date to NSString and get rid of the minutes... NSString *strDate = [dateFormatter stringFromDate:date]; // Convert it back to NSDate NSDate *newDate = [dateFormatter dateFromString:strDate];
Check if view is visible
if (self.navigationController.visibleViewController == self) {}
NSString Basics
Creating strings
NSString *myFirstString = @"foo";
NSString *mySecondString = [[NSString alloc] initWithFormat:
@"%@%@%@i", myFirstString, @"bar", 1];
Comparing strings
NSString *myString = @"foo"; if([myString isEqualToString:@"foo"]) { NSLog (@"Strings are equal!"); }
Finding strings within strings
NSString *myString = @"foo"; NSString *searchForMe = @"Howdi"; NSRange range = [myString rangeOfString : searchForMe]; int location = range.location; int length = range.length; if (location != NSNotFound) { NSString *locationAndLength = [[NSString alloc] initWithFormat: @"Location: %i, length: %i",location, length];
NSLog(@"I found something."); NSLog(locationAndLength
); }
Replacing strings within strings
NSString *myString = @"foo"; myString = [myString stringByReplacingOccurancesOfString:@"oo" withString:@"uu"];
Extracting substrings from strings
There are 3 methods that allow to extract substrings from a parent string:
- -substringToIndex:
- -substringWithRange:
- -substringFromIndex: (which respectively take a substring from the beginning, middle, and end of a parent string)
The first method substringToIndex
returns a new string which is composed of the characters from the beginning of the receiver string up to (but not including) the character at the specified index:
NSString *aString = @"Running out of ideas for strings.";
NSString *substring = [aString substringToIndex:7];
// result: @"Running"
The method substringFromIndex
works in the same way, except now the substring starts at the specified index of the receiver (including the character at the index) and includes all the characters to the end of the receiver:
NSString *substring = [aString substringFromIndex:25]; // result: @"strings"
Finally, we have the method which lets us arbitrarily extract a substring from anywhere within the parent string substringWithRange
. The argument to this method is an NSRange
:
NSString *substring = [aString substringWithRange:NSMakeRange(15, 5)]; // result: @"ideas"
Here the range starts with the 15th character, “i”, and extends to include the next four characters, giving us a length of 5, “ideas”.
How to find class type of an object
NSLog(@"Is of type: %@", [myObject class]);
NSLog(@"Is of type NSString?: %@", ([[myObject class] isMemberOfClass:
[NSString class]])? @"Yes" : @"No");
NSLog(@"Is a kind of NSString: %@", ([[myObject classForCoder]
isSubclassOfClass:[NSString class]])? @"Yes" : @"No");
Location via GPS with iOS
First add the Core Location framework:
- right click on the “Frameworks” group and go to Add > Existing Frameworks…
- select the CoreLocation.framework
Then you can use the framework in your app:
#import <CoreLocation/CoreLocation.h>
@interface MyLocation : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
@end
#import "MyLocation.h"
@implementation MyLocation
- (id) init {
if ((self = [super init])) {
// Custom initialization
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
}
return self;
}
- (void) locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
int degrees = newLocation.coordinate.latitude;
double decimal = fabs(newLocation.coordinate.latitude - degrees);
int minutes = decimal * 60;
double seconds = decimal * 3600 - minutes * 60;
NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
degrees, minutes, seconds];
degrees = newLocation.coordinate.longitude;
decimal = fabs(newLocation.coordinate.longitude - degrees);
minutes = decimal * 60;
seconds = decimal * 3600 - minutes * 60;
NSString *lon = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
degrees, minutes, seconds];
}
@end
Differentiate between iPhone, iPad and simulator
#if TARGET_IPHONE_SIMULATOR
// simulator specific code#elif TARGET_OS_IPHONE
// iPhone specific code#elif TARGET_OS_IPAD // iPad specific code
#else // Unknown target #endif
Differentiate between iOS versions
Depending on your project settings Base SDK you can use the following code:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
// Do something for iOS > 4.0
#else
//Do something for iOS < 4.0
#endif
Private method in Objective-C
There are no private methods in Objective-C like e.g. in C# .NET. Though you can create a category with an empty name (class continuation) in Objective-C 2.0 (i.e. @interface MyClass ()
). With this category you can create the private method implementations in the same @implementation MyClass
file as the public methods.
With an addition like “__” at the start of your “private” methods you should bring in this naming convention to prevent your classes from being breakable in a too easy way. The possibility that someone will override some of your “private” methods by accident is then on a much lower value. Apple reserved names with a leading underscore for its own uses, so prefer an addition like “__”.
Create your classes for example like this:
In the header file:
@interface MyClass {
// My Instance Variables
}
- (void)myPublicMethod;
@end
And in the implementation file:
@interface MyClass(
/* Private methods */) - (void)__myPrivateMethod; @end @implementation MyClass - (void)myPublicMethod { // Implementation goes here } - (void)__myPrivateMethod { // Implementation goes here } @end
The second alternative is to put the category into its own .h file. You can name such a file after its class and category with a + separating them, so @interface MyClass (PrivateMethods)
can be found in MyClass+PrivateMethods.h
. With this convention you can import the header in your unit test classes.