Tuesday, January 8, 2013

iOS 5 : Customize UINavigationBar and UIBarButtonItem with the Appearance API



Change UINavigationBar Background
With the release of iOS 5, the UIAppearance protocol is used to access the appearance proxy for a class you would like to configure. Customization is done by sending messages to the target class appearance proxy. When changing the appearance of an object, all instances of the object can be updated or only specific instances within a container class.
Let’s see how this looks as it relates to updating the background color of a UINavigationBar, it’s text and the back button which will allow a user to return to a previous view controller.
The image below is the gradient that I will use for the background:
Using the above image, I created a one pixel wide image for both portrait and landscape variations of the navbar, reason being, the height of the navar bar when the device is in portrait mode is 44, whereas the height for landscape is 32.
The images in my project are NavigationPortraitBackground.png and NavigationLandscapeBackground.png, both shown below:
I now create two UIImage objects:
// Create image for navigation background - portrait
UIImage *NavigationPortraitBackground = [[UIImage imageNamed:@"NavigationPortraitBackground"] 
                              resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
 
// Create image for navigation background - landscape
UIImage *NavigationLandscapeBackground = [[UIImage imageNamed:@"NavigationLandscapeBackground"] 
                              resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
To set these images as the new backgrounds for all navigation bars, here’s all I need to do:
// Set the background image all UINavigationBars
[[UINavigationBar appearance] setBackgroundImage:NavigationPortraitBackground 
                                     forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:NavigationLandscapeBackground 
                                     forBarMetrics:UIBarMetricsLandscapePhone];
In addition to the color, I can change the appearance of the text on all navigations bars as well:
// Set the text appearance for navbar
[[UINavigationBar appearance] setTitleTextAttributes:
    [NSDictionary dictionaryWithObjectsAndKeys:
    [UIColor whiteColor], UITextAttributeTextColor, 
    [UIColor redColor], UITextAttributeTextShadowColor, 
    [NSValue valueWithUIOffset:UIOffsetMake(0, 0)], UITextAttributeTextShadowOffset, 
    [UIFont fontWithName:@"Verdana-Bold" size:16], UITextAttributeFont, 
    nil]];
As the final step, I will update the back button with a custom image, which is shown below (the button is shown on a gray backdrop so you can see the white border):
Using what I described in the early post about cap insets, I can create a UIImage object and use the appearance API of the UIBarButtonItem to set the back button look. Notice that each value in the cap inset is set to 12, indicating all four corners are to hold steady at 12 pixels, even if the images stretched or resized.
// Set back button for navbar
UIImage *backButton = [[UIImage imageNamed:@"blueButton"]  resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
  [[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButton forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
The last step is to create a button for the user interface that will push a new view controller, which will update the navigation bar to show the custom back button created above.
...
 
testButton = [[UIButton alloc] initWithFrame:CGRectMake(80, 30, 160, 44)];  
[testButton setTitle:@"Test Button" forState:UIControlStateNormal];
 
// Notice cap insets are different from above
UIImage *buttonImage = [[UIImage imageNamed:@"blueButton"]  resizableImageWithCapInsets:UIEdgeInsetsMake(0, 16, 0, 16)];
 
[testButton addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];        
[testButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
 
...
An important concept to understand here, I’ve used the same image, blueButton.png, for both the custom back button as well as the button on the primary user interface – setting the cap insets specifies the rules, if you will, of how the image can be stretched, yet keep the look appropriate for the context in which the button will appear (that is, on the navbar or main UI).
A few screenshots follow that show the custom navigation bar, text and buttons in both portrait and landscape modes:

i copied this post from this link 
http://mobiledevelopertips.com/user-interface/ios-5-customize-uinavigationbar-and-uibarbuttonitem-with-appearance-api.html#comment-109364

Monday, October 1, 2012

shouldAutorotateToInterfaceOrientation not getting called in iOS 6


The shouldAutorotateToInterfaceOrientation method is deprecated in iOS6. Instead shouldAutorotate and supportedInterfaceOrientation methods are used. If some logic is used in shouldAutorotateToInterfaceOrientation method, it should be implemented in -willRotateToInterfaceOrientation:duration: method.
First, if you want the view controller’s content to be able to auto rotate just return YES in -shouldAutorotate method.
1
2
3
4
- (BOOL)shouldAutorotate
{
 return YES;
}

Supported interface orientations are returned in the -supportedInterfaceOrientations method.
- (NSUInteger)supportedInterfaceOrientations
{
        //if you have different views for portrait and landscape they are assigned here for the first time
 self.view = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? _viewLandscape : _viewPortrait;
        //return orientations you want to support
 return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown);
}

f there is some logic, like switching views for landscape and portrait on rotation use the -willRotateToInterfaceOrientation:duration: method.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
 [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
 self.view = UIInterfaceOrientationIsLandscape(toInterfaceOrientation) ? _viewLandscape : _viewPortrait;
}

Friday, September 28, 2012

How to get the attributes of an instance of NSTableView


How to get the attributes of an instance of NSTableView


The table view object (in MacOSx) is a collection of nested objects :

  • NSScrollView, 
  • NSTableView,
  • NSTableColumn
To get to a ojbect in this collection, 
  • hold down the Control and Shift keyswhile clicking on the table view. 
You will see a list of the objects under the cursor, and you can select the object you're interested in. 


How can you suppress compilers warning "can't find an implementation of accessor methods"


How can you suppress compilers warning "can't find an implementation of accessor methods"

#:fromDocumentation
You use the @dynamic statement to tell the compiler to suppress a warning if it can’t find an implementation of accessor methods specified by an @property declaration.
@implementation MyClass

@dynamic title;

@end

A summary of property-properties attributes - and some tips


A summary of property-properties attributes - and some tips


@Property attributes
Writability
readwrite
mutually exclusive
default
Indicates that the property should be treated as read/write
readonly

only a getter method is required
if you attempt to assign a value using the dot syntax, you get a compiler error.
A readonly property can redelcare it as readwrite in a  class extension, a protocol or in a subclass.
Setter
Semantics
assign (iOS 5)
unsafe_unretain (iOS4)




default

setter uses simple assignment (new value not retained, old value is not released).
use this for scalar types (NSInteger, CGRect in Ref.Counted env.
on dealloc method make sure that object propertis marked assign are not released and the not assign are released.
property=newValue;
retain
strong
if (property!=newValue){
 [property release];
property = [newValue retain];
retain should be invoked on the object upon assignment
the previous value is sent a release message
valid only for Objective-C object types (no for Core Foundation)
_attribute_
use attribute keyword to specify that a Core foundation property should be treated like an Objective C for memory management
copy

if (property!=newValue){
[property release];
property = [newValue copy];
}
a copy of the object should be used for assignment
previus value is sent a release message
valid only for objects that implement the NSCopying protocol
WARNING-the copy method returns an immutable version of a collection, so if you want a mutable version you need to implement the setter rather to synthesize it.
Atomicity
nonatomic
Specify that accessor methods are not atomic
(by default accessors are atomic=robust access to properties in a multithreaded environment)
If you specity retain or copy with not the noatomic, then in a reference-counted environment, a synthesized get accessor for an object property uses a lock and retains and autoreleases the returned value (similar to code below nonatomic)
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
Interface Outlet
IBOutlet

To specify that a property is an Interface Builder oulet
@property (nonatomic, retain) IBOutlet NSButton *myButton;


  • when you see __Blabla is for instance variables and Blabla is for property attribute.
  • For declared properties, you should use assign instead of weak; for variables you should use __unsafe_unretained instead of __weak.
  • You will always use unsafe_unretained for properties that hold non-objects.
  • For properties that hold objects, you will usually use strong
  • unsafe_unretained will have a "dangling pointer" if the object it points to is deallocated.
  • Their most common use is for delegates, where you'd define a property for that delegate with the weak orunsafe_unretained attribute (assign is effectively unsafe_unretained),
  • copy attribute is most common with object types that have mutable subclasses.
  • copy method returns an immutable copy.
  • Curiously the copy and mutableCopy methods are define in NSObject like this:
-(id) copy              {return [self  copyWithZone:NULL];}
-(id) mutableCopy {return [self mutableCopyWithZone:NULL];}

         So you need to be carefully in your custom objects (you need to override the copyWithZone etc).

  •   nonatomic option will make your setter method run a tiny bit faster. 

TIP_1: 
For iOS 5.0-Lion use __weak. For iOS4.0-Snow Leopard use __unsafe_unretained. Why?

 As its name implies, __unsafe_unretained will continue pointing to the memory where an object was, even after it was deallocated. This can lead to crashes due to accessing that deallocated object.
Why would you ever use __unsafe_unretained then? Unfortunately, __weak is only supported for iOS 5.0 and Lion as deployment targets. If you want to target back to iOS 4.0 and Snow Leopard, you have to use the __unsafe_unretained qualifier.


TIP_2:
Do you know that when compiling for iOS or a 64-bit Mac OS X (not for 32-bit Mac OSX) program, you don't need to declare the instance variables?
The @property/@ synthesize calls are sufficient to make the space for the data.
(from The big nerd ranch Guide)

Retain Cycle


Retain Cycle


Retain cycles are a very common source of memory leaks.

We have retain cycles when :
The object A has strong ownership on object B (direct or indirect) and the B has, also strong ownership at A.

That happens for example if the A has an MutableArray of objects B and some from objects B have strong ownership on object A.

the solution on theses cases is to use strong ownership (retain, alloc, etc) to child objects (B) and the child objects to have weak (__weak) ownership at the father.

Apple provides the Instrument profiling tool to help you with that.
When you profile a program, you monitor it while it runs to see what’s happening behind the scenes.



  • Xcode -> 
  • Product -> 
  • Profile … (Instruments launch) choose Leaks 
  • -> Choose Cycles to see if your project has some of them. 




#:from Objective - C programming: The big Nerd Ranch Guide

Callbacks - short notes


For Objective-C programmers, there are three-forms that a callback can take.

  • -       TARGET-ACTION: before the wait begins you say “When x happens, send this particular message to that particular object,” The object receiving the message is the target. The selector for the message is the action.
  • -       Helper objects: Before the wait begins, you say “Here is a helper object that conforms to your protocol. Send it messages when things happen”. Helper objects are often known as delegates or data sources.
  • -       Notifications: There is an object called the notification center. Before the wait begins, you say to the notification center “This object is waiting for these sorts of notifications. When one of those notifications arrives, send the object this message”. When x happens, an object posts a notification to the notification center, and the center forwards it on to your object.

Types of Callbacks
Target-Action
sending ONE    callback   to ONE object
timers,simple user interface controls(buttons, sliders etc)
Helper objects
(delegate or data source)
sending MANY callbacks to ONE object
NSURLConnection.
The most common type of helper object is the delegate
Notifications
sending MANY callbacks to Multiple object
Notification center


Notes:
-       Notification centers do not own their observers (they typically remove itself from notification in its dealloc method)
-       Objects do not own their delegates or data sources (if you create an object that is delegate or data source, your object need to “clear” himself in its dealloc method). Exception: NSURLConnection owns its delegate
-       Objects do not own their targets. (if you create an object that is a target, your object should zero the target pointer in its dealloc method).Exception: NSTimer owns it’s target.



#:From The Big Nerd Ranch Guide Objective C programming