UITableView Tricks – Part 2 – Infinite Scrolling

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

Last time I posted about the UITableView Tricks to lay the cells of the tablview in Circular fashion. It was well received by the community and thank you all for your feedback and compliments. 

I received many requests for making this circular list scroll infinitely as with UIPickerView, which means that the list repeats forever. It really makes sense just because the list itself is in circular fashion and user expect the content to repeat, without him/her having to scroll back to top.

I came across the 2011 WWDC video – Advanced Scrollview Techniques which provides the best feasible solution to support infinite scrolling. Many attempts have been made before to find a solution by having the height of the scrollview’s content size to a large number so that it takes days, if not AGES for a user to get to the end point. But it was never a complete solution.

 

I went a bit closer to the perfect solution and here it is. The goal here is to provide a generic solution to a UITableView while having the user/ developer to do minimum or ZERO changes. This lead me to create a subclass of UITableView, and named as BBTableView

 

By using BBTableView,  a developer has to do ZERO changes ( some minor changes for additional functionality, explained later ) to enable infinite scrolling. 

 

Behind the scenes:

 

 The core logic of this solution is

 

1. To increase the tableview content by a factor of 3, so that we make the 3 copies of the content laid one after another vertically. 

2. Whenever the top end of the scroll is reached, move the the scroll offset back to start of the 2nd copy

3. When the bottom end of the scroll is reached, we move the scroll offset back to the start of the 2nd copy minus the height of the tableview, so that we end up showing the same content as we are now.

Infinite Scrolling

This solution did bring an obstacle to my goal of making this component as a Drag-n-Drop component. i.e. Making 2 additional copies of rows provided by datasource also changes the index paths used in datasource or delegate methods that are propagated to the component user, a developer who would use this component.

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

This can be avoided by intercepting the delegate or datasource methods to morph the index paths exchanged between the UITableView and the its datasource or delegate methods.

Thanks Evadne Wu , for allowing me to use the interceptor component written by her.

Two  properties have been added to BBTableView,

a. contentAlignment

Allows the change the direction of the semi-circle. It supports two directions


ClockWiseScreen Shot 2012 12 07 at 9 25 33 PM

eBBTableViewContentAlignmentRight Layouts the circle Clockwise

eBBTableViewContentAlignmentRight – Layouts the circle Anti-Clockwise

b. enableInfiniteScrolling

    set YES to enable infinite scrolling. NO to reset to default scrolling behavior of UITableView

 

As every software, this component too have its Cons:

1. Since the issue with Index Paths resolved by intercepting delegate / datasource methods, Any additions or modifications to UITableView datasource/ delegate methods involving index path, requires a change to counterpart datasource / delegate methods implemented in BBTableView. However, on a good note, this change includes only getting the morphed index path and calling appropriate method on the receiver of Datasource interceptor.

A  sample intercepted Datasource method would look like:

(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [_dataSourceInterceptor.receiver tableView:tableView cellForRowAtIndexPath:MORPHED_INDEX_PATH(indexPath)];

}

 

Check the source code updated in github here https://github.com/bharath2020/UITableViewTricks

Happy Coding 🙂

Thoughts on iOS UDID

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

There is a lot of buzz with Apple’s rejection of apps accessing UDID API . Let us analyze it.

 

 

What is UDID?

 

UDID is the unique identifier to identify an iOS device uniquely. Apple had exposed an API to access this unique identifier from the start of iOS 2.0 SDK. This made interesting things possible and eventually became a critical API for some of the application’s core functionality. For example. Flurry Analytics, depend on this UDID for reporting number of devices an application is activated. Although, I cannot go through all the list of application using this API, let us do some Impact Analysis and possible problems and their solutions from this move by Apple.

 

When would you use the uniqueIdentifier?

 

I would typically use it in the context where I need to uniquely identify the device in a pool of iOS devices, where this info is send to a centralized place and is used for various purposes. Standalone applications more often does not need this info, unless they have integrated with third party SDK like Flurry, to support non-core features of an application, such as gathering statistics. Therefore, we would not keep this category of applications as these does not have major dependency on UDID.

 

 

What would you do with uniqueIdentifier with a pool of device?

 

