""

Tag Archive: objective-c

UIScrollView Case: Who are they?

Found something of interest, I noticed it during the use of UIScrollView. I was adding multiple UIImageView to scrollview dynamically, at some point later I was iterating through subviews of scrollview and doing some manipulation stuff. I was getting weird results. I printed a log for total count of scrollview’s subviews, found that total count was two more extra than I was supposed to have. I was adding five UIImageView to UIScrollView and total count of subview array was 7. Going more deeper with log prints, found that those two extra views were UIImageView [sighs] I was wondering how was those two extra UIImageView getting added to UIScrollView?

I removed all subviews from UIScrollView before adding my other UIImageView/s. This trick worked just partially. There were no extra two UIImageView and I was not getting any weird result from my processing code. I was thinking if it was some bug with UIScrollView but I was so wrong. I looked more closer to the output and found that two scroll indicators (horizontal and vertical) are missing :P, then it struck me that those two extra UIImageView were actually indicators. I changed my processing/iteration code instead of just plainly removing all subviews. All was well in the end.

Happy Valentines Day ๐Ÿ™‚

instagram

Posting photo to instagram from your app could be tricky if some basic things isn’t handled properly. I’l be talking about small things where i made mistake. We cannot post image directly to instagram from app/code. Instead we have to use Documentation Interaction API, UIDocumentInteractionController and URL Schemes to open photo on instagram and share/post from there. Here control also won’t be returned back to your app.

The identifier for UTI is “com.instagram.photo”. Before triggering instagram to open your photo, always check if instagram is available on your device:

NSURL *instagramURL = [NSURL URLWithString:@"instagram://location?id=1"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
    //handle
}

Here is the code to open photo on instagram app

-(void) openFileOnInstagram{
	CGRect rect = CGRectMake(0 ,0 , 0, 0);
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIGraphicsEndImageContext();
    NSString  *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:@"InstagramPost.app/no_image.ig"];
    
    NSURL *imageAttachFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:@"file://%@", imagePath]];
    
    self.dic.UTI = @"com.instagram.photo";
    self.dic = [self setupControllerWithURL:imageAttachFile usingDelegate:self];
    self.dic=[UIDocumentInteractionController interactionControllerWithURL:imageAttachFile];
    [self.dic presentOpenInMenuFromRect: rect inView: self.view animated: YES ];
}
- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL*) fileURL usingDelegate: (id ) interactionDelegate {
    UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL: fileURL];
    interactionController.delegate = interactionDelegate;
    return interactionController;
}

First mistake i did was with getting filepath of my image. My failed attempt was:

NSString  *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Document/no_image.ig"];

So i was assuming that device will have same path structure as my macbook have:

/Users/gaanza/Library/Application Support/iPhone Simulator/6.1/Applications/Documents/no_image.ig

It was my mistake, path in device is like this:

/var/mobile/Applications/40591A2D-B464-49FF-8BA2-64CC4886F7A0/InstagramPost.app/no_image.ig

I simply replaced “Documents” with “InstagramPost.app”, InstagramPost is a name of my application so you have to provide yours with .app extension.

Second mistake i did was with file extension of image. You cannot trigger the instagram app to open if we don’t use “.ig” extension, so save the image in PNG/JPEG format but with .ig extension.

Third mistake i did was with not saving file with .ig extension, i was saving file with png extension but using .ig on code call, so this also won’t work :P, you have to save your file in png/jpeg format but with .ig extension.

Please also check instagram reference page.

‘&’, what a flow breaker. When you send a string data that contains ‘&’ in it to a server then what do you notice? In my case server received only data preceding ‘&’. What happened to the other data ? Well it seemed that data from ‘&’ onwards got cut away. In my previous post i mentioned how to encode string that contains spaces in it. I tried same encoding in this case and it didn’t work. I found a working solution, courtesy stackoverflow.com

I added a new routine function to our NSString via category, whose task was to encode the string so that special characters be handled gracefuly.

@interface NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding;
@end
@implementation NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding {
    CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding);
    NSString *rfcEscaped = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                NULL, 
                                                (CFStringRef)self,
                                                NULL, 
                                                (CFStringRef)@";/?:@&=$+{}<>,",
                                                cfEncoding);
    return rfcEscaped;
}
@end

Everthing was smooth after that, just using above category to encode my input:

NSString *postDataString = [inputText stringByAddingRFC3875PercentEscapesUsingEncoding: NSUTF8StringEncoding];

Don’t forget to import:

#import "NSString+RFC3875.h"

Thanks.

Clear all: Core Data

Core Data is really super awesome and comes in a handy on almost my all of projects. I am posting quick code for deleting all your rows from entity. This code might do the job when you are in need of clearing all data.

