Thursday 25 July 2013

How to Get a List of all Properties that are declared in an Interface or Class in Objective C at RunTime:


-(NSArray*)listAllPropertiesInClassName:(NSString *)className
{
    Class classRef = NSClassFromString(className);
    
    unsigned int propCount;
    
    objc_property_t  *properties = class_copyPropertyList(classRef, &propCount);
    NSMutableArray *arr = [NSMutableArray array];
    for (int i=0; i < propCount; i++)
    {
        objc_property_t property = properties[i];
        
        //Get Property Name
        const char *propertyName = property_getName(property);
        if(propertyName)
        {
            //Get property Type
            const char *propertyType = getPropertyType(property);
            
            NSString *propName = [NSString stringWithUTF8String:propertyName];
            NSString *propType = [NSString stringWithUTF8String:propertyType];
            NSLog(@"%@==%@", propName, propType);
            NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:propName,  @"ProperyName", propType, @"PropertyType",nil];                                

            [arr addObject:dic];
        }
    }
    
    return (NSArray*)arr;
}


static const char *getPropertyType(objc_property_t property)
{
    const char *attributes = property_getAttributes(property);
    char buffer[1 + strlen(attributes)];
    strcpy(buffer, attributes);
    char *state = buffer, *attribute;
    while ((attribute = strsep(&state, ",")) != NULL) {
        if (attribute[0] == 'T' && attribute[1] != '@') {
            // it's a C primitive type:
            /*
               you will get "i", "l", "I", struct, etc.
              for int "i", long "l", unsigned "I", struct, etc.
             */
            NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
        else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
            // It is an Objective-C id Type object
            return "id";
        }
        else if (attribute[0] == 'T' && attribute[1] == '@') {
            // Its anothoer Objective C Type Object:
            NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
            return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding];
        }
    }
    return "";
}













Friday 18 January 2013

How to Create an Image Gallery View With UIScrollView that allows Paging and Zooming.

First create an Interface with name RootViewController.

In RootViewController.h file write this:

@interface RootViewController : UIViewController <UIScrollViewDelegate> {
    UIScrollView *imageScrollView;
    UIImageView *imageView;
   
    int pageNumber;
    CGRect  viewFrame;
}

@property (nonatomic, retain) IBOutlet UIScrollView *imageScrollView;
@property (nonatomic, retain) IBOutlet UIImageView *imageView;

- (id)initWithPageNumber:(int)page andFrame:(CGRect)aFrame;

@end


In RootViewControlle.m file write this:

#import "RootViewController.h"

#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5


@interface RootViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
@end


@implementation RootViewController

@synthesize imageScrollView, imageView;

// load the view nib and initialize the pageNumber ivar
- (id)initWithPageNumber:(int)page andFrame:(CGRect)aFrame
{
    if (self = [super initWithNibName:@"RootViewController" bundle:nil])
    {
        pageNumber = page;
        viewFrame = aFrame;
        self.view.frame = viewFrame;
    }
    return self;
}


- (void)loadView {
    [super loadView];
   
    self.view.frame = viewFrame;
    imageScrollView.contentSize = CGSizeMake(0, viewFrame.size.height);
   
    //self.view.backgroundColor=[UIColor redColor];
    // set the tag for the image view
    [imageView setTag:ZOOM_VIEW_TAG];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.frame = CGRectMake(0, 0, viewFrame.size.width, viewFrame.size.height);
    //imageView.frame = CGRectMake(0, 0, 1730, 2430);
    imageScrollView.contentMode = UIViewContentModeScaleAspectFit;
    imageScrollView.frame = CGRectMake(0, 0, viewFrame.size.width, viewFrame.size.height);
   
    // add gesture recognizers to the image view
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
    UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];
   
    [doubleTap setNumberOfTapsRequired:2];
    [twoFingerTap setNumberOfTouchesRequired:2];
   
    [imageView addGestureRecognizer:singleTap];
    [imageView addGestureRecognizer:doubleTap];
    [imageView addGestureRecognizer:twoFingerTap];
   
    [singleTap release];
    [doubleTap release];
    [twoFingerTap release];
   
    // calculate minimum scale to perfectly fit image width, and begin at that scale
    float minimumScale = [imageScrollView frame].size.width  / [imageView frame].size.width;
    [imageScrollView setMinimumZoomScale:minimumScale];
    [imageScrollView setZoomScale:minimumScale];
}


- (void)viewDidUnload {
    self.imageScrollView = nil;
    self.imageView = nil;
   
}


- (void)dealloc {
    [imageScrollView release];
    [imageView release];
    [super dealloc];
}

#pragma mark UIScrollViewDelegate methods

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}

/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary      */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    [scrollView setZoomScale:scale+0.01 animated:NO];
    [scrollView setZoomScale:scale animated:NO];
}