Scenario 1:

 

“A scenario could be where the application could act as client and all the instances of the application across the devices are writing some data into the centralized place, could be a Mac or a Centralized Server. In this case the unique identifier would be able to identify the application instance uniquely to resolve the conflicts, say while writing the data to same location.”

 

Syncing

Fig: Scenario 1 showing Application installed in multiple iOS devices syncs with Mac / Server sharing and updating the data

Example: A Simple Notes application where notes are recorded in various iOS devices and then are synchronized with the Mac Application, where the Mac Application acting as a centralized unit.

 

Scenario 2:

 

“Another scenario would be to individually track the number of devices in which the application is activated which helps the sales people to pitch up their sales or we can find them in many of the third party ads which aid in gaining statistics of the application”

 

Example: Analytics SDK like Flurry, InMobi and so on.

 

While the first scenario helps the application in its core functionality, the second scenario is matter of statistics that helps drive the sales. However, accessing a unique identifier of a device without knowledge is a breach of privacy which i believe the motive behind apple deprecating this API.

 

Before digging deep, Let us look at the alternative solution from Apple?

 

Special Considerations:

 

Do not use the uniqueIdentifier property. To create a unique identifier specific to your app, you can call the CFUUIDCreate function to create a UUID, and write it to the defaults database using the NSUserDefaults class.

 

Well, CFUUIDCreate does create the unique identifier, but will that be sufficient to identify the Device uniquely?? Wait, am I sounding wrong! Your read it right.

Although Apple recommend to create unique identifier and store it in defaults, it works fine as long as the app isn’t deleted and re-installed by the user. Since, doing that would delete the defaults database and upon re-installing a fresh unique identifier would be created which defeats our purpose.

 

Let us track back and see what exactly we need

“We need to find a way where an application would identify uniquely against its clone across multiple devices.”

The critical requirement here is not creating a unique identifier, but persisting it from the time application is installed on a device till literally the lifetime of the device and not the application. Uh!!

There are many solutions floating around like the one from crashlytics, where they achieve the persistence by storing the custom unique identifier in the UIPasteboard. However, there are couple of cons here

  • Apple does not guarantee that the Pasteboard data persists permanently across OS upgrades or reboot
  • Any other application can access this data or override them and one need to ensure that this would be in un-readable form for other that the application which created it.

 

My Solution (Intermediate):

The solution is to change the way we modelled our application behavior. For you to understand, let me divide the iOS era into two.

Pre-iCloud & Post-iCloud.

In Pre-iCloud we used to treat each iOS device as a separate one even though they are owned by ( literally under same apple id) single person. This means that an app in iPhone would have different state than the one in iPad, and probably a External Sync would be required to get them into single state.

In Post-iCloud era, as a developer, one should not distinguish between an application installed in two iOS device grouped under single Apple ID, which is strong point behind the Apple’s iCloud – “It Just Works”. i.e the iCloud make sure that all the data and state information would be consisted across the iOS devices grouped under single Apple ID.

With that differentiation, the solution would be:

“Create a unique identifier as suggested by the Apple and  store them in defaults as wells as in iCloud. Check NSUbiquitousKeyValueStore or using this short piece of library from Mugunth Kumar which I liked, for storing into iCloud. So Even if the App is deleted, the same ID would be retrieved back from iCloud, unless your iCloud is reset which accom”

NOTE: We could use a same approach for tracking the number of apps installed with the difference being the count would be number of users installed the application rather than the number of devices using it.

 

What are your thoughts on this?

Thoughts on iOS UDID

There is a lot of buzz with Apple’s rejection of apps accessing UDID API . Let us analyze it.

 

 

What is UDID?

 

UDID is the unique identifier to identify an iOS device uniquely. Apple had exposed an API to access this unique identifier from the start of iOS 2.0 SDK. This made interesting things possible and eventually became a critical API for some of the application’s core functionality. For example. Flurry Analytics, depend on this UDID for reporting number of devices an application is activated. Although, I cannot go through all the list of application using this API, let us do some Impact Analysis and possible problems and their solutions from this move by Apple.

 

When would you use the uniqueIdentifier?

 

