Showing posts with label objective-c. Show all posts
Showing posts with label objective-c. Show all posts

August 3, 2009

Assigning Delegates

Kind reader Demitri Muna pointed out a flaw in my TableFormEditor package. I stumbled into a trap I fear many newbie Objective-C programmers also fall into: that of retaining delegates. It is a two-line change, but I feel this issue is important enough to write about it.

The basic problem is a retain cycle which results in a memory leak. This has been fairly well documented in this thread, but I will go into more detail here in the context of the TableFormEditor.

In this context, there are 2 actors involved:

  1. the client object
  2. the TableFormEditor object

When the client object creates a TableFormEditor instance, it needs to pass a delegate to handle the various callbacks. Typically, but not required, the delegate is the client object (i.e. self).

The TableFormEditor has this declaration in its .h file:

@property (nonatomic,retain) id <TableFormEditorDelegate> delegate; 


So what this means is that the client has a retain on the TableFormEditor (because it created it via [alloc]), and the TableFormEditor instance has a retain on the client (via the "retain" keyword in the @property declaration).

This is the dreaded A -> B and B -> A scenario described in the Stack Overflow thread mentioned above. When you are in this situation, A and B will never go away because B has a retain on A that will not release until B goes away. But B won't go away until A goes away. Result: memory leak!

However, all is not lost if you followed the pattern I have in the TableFormEditor example. In the example, I do not keep the TableFormEditor object around. As soon as I push it on the Navigation Controller's stack, I release it:

   
// stick the editor onto the navigator's stack 
[self.navigationController pushViewController:form animated:YES];      

// release the form since the navigator retained it 
[form release]; 


But, if you retain the pointer to the TableFormEditor, like keeping it in an instance variable, then you will likely end up with a memory leak.

Thus I have released version 1.6 of the TableFormEditor class to make this change:

@property (nonatomic,assign) id <TableFormEditorDelegate> delegate; 


This simply assigns the pointer without bumping up the retain count. This breaks the cycle and the potential for memory leaks.

For more information on retain cycles and how to prevent them, I urge you to check out this blog article at Cocoa With Love.





June 9, 2009

Java on the iPhone?

Is it possible? Can you run Java on the iPhone? Well, no, at least not at this time. Perhaps never, due to the rules Apple have in place disallowing interpreted languages from operating on the iPhone. This is a real shame because quite frankly, Objective-C is not an easy language to work with. And since it is the only language we have to work on for the iPhone, our hands are extremely tied. (One could argue that Objective-C++ allows C++, but in my opinion, this is a much uglier situation than just coding in Objective-C.) I am a former Java coder. Java may not be the most enabling language (think Python or Groovy), but the grammar is clean and simple and arguments about Java being too verbose are lost when comparing it to Objective-C. I like the power of the Cocoa-Touch run-time environment. However, the vehicle to get to that power (Objective-C) is a nightmare. Objective-C is clunky, verbose, inconsistent, and archaic. It is loosely based on SmallTalk, a relatively unused language in the industry. There's a reason for that. To me, doing anything in Objective-C is painful. Take the mundane task of creating a dictionary and adding a key/value pair to it. In Objective-C, it would look something like this:
NSMutableDictionary* dict;
dict = [[NSMutableDictionary alloc] initWithCapacity:3];
[dict addObject:@"Some data" forKey:@"key"];
I have many issues with this code:
  1. Why does Objective-C insist of dealing with pointers? Since you can't instantiate an object on the stack like you can in C++, having to specify the "*" character is superfluous. The fact that these are pointers should be hidden, as they are in Java. In the rare cases you need to actually refer to the class name and not the pointer, use some other syntax.
  2. The [object method] call syntax is really whacked. My opinion is that this is not an intuitive syntax, nor is it easy to read or write. It is nearly impossible to visually parse, especially with nested calls.
  3. Semicolons? Come on. There is no reason why a language parser cannot figure out the end of a statement. These are artifacts from the days of Pascal and C when they didn't know better. Tcl, Groovy, Python, Ruby, JavaScript, et al prove that semicolons are extraneous syntax fluff. It's a shame that most programmers accept them as the de facto for languages, when in fact they indicate a poorly designed grammar.
  4. Look how verbose and awkward it is to add a single element to the dictionary. I get carpal tunnel syndrome just reading Objective-C code. Objective-C forces you to use positional arguments and named arguments at the same time. If it wasn't for Xcode helping to write Objective-C, it would be a horrid language to type.
  5. I miss the commas between arguments. These are not needless syntactical fluff, as the "*" and ";" characters are. Commas help visually separate arguments. Without them, the args all blend together and make it hard to read.
  6. What's with the @ characters in front of strings? I understand they are trying to differentiate between C-style string constants and NSString constants, but why give the simpler syntax to C? I have never used a C-style string in an Objective-C program. I would have made "string" automatically be an NSString constant, and if you want a dinosaur C-style string, then use @"string".