- (void) clearAllRecords{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Chat" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    
    NSError *error;
    NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
    fetchRequest = nil;
    
    
    for (NSManagedObject *managedObject in items) {
        [managedObjectContext deleteObject:managedObject];
    }
    if (![managedObjectContext save:&error]) {
    }    
}

Why flush ?

Interesting stuff i came to know about which i was unaware of. This post is more of a discussion on the problem. I haven’t understood the solution and so would request you to have a say.

I have done json parsing numerous times. I can tell if json is valid or not by looking it. I was using google-gson for android application and its awesome. Application was supported by php web service. The solution that fixed the problem is related to php and i am not a php developer and don’t have that much inner understanding of it. It was regular json parsing routine. Application just crashed when gson was parsing the json response from php service.

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 2

From error I understood the reason but that was not it. I was very confident that something else was the problem because json response was perfect. I wrote quick objective-c routine(SBJSON) to parse same json response and it worked there. I even did validation on jsonlint.com
After doing bit of research I came across a working solution. In php before sending response I had to put this:

ob_clean();
echo header('Content-Type: application/json');

I checked the php manual to understand what those lines means, header function was quite obvious. According to manual, ob_clean:

This function discards the contents of the output buffer.

Now I have no idea why discarding the contents of output buffer was working. This was the case for android, I mean in iphone I didn’t need ob_clean. I am still looking for the explanation on this.

Affair with core data: IPhone

I have lots of stuff to write upon. Problems that I have faced and how I have solved it. For this post i have picked up coredata topic. Core Data is a persistence framework. I would love to give one beginner’s tutorial on coredata but this post will be about the pitfall that most of the beginners falls into and i have tasted it. I assume that you have already used Core data with your project. I would refer this tutorial for quick basic walkthorough. There was a chat application where i had to manange chat history. I was using Core Data for saving all chat messages. This is how my rough sketch of chat entity looks like:

#import 
#import 


@interface Chat : NSManagedObject

@property (nonatomic, retain) NSNumber * chat_id;
@property (nonatomic, retain) NSString * message;
@property (nonatomic, retain) NSNumber * timestamp;
@property (nonatomic, retain) NSString * username;

@end

Chat entity has four attributes. Everything was setup properly. When I ran the program, an error occured:

Failed to call designated initializer on NSManagedObject

I was initializing my chat like this:

Chat *chat = [[Chat alloc] init];

According to error init wasn’t appropiate initializer. I checked the class reference docs and according to it:

if you instantiate a managed object directly, you must call the designated initializer (initWithEntity:insertIntoManagedObjectContext:)

My chat implementation file looks like this:

#import "Chat.h"

@implementation Chat

@dynamic chat_id;
@dynamic message;
@dynamic timestamp;
@dynamic username;

@end

I looked for initWithEntity in refrence doc and it says:

You are discouraged from overriding this methodโ€”you should instead override awakeFromInsert and/or awakeFromFetch (if there is logic common to these methods, it should be factored into a third method which is invoked from both). If you do perform custom initialization in this method, you may cause problems with undo and redo operations.

Then I checked for NSEntityDescription in reference because initWithEntity was taking it as a parameter:

- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context

I was going through all the methods in class reference and there I found one method:

+ (id)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context

According to reference docs:

Creates, configures, and returns an instance of the class for the entity with a given name.
Returns a new, autoreleased, fully configured instance of the class for the entity named entityName. The instance has its entity description set and is inserted it into context.

From reading those, I changed my initializer and new code looked like this:

Chat *chat = (Chat *)[NSEntityDescription insertNewObjectForEntityForName:@"Chat" inManagedObjectContext:managedObjectContext];

This worked smoothly for me.

Reverse geocoding: IPhone

There will be a time when we would have to get the address of location from lattitude and longitude value. This concept is called Reverse geocoding. Well as usual this post is again about the mistake that I made and the solution that I got for it. Apple has introduced CLGeocoder class from ios 5.0 onwards. According to reference doc:

The CLGeocoder class provides services for converting between a coordinate (specified as a latitude and longitude) and the user-friendly representation of that coordinate.

For reverse geocoding there is a method where you provide location and it will convert:

- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler

Now I’ll start the boring tale of my mistake. If you see the reverseGeocodeLocation, it takes CLLocation as parameter which represent location data that also consist our latitude and longitude information. Now I had just lat and long value that I was receiving from my json object. So I had a simple requirement to parse those values and convert them to meaningful street address. I have a float values of lat and long, reverseGeocodeLocation takes CLLocation as parameter. I need to somehow convert float values to CLLocation or make CLLocation from my float values. So here is what I did first:

CLLocation *coordinates = [[CLLocation alloc]init];
coordinates.coordinate.latitude = [@"41.409261" floatValue];
coordinates.coordinate.longitude = [@"2.163517" floatValue];