I would typically use it in the context where I need to uniquely identify the device in a pool of iOS devices, where this info is send to a centralized place and is used for various purposes. Standalone applications more often does not need this info, unless they have integrated with third party SDK like Flurry, to support non-core features of an application, such as gathering statistics. Therefore, we would not keep this category of applications as these does not have major dependency on UDID.

 

 

What would you do with uniqueIdentifier with a pool of device?

 

Scenario 1:

 

“A scenario could be where the application could act as client and all the instances of the application across the devices are writing some data into the centralized place, could be a Mac or a Centralized Server. In this case the unique identifier would be able to identify the application instance uniquely to resolve the conflicts, say while writing the data to same location.”

 

Syncing

Fig: Scenario 1 showing Application installed in multiple iOS devices syncs with Mac / Server sharing and updating the data

Example: A Simple Notes application where notes are recorded in various iOS devices and then are synchronized with the Mac Application, where the Mac Application acting as a centralized unit.

 

Scenario 2:

 

“Another scenario would be to individually track the number of devices in which the application is activated which helps the sales people to pitch up their sales or we can find them in many of the third party ads which aid in gaining statistics of the application”

 

Example: Analytics SDK like Flurry, InMobi and so on.

 

While the first scenario helps the application in its core functionality, the second scenario is matter of statistics that helps drive the sales. However, accessing a unique identifier of a device without knowledge is a breach of privacy which i believe the motive behind apple deprecating this API.

 

Before digging deep, Let us look at the alternative solution from Apple?

 

Special Considerations:

 

Do not use the uniqueIdentifier property. To create a unique identifier specific to your app, you can call the CFUUIDCreate function to create a UUID, and write it to the defaults database using the NSUserDefaults class.

 

Well, CFUUIDCreate does create the unique identifier, but will that be sufficient to identify the Device uniquely?? Wait, am I sounding wrong! Your read it right.

Although Apple recommend to create unique identifier and store it in defaults, it works fine as long as the app isn’t deleted and re-installed by the user. Since, doing that would delete the defaults database and upon re-installing a fresh unique identifier would be created which defeats our purpose.

 

Let us track back and see what exactly we need

“We need to find a way where an application would identify uniquely against its clone across multiple devices.”

The critical requirement here is not creating a unique identifier, but persisting it from the time application is installed on a device till literally the lifetime of the device and not the application. Uh!!

There are many solutions floating around like the one from crashlytics, where they achieve the persistence by storing the custom unique identifier in the UIPasteboard. However, there are couple of cons here

  • Apple does not guarantee that the Pasteboard data persists permanently across OS upgrades or reboot
  • Any other application can access this data or override them and one need to ensure that this would be in un-readable form for other that the application which created it.

 

My Solution (Intermediate):

The solution is to change the way we modelled our application behavior. For you to understand, let me divide the iOS era into two.

Pre-iCloud & Post-iCloud.

In Pre-iCloud we used to treat each iOS device as a separate one even though they are owned by ( literally under same apple id) single person. This means that an app in iPhone would have different state than the one in iPad, and probably a External Sync would be required to get them into single state.

In Post-iCloud era, as a developer, one should not distinguish between an application installed in two iOS device grouped under single Apple ID, which is strong point behind the Apple’s iCloud – “It Just Works”. i.e the iCloud make sure that all the data and state information would be consisted across the iOS devices grouped under single Apple ID.

With that differentiation, the solution would be:

“Create a unique identifier as suggested by the Apple and  store them in defaults as wells as in iCloud. Check NSUbiquitousKeyValueStore or using this short piece of library from Mugunth Kumar which I liked, for storing into iCloud. So Even if the App is deleted, the same ID would be retrieved back from iCloud, unless your iCloud is reset which accom”

NOTE: We could use a same approach for tracking the number of apps installed with the difference being the count would be number of users installed the application rather than the number of devices using it.

 

What are your thoughts on this?

Pattern Drawing with CGPattern in iOS or Mac

If you are looking for help on how to stroke or fill up a pattern in iOS or Mac OS X, then You have landed at the right place.

