Showing posts with label Objective-C. Show all posts
Showing posts with label Objective-C. Show all posts

Friday, February 10, 2012

Lesson Learnt from iPhone Development

Last week was quite tough for me dealing with the project I was working on. The project was quite simple actually. It was released on App Store and the client decided to make minor changes to the application. I made the requested changes and the application was resubmitted to the App Store. Then we got Apple's email saying that the app was rejected. The email said:

"We found that your app does not follow the iOS Data Storage Guidelines https://developer.apple.com/icloud/documentation/data-storage/, which is not in compliance with the App Store Review Guidelines https://developer.apple.com/appstore/resources/approval/guidelines.html#functionality.

In particular, we found that the app is storing too much data, which can be recreated, in the incorrect location."

I have to admit that I don't visit Apple Developer Portal regularly to check if there are any update on their Developer Guidelines. So the thing is our data was stored in document folder and I need to move application's data to library/cache folder for prior iOS 5.0.1 and setting "do not back up" attribute for iOS 5.0.1 above. Thanks to iCloud, iSun, iMoon and whatever it is on the sky above.

There was another thing screwed me, the core data. Core data needs versioning if you happen to change the data structure like adding columns, changing relationships, renaming tables, etc. Apple has documentation about it but don't expect everything goes smoothly as there are many things undocumented. If you find any errors, stackoverflow.com is your help.

Last thing is, I think it is always a good idea to introduce a User Default value that holds your application version early when you start developing your app. It is useful if you need to trace what application version installed on a device. Usually you need this when there are any update for your app.

Wednesday, April 6, 2011

Encode URL and Decode Google Translate's Response in Objective C

I've been working on a project that needs to get a translation from google translate web service. There are some codes in google code that can help you doing this. However, I found some problems regarding string encoding.

I used to encode the string with NSUTF8StringEncoding, but it doesn't encode character & into %26 or + into %2B so I had to encode it manually.

NSString* urlEncodedText = [text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
urlEncodedText = [CommonUtil encodeCharacters:urlEncodedText];

+ (NSString*) encodeCharacters:(NSString*) string {
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"%26" forKey:@"&"];
[dict setObject:@"%2B" forKey:@"+"];

NSArray* keys = [dict allKeys];
for (int i = 0; i < [keys count]; i++) {
NSString* key = [keys objectAtIndex:i];
string = [string stringByReplacingOccurrencesOfString:key withString:[dict objectForKey:key]];
}

return string;
}

The same thing happens when I get the translation. I get &amp; instead of &, &quot; instead of " (double quote), etc so I had to manually decode it.