Okay, that's six major complaints in just 3 lines of code. This doesn't even go into my other major beefs, such as separate files for class definitions and declarations, the @property/@synthesize malarkey, the use of "@end" as a block terminator, etc. Java can do the same task a little better and with a much cleaner syntax:
HashMap dict;
dict = new HashMap(3);
dict.put("key", "Some data");
It still has those dumb semicolons, but this is still a major improvement. I know all this bitching and moaning doesn't accomplish much. Objective-C is the tool we have to work with on iPhone development. There is nothing you can do about it. Adapt and move on. And adapt I did. I tolerated Objective-C's quirks for months. But I always thought about how much easier and productive it would all be in another language. I couldn't let it go. Then I came up with an idea: What if I just used the syntax of Java, and not the Java run-time environment? What if I wrote a translator, one that translated Java code into Objective-C? How hard would it be? I think this is quite possible, as long as you lay down a few ground rules. I have accumulated a fair number of these ground rules and revelations from tinkering with prototypes. The above Objective-C code could look like this in Java syntax:
NSMutableDictionary dict;
dict = NSMutableDictionary.alloc().initWithCapacity(3);
dict.addObject("Some data", forKey="key");
Notice a few things different? But some things are the same. The most important aspect of this is how we pass parameters. The first parameter is passed like normal, but all subsequent parameters are passed as if they are keyword parameters (ala Python). Although this is parseable Java syntax, it wouldn't compile. But it can be translated to Objective-C very easily. The whole idea is boiled down to this: In Xcode, write your iPhone software using Java syntax. Calls to the Objective-C runtime and Cocoa Touch are pretty much the same. There are no separate .h and .m files, just .java files. Then run the Java code through a translator that generates the Objective-C .h and .m files, which then get compiled. Xcode provides the ability to run preprocess steps in a build operation. So you could set up your builds to translate your Java source to Objective-C, then the normal build process would take it from there. Another benefit is that Xcode will think you're typing in Java code (because you are, sort of), so you will get all the nice keyword highlighting and other editor shortcuts. This idea is not limited to Java. Although Python does not have static typing, the ShedSkin project proves that you can translate Python to C++, so it is likely possible to also translate Python to Objective C. But this situation is not perfect. For starters, any compile errors in the Objective-C source will have to be corrected in the original Java source. Unless you want to abandon your original source, you should never edit the generated Objective-C source code. Runtime debugging will have to be in Objective-C. For some, these problems may be enough to warrant this as an exercise in futility. I will reserve judgment until trying it in production software rather than just in tinkering. This introduction is just to whet your appetite of the possibilities. This project I call "Typhoon". Typhoon will comprise the set of language translators and any additional run-time support necessary. In future articles, I will describe some of the ideas of Typhoon. I invite readers to leave comments on what you think about this idea. Is it worth pursuing? Or is it an idiotic waste of time? Please let me know.

May 6, 2009

Reflection in Objective-C