NOTE: A reader of this post is assumed to have prior knowledge of custom drawing in iOS’s UIView, CGContext, and Quartz 2D basics

You can find the Code sample from Github

The Sample code demonstrates the following things:

  • Creation of 3 Different kinds of patterns using CGPattern
  • In the Sample, tap “Change Pattern” to switch to next pattern
  • Use the slider, to increase the size of pattern cell

pattern is an image, usually small, used for filling regions by tiling, that is, by placing copies of the pattern side by side like ceramic tiles. Here we see how we can achieve pattern filling in iOS or Mac using CGPattern.

A step by step explanation on usage of CGPatterns

Quartz draw the patterns using cell based drawing technique, where it would provide us the option to draw a single pattern cell in a context, and uses the context to tile across the remaining area evenly.

STEP 1 : Create a CGPattern instance as below

//Pattern Callback methods

// drawPatternCell – callback to draw a single cell

//PatternReleaseInfoCallback – invoked when a pattern is released

CGPatternCallbacks callBack;

callBack.drawPattern = &drawPatternCell;

callBack.releaseInfo = &PatternReleaseInfoCallback;

callBack.version = 0;

 

// param1 – &patters_types[patternCount] – a context info, here which defines which pattern to be drawn


// param2 – rect of a single pattern cell

 

// param3 – transformation matrix

 

// offsetX – a offset or horizontal gap between each cell.. minimum should be width of the cell

 

// offsetY – a offset of vertical gap between each cell. minimum should be heigh of the cell

 

// Style of – how the pattern cell are to be placed where are drawn on a region bigger than the single pattern cell

 

// shouldColor –   a pattern can also be used as a mask, where the color is applied during the actual context where the pattern is drawn. So, literally you have to say true, if the pattern cell can chose its color, or no if the color at its main context is to be chosen

 

// callback – 2 callbacks encapsulated in a struct CGPatterCallbacks

 

_patterns[patternCount] = CGPatternCreate(&patters_types[patternCount], CGRectMake(0.0, 0.0, PATTERN_CELL_WIDTH, PATTERN_CELL_HEIGHT), CGAffineTransformIdentity, PATTERN_CELL_WIDTH, PATTERN_CELL_HEIGHT, kCGPatternTilingConstantSpacing, true, &callBack);

 

 

STEP 2:  (Important) define the drawPattern callback as below. This is the place where you are allowed to draw a single cell of a pattern. The drawing technique of pattern cell is same as one would draw in View’s drawRect method or drawing with any CGBitmapContext.

 

Pattern 1 – Chequered flag –

Chequered Flag Pattern

//Chequered Flag

//Fill the entire background with white color

CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);

CGContextFillRect(context, CGRectMake(0.0, 0.0, cellWidth, cellHeight));

 

CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);

//Fill the top left quarter of the cell with black

CGContextFillRect(context, CGRectMake(0.0, 0.0, cellWidth/2.0, cellHeight/2.0));

 

//Fill the bottom right quarter of the cell with black

CGContextFillRect(context, CGRectMake(cellWidth/2.0, cellHeight/2.0, cellWidth/2.0, cellHeight/2.0));

 

Pattern 2

pattern_2

//http://www.kitchenbeforeandafter.com/wp-content/uploads/2009/05/kitchen-backsplash-tile-patterns2-300×216.gif

//       /

//     /

//  _ /

//   |_|

//  /  

// /    

///      

 

 

//stroke middle square

CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);

CGContextFillRect(context, CGRectMake(0.0, 0.0, cellWidth, cellHeight));

 

 

//stroke diagonal

CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);

CGPoint points [] = {{0.0,0.0}, {cellWidth,cellHeight }, {cellWidth,0.0}, {0.0,cellHeight}};

CGContextStrokeLineSegments(context, points, 4);

 

CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);

int num_of_parts = 8;

float partWitdth = cellWidth / num_of_parts;

CGRect middleSpot = CGRectMake(partWitdth * 3, partWitdth*3, 2* partWitdth, 2*partWitdth);

 

CGContextFillRect(context, middleSpot);


Pattern 3

Circular_pattern