But there lies a big problem. The thing is coordinate property(CLLocationCoordinate2D) is read only so I cannot assign my float values to respective lat and long directly. So now what I had to do was initialize CLLocation from CLLocationCoordinate2D which is a structure. This is how I represented my lat and long with CLLocationCoordinate2D:

CLLocationCoordinate2D coordinate;
coordinate.latitude = [@"41.409261" floatValue];
coordinate.longitude = [@"2.163517" floatValue];

Initialize CLLocation with newly created coordinate:

CLLocation *currentLocation = [[CLLocation alloc]initWithCoordinate:coordinate altitude:1 horizontalAccuracy:1 verticalAccuracy:-1 timestamp:[NSDate date]];

My location is ready now and I just pass it to reverseGeocodeLocation and on complete handler I receive my meaningful street address:

[self.geocoder reverseGeocodeLocation: currentLocation completionHandler:
     ^(NSArray *placemarks, NSError *error) {      
         //Get nearby address
         CLPlacemark *placemark = [placemarks objectAtIndex:0];
         
         NSString *addressName = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];

         NSLog(@"My location name is %@",addressName);
         }];

Another not so interesting tale…Lots of thing you learn from mistakes and lots of knowledge you gain. When I started iphone development, I chose non-ARC way to know and learn the concepts of memory management. It was fun and good experience apart from objective-c being ugly(syntax). Whenever there was memory leak and any crash due to low on memory, it used to give me dose of excitement, debugging tits and bits had been good learning experience. It has been good journey for me. I started ARC later and life’s been good and easy for me.

I was trying to do some experiment with one iphone project based on facebook. I remember when my project was already using SBJSON for parsing json, then later when I had to integrate facebook to my project and I had lots of sbjson conflict errors. It seemed facebook was using another version of SBJSON library, so I had to remove my SBJSON and integrate the library that facebook was using. I found it in github facebook project. So that was another experience and at that time I was working on non-arc environment. So recently I tried to do something to see the result on what would happen if I do along these lines. So I created ARC based project and integrated facebook sdk 3.1 and then I integarted that same SBJSON that I had integrated on past to avoid conflict. This time my project and facebook sdk was ARC based and SBJSON was non-arc. So I decided to see the result by changing all lines of releasing memory to setting them to nil on the source codes of SBJSON. As release call will throw syntax error in arc environment so I was replacing them by nil assignment. Why nil assignment ? Well I wanted to see if there is any harm with that?

Everthing was fine. I was making rest call to my web services and parsing json. Then moment came and one crash sting me like a bee. So my crash error was this:

MyApp(2121,0xb0185000) malloc: *** error for object 0x1068310: double free
*** set a breakpoint in malloc_error_break to debug

From the description it was clear that I was trying to release already released memory. But big question was WHERE? Then as error asked me to do, I did set a breakpoint on malloc_error_break but still it was not enough for me. I need more clear error log, so I enabled zombies and trust me!! at this point of time zombies is your best friend. So as I knew I got a very clear picture, yeah NAKED CLEAR

[NSDecimalNumber retain]: message sent to deallocated instance

So it seems my decimal number has already been released before retain was called. Now another big question was NSDecimalNumber ????

I decided to play with parsing json because this crash was coming only parsing certain type of value. So I need to dig up more deeper. I was parsing every kind of value and trying to replicate the crash. Then crash happened and I had a big stupid grin on my face. I again tested parsing same kind of data and crash happened again and my stupid grin went wider. So crash was happening when I was parsing numbers. Something like this {“answer”:5} Now time was to follow the trails. So I started from [responseString JSONValue] , responseString is string and JSONValue is a method added via category. So I opened NSSting+SBJSON.m file and looked for the function. Now within function SBJsonParser was being used to parse the string, so I opened SBJsonParser.m file and searched for NSDecimalNumber because my best friend zombie told me I had a memory boom with decimal numbers. I got goosebumps when I found the stupid but very critical mistake I had made and it was the culprit of existence of this post that you are reading now. ๐Ÿ˜€ So my mistake happend on this method

(BOOL)scanNumber:(NSNumber **)o

See this is why I love zombie as it told me the problem was with decimalnumber and see where did I end up with. Yeah scanNumber! ๐Ÿ˜› Now time for showing my mistake, but I would also like you to check the source code and look by yourself and I guess you already have SBJSON library.

@autoreleasepool {
    id str = [[NSString alloc] initWithBytesNoCopy:(char*)ns
                                            length:c - ns
                                          encoding:NSUTF8StringEncoding
                                      freeWhenDone:NO];

    if (str && (*o = [NSDecimalNumber decimalNumberWithString:str]))
        return YES;
}