#pragma mark TapDetectingImageViewDelegate methods

- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
    // single tap does nothing for now
}

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
    // double tap zooms in
    float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}

- (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer {
   
    // two-finger tap zooms out
    float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}

#pragma mark Utility methods

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
   
    CGRect zoomRect;
   
    // the zoom rect is in the content view's coordinates.
    //    At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
    //    As the zoom scale decreases, so more content is visible, the size of the rect grows.
    zoomRect.size.height = [imageScrollView frame].size.height / scale;
    zoomRect.size.width  = [imageScrollView frame].size.width  / scale;
   
    // choose an origin so as to get the right center.
    zoomRect.origin.x    = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y    = center.y - (zoomRect.size.height / 2.0);
   
    return zoomRect;
}

@end





Now  Create a main class where you want to Show all Images with Paging and Zooming feature:


Create a new Interface with name ImageGalleryViewC

In ImageGalleryViewC.h file write this:

#import <UIKit/UIKit.h>

@class RootViewController;

@interface ImageGalleryViewC : UIViewController
{
    RootViewController  *objRoot;
    NSMutableArray  *imageArray;
    NSInteger       currentPage;
 }

@property NSInteger       currentPage;
@property (retain, nonatomic) IBOutlet UIScrollView *imageGalleryScroll;

- (id)initWithImageArray:(NSMutableArray*) aArray;

@end



and In ImageGalleryView.m file write this:

 #import "ImageGalleryViewC.h"
#import "RootViewController.h"

@interface ImageGalleryViewC ()
 //Write some utility methods if needed
@end

@implementation ImageGalleryViewC
@synthesize imageGalleryScroll;
@synthesize currentPage;
- (id)initWithImageArray:(NSMutableArray*) aArray
{
    self = [super initWithNibName:@"ImageGalleryViewC" bundle:nil];
    if (self) {
        // Custom initialization
        ReleaseObject(imageArray);
        imageArray = [[NSMutableArray alloc] initWithArray:aArray];
      
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
  
    self.navigationItem.hidesBackButton=YES;
     
 
    [self createButtonOnScroll];
}



-(void) createButtonOnScroll
{
    // Buttons on scroll with jar images
    int xC = 0.0, yC = 5.0;
    for (int i=0; i<[imageArray count]; i++)
    {
      
        int aTag = i;
        CGRect frame = CGRectMake(xC, 0, 320, 416);
      
        UIImage *aImage = [imageArray objectAtIndex:i]; //[UIImage imageNamed:[imageArray objectAtIndex:aTag]];
        if(aImage)
        {
            objRoot = [[RootViewController alloc] initWithPageNumber:aTag andFrame:frame];
            objRoot.view.contentMode = UIViewContentModeScaleAspectFit;
            objRoot.imageView.image = aImage;
            objRoot.imageView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
            objRoot.imageScrollView.minimumZoomScale = 1;
            objRoot.imageScrollView.contentSize = CGSizeMake(0, frame.size.height);
            objRoot.imageScrollView.maximumZoomScale = 3;
            [imageGalleryScroll addSubview:objRoot.view];
        }
        xC = xC + 320 + 5.0;
        imageGalleryScroll.contentSize = CGSizeMake(xC, yC);  
    }
  
    if(self.currentPage>0)
    {
        CGFloat xC =  currentPage*320.0;
        CGRect visibleRect=CGRectMake(xC, 0, 320, 416);
        [imageGalleryScroll scrollRectToVisible:visibleRect animated:NO];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)sender
{
    CGFloat pageWidth = imageGalleryScroll.frame.size.width;
    float xOff = imageGalleryScroll.contentOffset.x;
    float frameW = abs (((int)xOff) / ((int)pageWidth));
    float diff = abs ((frameW * pageWidth) - xOff);
    if (diff < 0.00001)
    {
    }
  
    // Calculate current page ..
    //currentPage = floor((imageGalleryScroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{  
}


- (void)viewDidUnload
{
    objRoot = nil;
    [self setImageGalleryScroll:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)dealloc {
  
    [objRoot release];
    objRoot = nil;
    [imageArray release];
    [imageGalleryScroll release];
    [super dealloc];
}
@end



Now from where you want to show all Images with scrolling and zooming write this:

 // Add your Image to an Array and Pass it to the ImageGalleryViewC class. Also set current Page Number ie from which array index or Page number images appears .

-(void) goToScrollZoom
{
//Here I have take imageArray that contains UIImage objects
    if([imageArray count]>0)
    {
        ImageGalleryViewC *obj = [[ImageGalleryViewC alloc] initWithImageArray:imageArray];
        obj.currentPage=0;
        [self.navigationController pushViewController:obj animated:YES];
        [obj release];
 
    }
    else
    {
        NSLog(@"No Image");
    }
}