The Elements involve in this pattern are a circle drawn with various transformations

  • Circle
  • Semi-Circle
    • Circle shifted towards left by half the width of the cell
    • Circle shifted towards right by half the width of the cell
    • Circle shifted towards top by half the height of the cell
    • Circle shifted towards bottom by half the height of the cell
  • Arc
    • Circle shifted towards left & top by half the width and half the height of the cell respectively
    • Circle shifted towards left & bottom by half the width and half the height of the cell respectively
    • Circle shifted towards right & top by half the width and half the height of the cell respectively
    • Circle shifted towards right & bottom by half the width and half the height of the cell respectively

You can clone a copy of this Sample project from GitHub

STEP 3: Applying the Pattern.

Finally we would be applying the pattern in drawRect method of BBQuartzView in this sample.

// Drawing code

float alpha = 1;

 

//choose the pattern to be filled based on the currentPattern selected

CGContextRef context = UIGraphicsGetCurrentContext();

CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern (NULL);// 6

CGContextSetFillColorSpace (context, patternSpace);// 7

CGColorSpaceRelease (patternSpace);

 

//set the pattern as the Current Context’s fill pattern

 

//we dont need to set any color, as the pattern cell itself has chosen its own color

CGContextSetFillPattern(context, _patterns[_currentPattern],   &alpha);


//We would be filling the entire portion of this view

CGContextFillRect(context, [self bounds]);

  • Choose the pattern that needs to be applied. In this sample, the pattern is chosen based on the _currentPattern variable value (0- Chequered pattern, 1- Pattern2, 3- Pattern3)
  • Patterns are created at the time of initializing the view. In sample, it is in initWithCoder method of BBQuartzView
  • The drawPattern callback is invoked only when the pattern is all set to be drawn. In my case, it is invoked when CGContextFillRect in the above drawing code snippet. You can use this pattern to fill any shape. The selected pattern would also be reflected while using CGContext drawing API like, CGContextFill variants, CGContextFillPath variants
  • The drawPattern Callback is called only once in its lifetime and for subsequent drawing, the pattern cell buffer would be re-used. So resize the single pattern cell, the patterns are re-created

Here is are the pics how the patterns would look like(captured from sample code).

patterns.png

 

You can clone a copy of this Sample project from GitHub

Hope, you find this piece of info useful. Fill in your comments or queries in below comment’s section. Waiting for you comments.

Happy Coding 🙂

iOS Open Folder Animation

As I was fiddling with my iPad,  Open Folder Animation in iOS caught my attention. After giving it a serious though on how to achieve it, It looked Trivial.

iOS Folder View

 

Let us get together to write a piece of code which does this cool animation.

 

1. Plan

iOS_Folder_View_Plan.png

We can achieve this using 3 Main Layers

1. Layer -1 (Main View) : The Lowest layer contains the main screen which stores the main content

2. Layer -2  (Folder View): The Folder View, which hosts the Folder Icons. Once the Folder Opens, This is the only view which is active accepting the Touch Event. This layer resides above Layer-1

3. Layer-2.1 (Arrow ) : The Arrow, which points to the selected folder. This is movable on x-Axis.

4. Layer-3 (Layer to host Bottom part of Main Content View) : This layer hosts the bottom part of the Main Content View (Layer -1) i.e from point where Folder View ( Layer-2) occupies to the end of the Main Content View. This Layer is place above the Folder View (Layer-2 ) in terms of Level. In Terms of position on screen, this layer is placed just below the Folder View(Layer-2)

 

2. Execution

We can achieve Open Folder Animation effect in 3 Simple Steps

STEP 1: Capture the Main View Content into an image

  • Capturing Main View Content Image can be achieve using renderInContext: API. as shown in code snippet below
  • Clip the Main View into two parts, One part is the visible portion above the Folder view and rest of the image would be hosted in Layer -3. The Trick used in sample code below to avoid the cutting of the image into two parts, is by setting the Layer-3 bounds, such that it should hide the top portion (Part-1) of the Main Content view.

-(void)captureImageFromPointAndSetupMaskView:(CGPoint)selectedFolderPoint