When I first learned Java, I thought the whole reflection package was novel, and it put Java closer to the realm of interpreted scripting language and farther away from the then-mainstream languages of C and C++. The idea of being able to look inward at the class metadata of an object at runtime was really fascinating, although not always terribly useful in everyday application programming. Those programmers coming over to the Objective-C world from Java will be happy to know that Objective-C also supports the concepts of reflection, AKA introspection. In fact, Objective-C 2.0 has many runtime features such as dynamically changing a class definition and even creating a new class dynamically. The necessity for these abilities is rather obscure, and it firms my belief that Objective-C is a ridiculously bloated language. To me, Objective-C has a bit of an identity crisis: it's not quite sure if it's an interpreted language or a compiled language. The runtime is mostly dynamic. Unlike C++, Objective-C does runtime binding. This is why you can do things like define methods for an implementation that are never declared in your header file, or extend existing classes with categories. Unfortunately, because of all this bloat, it is hard to find just the simple stuff that you might actually use in your day-to-day code. I will try to unearth some of these jewels and bring them to light.

Grandpa NSObject

Most, if not all, the runtime reflection support comes from the NSObject class. NSObject, like Java's Object class, is the granddaddy class of all classes (except for some rare exceptions). Therefore, all of your classes already have access to this reflection support. It's important to note that all this reflection support is not part of the Objective-C language per se; it is part of the NS* runtime environment. This is also why some of this stuff seems tacked on. It's because it has, uh, been tacked on.

Getting Class Metadata

You can access the class metadata for an object by calling the class method:

Class c = [self class];

This method is both an instance and a class method. It returns a C struct full of all sorts of mysterious stuff, like the list of instance variables, methods, etc. All of this is old hat to the java.lang.reflect package users out there, but the interfaces to reach this stuff in Objective-C seems really complex. This is probably difficult by design to keep the riff-raff out. So far, the only use I have for the class method is to provide the parameter to the isKindOfClass method described below. I never need to actually look at the contents of the Class structure.

Dynamic Method Invocation

I already discussed one aspect of reflection in my article about invoking methods. This allows you to build up a method call, arguments and all, at runtime. This is similar to using the java.lang.reflect.Method class in Java.

Testing inheritance

Java has an operator called instanceof that allows you to check if a object is an instance of a particular class or interface. Objective-C has a similar feature, the isKindOfClass: method. isKindOfClass: will return YES if the receiver is an instance of the given class or an instance of any class derived from the class. For example, if I had an array of related pointers, I can operate on each differently according to its type:

for(BaseClass* base in myArray) {
 if([base isKindOfClass:[ClassOne class]]) {
     // do stuff specific to ClassOne
 }
 else if([base isKindOfClass:[ClassTwo class]]) {
     // do stuff specific to ClassTwo
 }
 else if([base isKindOfClass:[ClassThree class]]) {
     // do stuff specific to ClassThree
 }
 // etc
}

If you want an exact class match, and not match any inheriting classes, then you use isMemberOfClass:.

Testing Protocol Conformance

Similar to class instance testing, you can also test whether an object conforms to a particular protocol. Java neatly uses instanceof for both classes and interfaces, but Objective-C has to have a more clunkier approach. To test conformance, use the conformsToProtocol: method:

BOOL conforms = [obj conformsToProtocol:@protocol(MyInterface)];

Testing for Method Existence

To an old Java and C++ hack like me, it seems extremely odd that you may not know if an object implements a method or not. But since Objective-C classes are largely dynamic, you need a way to check if a method you need is actually there. Hence the method respondsToSelector:. Here you are asking the receiver if it implements (or inherits) the given method:

if([obj respondsToSelector:@selector(aMethod:)]) {
   // it's there, so we can call it
   [obj aMethod:YES];
}

Certainly, there is way more you can do on the reflection front in Objective-C, but I tried to discuss the more commonly used reflection mechanisms. If you need too add hardcore dynamic nature to your software, you should be familliar with these documents: Runtime Programming Guide: Introduction Runtime Reference

March 18, 2009

Copying pitfalls