+ (NSString *) decodeCharacters:(NSString *)string {
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"&" forKey:@"&amp;"];
[dict setObject:@"\"" forKey:@"
&quot;"];
[dict setObject:@"'" forKey:@"
&#39;"];
[dict setObject:@"<" forKey:@"
&lt;"];
[dict setObject:@">" forKey:@"
&gt;"];

NSArray* keys = [dict allKeys];
for (int i = 0; i < [keys count]; i++) {
NSString* key = [keys objectAtIndex:i];
string = [string stringByReplacingOccurrencesOfString:key withString:[dict objectForKey:key]];
}

return string;
}

Monday, September 13, 2010

nil, NULL, and release

Just a quick note about how to check whether an object is null or not in Objective-C. In java, it is easy to do that through 'null' keyword. While in Objective-C, there are two keywords, 'NULL' and 'nil', to deal with that action. What is the difference? NOTHING. Both keywords point to __DARWIN_NULL which is defined as : #define NULL ((void *)0) . It means, they point to address 0 in memory.

When we release an object using [object release], don't forget to set it to nil or NULL because when we compare it in 'if' statement, it won't be true because it is still pointing to its old address.

For example:

MyViewController c = [[MyViewController alloc] init];
[c release];

If we compare it in 'if' statement if(c), the statement will return true because the pointer is still pointing to its address even tough we have released it before. We need to set it to nil or NULL c = nil to make it point to address 0. After we do that, if(c) will return 0, which is false in C.

Tuesday, August 3, 2010

Objective-C Event Handling Overview

Objective-C manages user input event as responder chain. It goes backward up from the first responder (object that user is interacting with) until application delegate at the top most.



UIResponder contains methods to catch events. When we create a view as subclass of UIView, it inherits methods to access the events.



We can handle the events by implementing those methods. Following MVC pattern, usually we will delegate it to a controller.

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[controller doSomething];
}

UIControl Target Action Events

When we work with events, the UIResponder class holds many of the methods critical for event control. Similarly, we can access a lot of the methods important to SDK controls through the UIControl class. UIControl is a child of UIView (and thus UIResponder).

The UIControl object introduces a whole new event-handling infrastructure that takes touch events and (eventually) converts them into simple actions, without having to worry about the specifics of how a user accessed control.



When a touch event arrives at a UIControl object (via normal dispatching along the responder chain), the control does something unique. Inside the standard UIResponder methods (such as touchesBegan:withEvent:), a UIControl object turns standard touch events into special control events. These control events broadly describe how the user has interacted with the controls rather than just recording gestures. For example, they might report that a button has been pushed or a slider moved.

Once a standard event has been turned into a control event, a sequence of additional methods is called. First, the UIControl object calls sendActionsForControlEvents:. That in turn breaks down the events it’s been sent and calls sendAction:to:forEvent:, once per event. Here the control event is turned into an action, which is a specific method that’s going to be run in a specific target object. Finally the UIApplication method sendAction:to:fromSender:forEvent: is called by the control, again once per event.

That whole process can be slightly exhausting, and fortunately we shouldn’t normally need to know its details. For our purposes, we should be aware that a UIControl object turns a touch event first into a control event and then into an action with a specific recipient. Even better, it’s only the last part of that conversion, from control event into targeted action, which we need to code.

Summary

Events are catched by the view (UIView) and then, following MVC pattern, they are delegated to the controller to be handled.

Wednesday, July 21, 2010

Delegate

Usually if we want to add new behavior in an existing object, we do inheritance. For example if we have class Apple below:



If we want the Apple class to have a new behavior such as growAppleInDesert(), we have some options:
1. Put the new method in interface or parent class, IFruit. This will apply to all subclasses, however.
2. Put the new method in Apple class. This can be done; however, if our Apple class is a simple UI, adding the action growAppleInDesert() here will break layering pattern.
3. Subclass Apple to create new class, say DesertApple. This is what OO design pattern suggested.
4. Create new class, say AppleGrowAction which contains growAppleInDesert() , growAppleInMeadow(), etc. Our current Apple object can then refer to the new AppleGrowAction class to call its methods. This is known as delegate.
5. Using "Category" feature of Objective-C. This will be explained later.

Another example is if we want to create a new component from an existing one. We have some options:
1. We can inherit the existing component; however, if the component has so many methods, we will end up having those methods in our class.
2. Put the component as delegate, our new component will only need to call methods in existing component.

In Cocoa Framework, delegate usually implemented as protocol. For example if we have a control UITextField, we will need to implement UITextFieldDelegate protocol in order to handle text field event.



In Java it is common to do (3) or (4), but, in Objective-C, (4) is widely used. It is called delegation because we delegate some tasks to another object.

Category

Category is an Objective-C feature that allows us to extend the capability of a given class. This feature works even if we do not have access to the source code of the class we are extending. When we extend a given class through a category, the extension is inherited by all its subclasses. Of course, the additional methods defined by the category are only seen by our program.

To illustrate this feature, let us extend the NSObject class by adding an instance method to it:

Tuesday, July 20, 2010

Java reference, Objective-C retain count

Java

How Java's garbage collector knows that an object must be destroyed? An object is a candidate for garbage collector if they lose all its references. For example Object B below. It is referred by variable B1 and B2. Once both B1 and B2 lose reference to it, none knows that it exists, then it becomes candidate for garbage collector.



Objective-C

Objective-C on the other hand, uses different approach. Each object holds a variable named retainCount. It is set to 1 the first time the object created. It is incremented anytime the object retained or copied. It is decremented anytime it is released. When the retainCount equals zero, the object is destroyed.

Those differences happen because they use different approach in memory management. Java depends on its garbage collection algorithm to release unused memory, while Objective-C gives programmers more responsibility to release their objects. If you allocate memory, it is your responsibility to release it.

However, since XCode 4.2 Apple has put new feature called ARC (Automatic Reference Counting) to ease developers’ job dealing with allocating and releasing memory. It is sort of AOP implementation in Objective-C for me.

Using ARC, we don’t need to release memory we allocated before, in other words we don’t need to deal with retain-release code anymore. The compiler takes care the code of retaining-relasing objects. At compile time, the compiler crosscuts your code and adds some line of retain-release code. Using ARC we now only have to deal with our logic.
 

©2009 Stay the Same | by TNB