{

UIGraphicsBeginImageContext(mMainBackgroundView.frame.size);

//capture the main content view

[mMainBackgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();

[mBottomPartOfMainBackgroundView setImage:backgroundImage];

//set the bounds such that the we hide the part of the main content image, which is visible just above the Folder View.

//This gets the continuation effect on the image once the folder view appears on screen

[mBottomPartOfMainBackgroundView.superview setBounds:CGRectMake(0.0, selectedFolderPoint.y + mSelectedArrowTipView.frame.size.height, mMainBackgroundView.frame.size.width, mMainBackgroundView.frame.size.height)];


}

 

STEP 2: Layout the Folder View(Layer 2 & 2.1) and Bottom Part Of Main Content View (Layer -3)

  • Folder View and Arrow View are grouped in Single View.
  • Place The Arrow View such that it is right below and to the Center of the Tapped Folder Icon Tapped
  • Place the Folder View Just below Arrow View

-(void)layoutBottomPartOfMainViewRelativeToPointInMainView:(CGPoint)selectedFolderPoint

{

//Place the Folder View Just below Arrow View

CGRect folderViewFrame = [mFolderView frame];

folderViewFrame.origin.y = floorf(selectedFolderPoint.y);

[mFolderView setFrame:folderViewFrame];

//making sure the View which displays bottom part of Main Backgorund View is just below  the Folder View

CGRect maskFrame = mBottomPartOfMainBackgroundView.superview.frame;

maskFrame.origin.y = folderViewFrame.origin.y + mSelectedArrowTipView.frame.size.height;

mBottomPartOfMainBackgroundView.superview.frame = maskFrame;

//Place The Arrow View such that it is right below and to the Center of the Tapped Folder Icon Tapped

[UIView setAnimationsEnabled:NO];

mSelectedArrowTipView.center = CGPointMake(selectedFolderPoint.x, 0.0);

CGRect arrowFrame = mSelectedArrowTipView.frame;

arrowFrame.origin.y = 0.0;

mSelectedArrowTipView.frame = arrowFrame;

 

[UIView setAnimationsEnabled:YES];

}


 

STEP 3- Push The Layer-3 which hosts the other part of the Main Content View

-(void)layoutFinalFrameOfBottomPartOfMainContentView

{

//Push The Layer-3 which hosts the other part of the Main Content View

CGRect maskFrame = mBottomPartOfMainBackgroundView.superview.frame;

maskFrame.origin.y = mFolderView.frame.origin.y + mFolderView.frame.size.height;

mBottomPartOfMainBackgroundView.superview.frame = maskFrame;

}

 

Thats it !! The above 3 steps would be called upon tapping a Folder  Icon as show in below code snippet

-(IBAction)openFolder:(id)sender

{

//get the center point of the tapped folder

CGPoint selectedFolderPoint = CGPointMake([sender center].x, [sender frame].origin.y + [sender frame].size.height);

if( mFolderView.hidden )//if folder is not opened

{

//open folder animation

//STEP 1: Capture the Main View Content into an image

[self captureImageFromPointAndSetupMaskView:selectedFolderPoint];

//STEP 2: Layout the Folder View(Layer 2 & 2.1) and Bottom Part Of Main Content View (Layer -3)

[self layoutBottomPartOfMainViewRelativeToPointInMainView:selectedFolderPoint];

[UIView beginAnimations:@”FolderOpen” context:NULL];

[UIView setAnimationDuration:0.5];

[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

//captures the main background view’s image

mFolderView.hidden=NO;

mBottomPartOfMainBackgroundView.superview.hidden=NO;

//STEP 3- Push The Layer-3 which hosts the other part of the Main Content View

[self layoutFinalFrameOfBottomPartOfMainContentView];

[UIView commitAnimations];

}

else {

//close folder animation

[UIView beginAnimations:@”FolderClose” context:NULL];

[UIView setAnimationDuration:0.5];

[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[UIView setAnimationDidStopSelector:@selector(animation:didFinish:context:)];

[UIView setAnimationDelegate:self];

//restore the layout and hide the folder view after animation

[self closeFolder:selectedFolderPoint];

[UIView commitAnimations];

}

}

 

3. Result

Download the Full Source Code Here : iOS Open Folder Animation.zip

A Video of the Sample Code can be found here: iOS Open Folder Animation Video

[youtube=http://www.youtube.com/watch?v=xBB1humerBw]

If you like this post, Please leave your feedback / comment and Share this (See below for sharing options) to spread to all others who might be interested 🙂

Happy Coding 🙂

Tools helpful in Creating Universal iOS Apps

This post is about Tools [Code Snippets] which I prepared in the process of creating Universal iOS Apps

 

1. Identifying the Device

 

#device DEVICE_IS_IPAD (UIUserInterfaceIdiomiPad == [BBUtilities getUserInterfaceIdiom])

#device DEVICE_IS_IPHONE (UIUserInterfaceIdiomiPhone == [BBUtilities getUserInterfaceIdiom])

 

/*snippet to get user interface idiom*/

static UIUserInterfaceIdiom sDeviceUIIdiom = -1; -(UIUserInterfaceIdiom)getUserInterfaceIdiom

{

 

//We make sure that this method is invoked only once throughout the application lifetime

if( sDeviceUIIdiom == -1)

{

if([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)])

{

sDeviceUIIdiom = [[UIDevice currentDevice] userInterfaceIdiom];

}

}

return sDeviceUIIdiom;

}

 

2. Identifying iPhone 4 Device

 

#define DEVIS_IS_IPHONE4 ([BBUtilities isiPhone4])

 

/*snippet to get whether current device is iPhone 4 or not*/

static UIUserInterfaceIdiom sIsiPhone4 = -1;

 

-(BOOL) isiPhone4

{

//We make sure that this method is invoked only once throughout the application lifetime     i

if( sIsiPhone4 == -1)

{

if([[UIScreen mainScreen] respondsToSelector:@selector(scale)])

{

sIsiPhone4 = [[UIScreen mainScreen] scale] ==2.0 ;

}

else

{

sIsiPhone4=0;

}

}

return sIsiPhone4;

}

Quick Tip : Initializing static variables of a class in Objective C

Initializes the receiver before it’s used (before it receives its first message).

 

+ (void)initialize


Discussion The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.


[Reference : NSObject Class Reference]

You can place all your static member variable initialization code in this method as it guarantees it would be called only once BEFORE any method in that Class is invoked through any of its objects.

Happy Coding 🙂

Search 4 Twitter xAuth and OAuth Samples ENDS here

Hello,

This post is place where you will be re-directed to places where you learn about xAuth and OAuth w.r.t Twitter, Take away Sample code of Twitter Engine supporting xAuth and OAuth both for i[Phone] OS and Mac OS Platforms

  1. Official Twitter API Documentation
  2. xAuth Explained
  3. xAuth for Browserless Token Exchange
  4. OS X 10.5 Demo With Sample Code [See References section in that site]
  5. iPhone xAuth Explained with Sample Code
  6. MGTwitterEngine xAuth Support
  7. Testing TwitPIC OAUTH

 

 

Others

  • iPhone Dev SDK – Twitter Agent
  • SlideShow Presentation
  •  

    Hope this Helps!!

    Have Fun 🙂

    Efficient Memory Handling in UIViewController-Part 2

    In the last post we discussed about the skeleton of a typical UIViewController which handles memory warning efficiently.

    In this post, I will provide you Xcode Templates of a UIViewController, which takes care of all these things we have discussed earlier here, thus making our Lives easier.

    Following steps explain How to add these templates:

  • Navigate to Developer->Platforms->iPhoneOS.platform->Developer->Library->Xcode->File Templates->Cocoa Touch Class Folder
  • KEEP A BACKUP OF "UIViewController subclass" folder
  • Download the zip filehere
  • Unzip the file and replace the “UIViewController subclass” folder with the new one
  •  

    Please note that these templates works for UIViewControllers created with File->New File option

    Thats it, there should be no more hassles with Memory now!!

    Happy Coding!! 🙂

    Efficient Memory Handling in UIViewController-Part 1

    “Low Memory Warning” “Low Memory Crash” are the one’s that frightens iPhone Developers.

    There are many posts in various blogs explaining how to efficiently utilize the available memory, and some have tips in memory management. Most of the Cases, as I have seen, these memory issues arises often due to some negligence/improper handling of resources, esp. images, views, cached data and so on.

    As the saying goes “Prevention is better than cure”, This post FOCUS on

  • Handle memory warnings
  • Safe release of all the views
  • Releasing Data models
  • Releasing Caches
  •  

    in a ViewController, which we use it very often, and to some extent is the root cause of Memory issues we encounter.

    Here is a typical template of UIViewController:

    @interface myViewController(Private)

    -(void)releaseAllViews;

    -(void)customInitialisation; @end

     

     

    @implementation myViewController(Private)

    -(void)releaseAllViews;

    {

    // release all views this controller own

    }

     

    -(void)customInitialisation {

    // do the initialization of class variables here..

    should act as constructor for this class

    }

    @end

    STEP 1: A method, name it as releaseAllViews , which is responsible to release all & ONLY the Views, referenced either by IBOutlets, or view elements created in viewDidLoad method or elsewhere in the class.


    @implementation myViewController

    -(id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundle

    {

    //call super method

    self =[super initWithNibName:nibName bundle:nibBundle];

    if(self)

    {

    [self customInitialisation];

    }

    return self;

    }

    //Invoked when the class is instantiated in XIB

    -(id)initWithCoder:(NSCoder*)aDecoder

    {

    self = [super initWithCoder:aDecoder];

    if( self)

    {

    [self customInitialisation];

    }

    return self;

    }

    STEP 2: I would have a method which initializes all my class variables, also acts as a constructor, and this is typically invoked by “initWithNibName” (creating view controller programmatically) and “initWithCoder” (in case view controller is created in XIB).


    -(void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning]

    //Release all your caches like say Image Cache, any File Data etc.

    }

    STEP 3: didReceiveMemoryWarning is invoked at various times at different Memory Levels of the application. Make sure you release all the heavy objects like Images, Data and so on and don’t forget to make sure that these cached data should be able to restore their state in future, without having any impact on the application.


    -(void)viewDidUnload {

    [super viewDidUnload];

    //release all your views, which the controller owns, here

    [self releaseAllViews];

    }

    STEP 4: viewDidUnload is invoked when the system identifies that your view is no longer visible on screen, when the memory warning notification arrives. Make sure you call releaseAllViews to relinquish the ownership of the views the controller owns.

     

    -(void)dealloc {

    //remove as Observer from NotificationCenter, if this class has registered for any notifications

    [[NSNotificationCentre defaultCenter] removeObserver:self];

    [self releaseAllViews];

    //release all you member variables and appropriate caches

    }

    STEP 5: Release all your views, data cache, member variables, and remove as observer, incase the controller is registered to any of the notifications.


    In Part-2 of this Post, I will provide Xcode Templates for UIViewController class which includes all the above steps.

    Here I Leave this links which provides you tips in Memory Management in iPhone OS

  • iPhone Memory Management
  • 10 iPhone Memory Management Tips
  • UPDATE:

    One way to test the Memory Warning scenarios, one would use the Hardware -> Simulate Memory Warning menu in iOS Simulator. But, For some lazy people like me or for those smart people who wants the application to be periodically check for the memory warning at the background, I found a Code snippet from iDevRecipes

    All you need to do is to place the below code in your App Delegate

    #if TARGET_IPHONE_SIMULATOR

    – (void)simulateMemoryWarning

    {

    CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)@”UISimulatedMemoryWarningNotification”, NULL, NULL, true);

    }

    #endif

     

    Place the below code in your application:didFinishLaunchingWithOptions: method (preferably in the first line of this method)

    #if TARGET_IPHONE_SIMULATOR

    //lets call the simulate warning every 5 minutes (300 seconds)

    [NSTimer scheduledTimerWithTimeInterval:300.0 target:self selector:@selector(simulateMemoryWarning) userInfo:nil repeats:YES];

    #endif

    NOTE: The above code snippets has to be placed between TARGET_IPHONE_SIMULATIOR  and #endif to make sure that this code is only executed in the Simulator, as we are using thing which are undocumented and if used in App Store builds, it would violate Apple SDK policy and application could be rejected.