Copy semantics are a little different in Objective-C than in Java and C++. Say we have an array:
NSArray* arr1 = [[NSArray alloc] init];
And you have some data in it. Most people realize that the following assignment
NSArray* arr2 = arr1;
doesn't make a copy of anything except the pointer. What you end up with is two pointers pointing to the same array. To make a shallow copy of arr1, you can do something like this:
NSArray* arr2 = [[NSArray alloc] initWithArray:arr1];
This is a "shallow" copy because although it creates a new array, all its contents are pointers which point to the same contents of arr1. The Objective-C frameworks provide a copy method which you would think would work, but it too creates a shallow copy. The following is just another way of saying the above:
NSArray* arr2 = [arr1 copy];
This will also allocate a new NSArray object (and retain it) and put in the same pointers from arr1 into arr2. To get a deep copy of arr1, meaning not only a new array but a new copy of each element in the array, you need something different:
NSArray* arr2 = [[NSArray alloc] initWithArray:arr1 copyItems:YES];
NSDictionary objects also provide this form of initializer to allow deep copying of a dictionary container. All of this is fairly muddy, but when we start talking about mutable containers, it gets worse. Consider the following code:
NSMutableDictionary* firstDict = [[NSMutableDictionary alloc] initWithCapacity:10];

// add some data to the dictionary
[firstDict setObject:@"hi" forKey:@"one"];

// now make a copy of it
NSMutableDictionary* secondDict = [firstDict copy];

// add some more data to the second dictionary
[secondDict setObject:@"there" forKey:@"two"];

// BOOM!

The "BOOM!" above means an exception is thrown. Why? Because the dictionary secondDict, although declared as an NSMutableDictionary and copied from another NSMutableDictionary is actually an NSDictionary. It is reasonable to think that copying a mutable into another mutable would create a mutable copy, but it is not so in Objective-C. The problem is that the copy method creates an immutable object. The solution here is to use the mutableCopy method, which is a special copy method just for mutable containers. So the line above should be replaced with:
NSMutableDictionary* secondDict = [firstDict mutableCopy];
So what if you want a deep copy of a mutable container? In this case, you can use the special NSDictionary initializer that takes the copyItems parameter:
NSMutableDictionary* secondDict = [[NSMutableDictionary alloc] initWithDictionary:firstDict copyItems:YES];
(Note that to use copy, mutableCopy, or the initializers that take copyItems, the objects that are contained in the array or dictionary must conform to the NSCopying and/or NSMutableCopying protocols.) What these examples show is that the initializers behave as expected, but the copy method is only for immutable containers and the mutableCopy method is for mutable containers. Because of this confusion, I prefer to use the initializer for both my shallow copying and deep copying; simply change the copyItems to NO for a shallow copy.

February 19, 2009

Objective-C Initializer Patterns

Creating objects in Objective-C is a two step process: you first allocate the space for the object, then you initialize it. In C++, the act of allocating (new) an object automatically calls the object's constructor, but it's basically the same two steps under the covers. However, the similarities end there. Objective-C initializer methods are different from C++ constructors. Those coming over from C++ might struggle a bit with them, so this article will attempt to bring forth these differences and discuss some common patterns.

Names

The most obvious difference are the names. The name of C++ constructors must be the same as the class name. Objective-C initializers, by convention, start with the prefix "init". However, since these are simply methods, this naming is purely by convention. You could call your initializer "jimmyJoeBob" if you wanted, but the pattern is to use "init" as the prefix, so "initJimmyJoeBob" would be OK.

Return Types

This one recently burned me. C++ constructors don't really have a return type, since they are not really methods. If it had to have a return type, you would assume it was a pointer to the class it is constructing. Not so in Objective-C. Take this blunder for instance: We have a base class:
@interface Base
{}
- (Base*) init;
@end
And we have a child class:
@interface Child : Base
{}
- (Child*) init;
@end
Each has an initializer. Neither is named "jimmyJoeBob", so we're OK there, but do you see the problem? Sure, this is a stupid mistake, but I believe many C++ converts will stumble into this: Class initializer methods must have a return type of id. If you fail to do this, and you are overriding a parent's initializer, you get a cryptic message from the compiler saying "warning: assignment from distinct objective-c type". This is because your override did not completely override; the return types don't match. Making all the initializers return id gets around this problem.

Return Values