and original lines of code was like this:

id str = [[NSString alloc] initWithBytesNoCopy:(char*)ns
                                            length:c - ns
                                          encoding:NSUTF8StringEncoding
                                      freeWhenDone:NO];
[str autorelease];
if (str && (*o = [NSDecimalNumber decimalNumberWithString:str]))
    return YES;

My mistake was that I used @autoreleasepool block because in hurry I couldn’t see that in original source code NSAutoreleasePool was not used and when I was using @autoreleasepool then all the autoreleased object was getting released after finish of the block. In my case decimalNumberWithString got released after releasepool block was finished and YES carriage was return. So later *o was pointing to deallocated memory and my app was crashing whenever I was parsing numbers.

But this was worth it and lots of fun debugging this crash. Also I am posting screenshot of enabling zombie objects

initialize that view: Storyboard

This post is about a problem that is basic but starters are likely to fall into if not careful. When using a tableview, there will be a time when there will be a need to use custom table cell class. There will be outlets defined for views inside cell. Now there will be a time for need of initializing views. Now there is a chance of falling into one common problem when trying to initialize views of cell that is being loaded from Storyboard. What could be happening is stuff doesn’t get initialized when cell is created. Only one thing comes to mind is that init is not getting called at all. So lets see how init method looks like when xcode creates UITableViewCell subclass for us:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

Yeah so we have initwithstyle for intializing our stuff. But when we write any initializing code then it doesn’t work. Thing is that when your views are being loaded from storyboard then initWithCoder is used not initwithstyle. So what we need is this:

- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Initialization code
    }
    return self;
}

Thanks.

That’s my unique identity: IPhone

Recently i had a requirement to send unique identifier for device to my web service. I was going through the documentation of UIDevice class at apple’s developers site. Apple has depreceated the “uniqueIdentifier” property from IOS 5 onwards. My application project traget was IOS 5 onwards. I did a search on alternatives on web and forums, got many options. In this post i am not giving any tutorial, just about what option i chose and what silly mistake i made while integrating it into my project. One good option was recommended to me by many sources and after using it i would myself recommend this to others. I read Unique Identifier Is Dead, Long Live Unique Identifier”, author has stated the recommendation provided by apple, its pros and cons and better way to use them. Author has implemented the class that encapsulated all the work of getting and storing identifier. So i would recommend to read that blog.

It was very simple to integrate into project, just need to copy and reference one header and implementation file. So now time to state what silly mistake i made, after integrating those implementation files, i ran my project and got so many errors. I am posting some of errors below:

Undefined symbols for architecture i386:
“_SecItemUpdate”, referenced from:
+[BPXLUUIDHandler storeUUID:] in BPXLUUIDHandler.o
“_SecItemAdd”, referenced from:
+[BPXLUUIDHandler storeUUID:] in BPXLUUIDHandler.o
“_SecItemCopyMatching”, referenced from:
+[BPXLUUIDHandler UUID] in BPXLUUIDHandler.o
+[BPXLUUIDHandler reset] in BPXLUUIDHandler.o
“_SecItemDelete”, referenced from:
+[BPXLUUIDHandler reset] in BPXLUUIDHandler.o
“_kSecAttrAccount”, referenced from:
_CreateKeychainQueryDictionary in BPXLUUIDHandler.o
“_kSecAttrService”, referenced from:
_CreateKeychainQueryDictionary in BPXLUUIDHandler.o
“_kSecClass”, referenced from:
_CreateKeychainQueryDictionary in BPXLUUIDHandler.o
“_kSecClassGenericPassword”, referenced from:
_CreateKeychainQueryDictionary in BPXLUUIDHandler.o
“_kSecReturnAttributes”, referenced from:
+[BPXLUUIDHandler UUID] in BPXLUUIDHandler.o
+[BPXLUUIDHandler reset] in BPXLUUIDHandler.o
“_kSecReturnData”, referenced from:
+[BPXLUUIDHandler UUID] in BPXLUUIDHandler.o
“_kSecValueData”, referenced from:
+[BPXLUUIDHandler storeUUID:] in BPXLUUIDHandler.o

So it seemed “SecItemAdd”, “SecItemUpdate” etc were not being processed or recognized. After experiencing similar “Undefined symbols for architecture i386” errors many times in past, i can tell what could be the primary reason. The most primary cause could be that appropriate framework hasn’t been linked up to target. So my first job was to search on SecItemAdd and all above stuff and look for framework they belong to. It seemed that they belong to security farmework. So once again i happened to forgot including the framework. Once everything goes fine then just do:

import "BPXLUUIDHandler.h"

and

[BPXLUUIDHandler UUID]

So anyone who happens to fall into this pitfall like me, don’t forget to link “Security.framework” to your project target.

Thanks.