All your initializers typically return "self". You might think that it would be nice if they did that automatically, but remember: these are really methods, not constructors. Initializers may return something different than what was allocated. What they return needs to be the same type as self, but it could be a different instance. One poor example would be if the class maintained a pool of already-allocated and initialized objects of itself. If the caller was initializing an object exactly the same as an object already in the pool, the initializer may deallocate itself and return the pooled instance instead. Initializers can also return nil if there was an error. C++ constructors can't return anything. The best they can do is set a flag, or worse, throw an exception. Because of these capabilities of the initializers, you should never use code like this:
id object = [MyClass alloc];
[object init];
[object doSomething];
The reason is the init method could have returned a different object, or nil, but this code would have missed it. The pattern you really should use is this:
id object = [[MyClass alloc] init];
And since the initializer could return nil, it might best to check the value before using it.

Automatic Memory Clearing

One really nice thing about Objective-C is that the allocate will fill the instance data with all 0's. As practical as this seems, C++ doesn't enjoy this luxury, and it must tediously initialize every instance variable; otherwise their values are random. This behavior makes most initializers unnecessary.

Super Initializers

Just like in C++, Objective-C initializers should explicitly call the appropriate initializer of its parent class. This is done via the "super" pointer. But wait! Since initializers can return nil or something entirely different, your child class initializer needs to be aware of that. The pattern here is to reassign self to what comes back from the super initializer, just in case it returned something else. And check for nil for good measure:
- (id) init {
  self = [super init];
  if(self) {
     ...
  }

  return self;
}

Returning Nil

When there is some error in the initializer, and your only recourse is to return nil, you have to be careful about creating a memory leak. If you simply returned nil, then the original pointer to the object is lost, which results in a memory leak. You should release yourself first before returning nil. The one who is returning nil is the one who releases. If you get back nil from a super initializer, you can assume it has already released. The release should be done at the first point of failure. Example:
- (id) init {
  if(someKindOfError) {
     [self release];
     return nil;
  }
}

Avoid Accessor Methods

It is generally recommended to avoid using property setters in initializers, due to possible side-effects. In other words, don't set properties with "self.propname = something". Use the instance variable directly: "propname = something;"

This can only apply to your own instance variables; for initializing instance variables on other objects, you may have only the accessor methods.

Convenience Constructors

There is one last pattern to consider for initializers. Some Cocoa classes have what are called convenience constructors. You might also call these factory methods. These are static (class-based) methods that allocate and initialize an object for you. Examples of these can be found in the NSString and NSArray classes. One thing to be aware of with convenience constructors: Unlike using alloc/init, the retain count of what is returned is not automatically set to 1. You need to retain any pointer you get back from a convenience constructor. I'm sure there is some valid use case as to why we have this inconsistent behavior, but I don't know what it is.

Example

Now we'll summarize all this with an example that demonstrates most of the patterns mentioned above. The interesting bits will be preceded by a red number and explained afterward:
- 1(id) 2initWithFile:(NSString*) filename {
3self = [super init];
4if(self) {
 if(filename == nil) {
     5[self release];
     return nil;
 } else {
     6m_filename = filename;
     [m_filename retain];
 }
}

7return self
}
  1. Initializers are instance methods that always return id
  2. By convention, initializers begin with the prefix "init"
  3. Always call your super initializer, and reassign self to that return
  4. Be sure to check the return value from your super, since it may return nil
  5. If you have an error release yourself first, then return nil
  6. Access your instance variables directly, and retain manually
  7. Return self

February 17, 2009

Property Pitfalls and Patterns

Properties are a handy, if not a cumbersome, addition to Objective-C 2.0. Although they add a good deal of convenience, you must never forget what is happening under the covers, else you could end up with problems and confusion. The problem I blindly walked into was not considering the automatic retain done when using the setter. Consider this statement:
self.name = input_name;
This actually invokes a setter that the compiler has synthesized for you. If you declared the property with the "retain" attribute, as in this:
@property (nonatomic,retain) NSString* name;
then what the above assignment will do is:
  1. release whatever name is pointing to
  2. set the new value
  3. retain the new value (take ownership)
This shortcut is extremely handy; however, it's easy to forget that there are some cases where you are already the owner of an object, so the retain is redundant and will cause a memory leak:
self.name = [[NSString alloc] initWithString:input_name];
When you alloc an object, the retain count is already set to one. When you assign this to your property, the setter will bump up the retain count again. The retain count of self.name is now 2. Thus, you have a memory leak. [update date:@"Feb 19, 2009"]; It should be noted that the line above is different than this line:
name = [[NSString alloc] initWithString:input_name];
This form is accessing the instance variable directly, whereas the self.name form is invoking the property's setName: method. This distinction is important because when you skirt around the setter, you don't get the 3 little "side-effects" mentioned above. This can be both useful and dangerous. I recommend NOT using the instance variable directly if it is a property, unless you are in an initializer. It is just too easy to get things wrong; if you assign directly to the instance variable and it already has something assigned to it, you get a memory leak. It is best to be consistent with how you use your properties. [endupdate]; There are a couple solutions I have seen so far, but I don't think any of them are very pretty. One common trick is to autorelease the return from init. This way, the retain count will still be 2, but the next time the autorelease pool is emptied, the redundant reference is cleaned up:
self.name = [[[NSString alloc] initWithString:input_name] autorelease];
This violates the general rule of avoiding autorelease as much as possible. Autoreleasing will release the memory (at some point), but you have no control when that actually happens. Memory could get bloated or even run out before it does happen. When coding on a limited resource device like the iPhone, I think this is a good rule to follow. Another solution is simply to release after the assignment:
self.name = [[NSString alloc] initWithString:input_name];
[self.name release];
But this is non intuitive and can be confusing. A clumsier but cleaner way would be to use a local variable:
NSString* temp = [[NSString alloc] initWithString:input_name];
self.name = temp;
[temp release];
Any other ideas on how best to do this? There is another pattern in common use that I missed in my first applications. It concerns dealloc and properties. Here is what I used to do:
- (void) dealloc
{
  [property1 release];
  [property2 release];

  [super dealloc];
}
Seems perfectly reasonable, and I believe in most cases, this is fine. However, the preferred mechanism for releasing properties is to assign nil to them:
- (void) dealloc
{
   self.property1 = nil;
   self.property2 = nil;

   [super dealloc];
}
So what's the difference? I'm still searching for the definitive answer, but I believe this is preferred because it releases the property and sets it to nil. How? At first glance, this looks like a memory leak. But remember the steps that synthesized setters do for you: 1) release the old value, 2) assign the new value, then 3) retain the new value. In this case, you can't retain nil, so the 3rd step is a no-op. This is a common technique in C++ destructors, which prevents a deallocated pointer from being used later on. This syntax is not intuitive, though, and you have to understand what's going on in the setter.

February 13, 2009

Private Methods in Objective-C

Most mainstream OO languages (C++, Java) support the notion of private, protected, and public class members. I've debated for years whether these protection attributes are really worthwhile, but it seems the designers of Objective-C felt protection for methods was not necessary. While you can add the various protection attributes to class and instance fields, you cannot do the same for methods.

There are several tricks you can employ, but I will present here the most straightforward and simplest approach. This trick uses the concept of class extensions, a bizarre facility that allows you to extend another class with replacement or additional methods. This technique is also sanctioned by the Apple Objective-C 2.0 Programming Language document (The Objective-C 2.0 Programming Language). To add a private method to your class, you extend your own class within your implementation (.m) file. This way, clients of your interface (.h) file do not see or know about your methods. For example:

// .h file to declare our class
@interface MyClass

// this is a public method
- (void) sayHi;
@end

You'll notice in the header file, which is imported by users of your MyClass, has no mention of a private method. It is the implementation file where we put it:
// .m file to define our class
// but first let's extend our class with a private method
@interface MyClass ()

// this is a private method
- (void) tellSecret;
@end

// now we implement everything
@implementation MyClass

// the public method
- (void) sayHi
{
  NSLog(@"Hello everyone!");
}

// the private method
- (void) tellSecret
{
  NSLog(@"Psst, ...");
}

@end