How To Make Iphone Apps

Everything Iphone Related

  • How To Make Iphone App
  • Objective-C Tips
  • Apps
  • Editorial
  • Contact

Understanding Subclassing

December 28, 2017 By Leslie

This means that if you have code in one class that you would like to reuse in another class you can create a subclass. The original class is called the superclass and the subclass gets all the code in the superclass. You can also add additional code to the subclass. Programmers do this all the time which creates a hierarchy like the graphic at the top of this page.

The Super And Self Keywords

If you haven’t yet groked the relationship between classes and objects the details of this can get confusing. For instance, take a look at the init override that you get from Xcode’s code library:

-(id)init{
    self = [super init];
    if (self) {
        //initialize here
    }
    return self;
}

NOTE I’m assuming you know about how to create classes in Objective-C here. If you don’t know what I’m talking about click here to read the chapter on creating classes in Objective-C.


So I highlighted some particularly confusing keywords that are in theinit function.self andsuper reference objects from the class that we are currently defining.

While both keywords objects created from the class self references the properties and methods defined in the current class definition while super references the properties and methods defined in the superclass definition.

Objects And Classes

Let’s take another look at that init override so we can see the context where we usually see this function.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@property(strong) NSString *name;

@end

@implementation MyClass

-(id)init{
    self = [super init];
    if (self) {
        //initialize here
        _name = @"MyClass Object";
    }
    return self;
}

@end

int main(int argc, const char * argv[]){
    @autoreleasepool {
        MyClass *myObject = [[MyClass alloc] init];
        NSLog(@"myObject.name = %@", myObject.name);
    }
    return 0;
}

Here’s the English version of the code above: we defined a class named MyClass which is a subclass of the NSObject class. MyClass is going to override the init function.

In the main function we are going to instantiate an object named myObject and write out the myObject name value to the console log.

Class Vs Object

A class is a definition of an entity (an abstract model) that is made up of definitions for properties and methods. By itself, a class doesn’t do much other than contain a definition. In the above example all the code that defines the class is between the @interface and @end keywords and the @implementation and @end keywords.

Objects are special variables that are created based on class code definitions. You can see how objects are used in the main function above. Typically, you would create many objects based on one class definition.

How It Gets Confusing

This stuff gets confusing because most people think of classes and objects as the same thing. After all, when you want an object to behave differently you must make changes so rewrite the class definition. So that’s pretty natural. Getting back to the init function though you can see why this gets confusing,

-(id)init{
    self = [super init];
    if (self) {
        //initialize here
    }
    return self;
}

In that first line of code after the function name, self = [super init];, it looks like we are getting an NSObject object from the superclass, assigning this object to self and then returning this to the caller.

This is not really the case. You are simply getting your MyClass object from the superclass. The reason that it seems like you are getting an NSObject object back here is because you are thinking in terms of objects and not class definitions. Even though this code will be used to initialize and return objects at some point right now we are only working on the code definition.

That self keyword doesn’t represent some NSObject object variable out there. It’s simply a way to reference the code from the superclass definition.

What subclassing really does for you is more like a copy and paste. It’s as if you have copied all of the NSObject code and used this code in MyClass. So that init call to super will just initialize the part of the class definition that is contained in NSObject before you finish up initializing.

Filed Under: Objective-C Tips Tagged With: Subclassing

Chapter Nine: How To Create Your Own Classes

October 16, 2017 By Leslie

At some point you will want to define your own classes to use in your app. So now let’s expand on the notion of object oriented programming by showing you how to implement your own custom classes. At this point you should be familiar with using existing objects in code; but you also need to be able to create your own types of objects.

Sub-Classes

One of the most common things that you will be doing with classes is something called sub-classing. As you can guess the iPhone has classes already in place to do things like present data tables, present windows and so on. Usually you will be creating your own object that inherits one of these preexisting objects and adding your own custom code to it. This is sub-classing.

Adding a New Class

XCode will help you do the initial set up work when you are creating a new class. To add a class you can simply control-click on a group folder in XCode and select New File… . In the dialog box that pops up select iOS > Cocoa Touch > Objective-C class and click Next . Then name your class and choose NSObject as the subclass.

Let’s do this now and call our class myClass. XCode created both the interface and the implementation files for myClass and added the code we need to get started. The interface file is the one that ends in .h. If you open that file you will see the code that XCode automatically filled in for us.

#import <Foundation/Foundation.h>

@interface myClass : NSObject{

}

@end

Interface File

This interface file uses an import directive to import the Foundation classes (which we always need to use). It also uses the interface keyword with the name of the class (myClass here) to indicate that we are defining a class.

The colon and the name NSObject means that our class will be a subclass of NSObject. Sub-classing and inheritance mean the same thing. You can say that myClass inherits from NSObject or you can say myClass is a subclass of NSObject.

We end the interface declaration with the end keyword @end.

Implementation File

XCode also created an implementation file, in case you did not notice XCode will create a separate file for the interface (header file that ends in .h) and the implementation file (ends in .m). Click on the implementation file to see the code that XCode added on our behalf.

#import "myClass.h"

@implementation myClass

@end

Our implementation file simply imports the myClass interface and includes the @implementation and @end keywords along with the name of our class.

Simple enough – we have created our first class. Right now it behaves exactly like NSObject, but soon we will be adding our own properties and methods to the class.

Adding Properties

When you add a property in a class you end up using a little black magic. That is, the system takes care of some of the implementation details for you if you do things in the typical way. You need to do two things to get a working property into your class: declare the property and then use @synthesize.

Here is what this looks like in the code:

Interface File (myClass.h):
#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;

@end

The property is defined by using the @property directive. The key thing to note here is strong.

Back in the implementation file we use @synthesize to evoke all the black magic that is required to create the property based on our definition in the interface file.

#import "myClass.h"

@implementation myClass
@synthesize name;

@end

One thing that is significant though is that when you use primitive types as properties the syntax is a little different. For example, I am going to add a number property to my class that is an integer. Notice that it is done in a slightly different way:

#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

@end

The first thing is that there is no asterisk * since this is not an object variable. The other thing is that instead of using the strong keyword it is using assign in the property declaration.

Dot Notation

What all this does for you is give you the ability to assign and retrieve the property values using dot notation. You have already encountered this in the examples. Here is how you use dot notation with a myClass object.

//Instantiate an object from myClass:
myClass *object = [[myClass alloc] init];

//assign properties:
object.name = @"Obie";
object.number = 3;

//Access and use the properties
//with dot notation:
NSLog(@"My object's name is %@", object.name);
NSLog(@"My Object's number is %i", object.number);

Note that we use an alloc and init message even though we never created these in our class definition. Since our class is a subclass of NSObject we can simply use the original NSObject constructer to create objects. We can also code additional constructors if we want to set properties before we return our object to the system.

Class Methods

As you remember from chapter ten , objects have both properties and methods. Properties describe the object (the object’s attributes) while methods are what the object does (the object’s behaviors).

Furthermore, methods can be either class methods or instance methods. Class methods do not require an instance of a class (an object) to be used, you simply send the message to the class itself.

Here is how to declare a class method:

Interface File:

#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

+(void)writeSomething;

@end

Implementation File:

#import "myClass.h"

@implementation myClass

@synthesize name, number;

+(void)writeSomething{
	NSLog(@"I'm writing something");
}

@end

Here, the plus sign indicates that this is a class method and the void in between the parenthesis means that the method will not return a value. This is followed by the name of the method and curly braces. Whatever we want the function to do we put in between the curly braces as code.

Since this is a class method we do not even need an object to use this method. All we need to do is send a message to the class name itself:

[myClass writeSomething];

Instance Methods

Instance methods also are used to code behavior, but these are different than class methods because they may only be used by sending a message to an object. You code them the same way inside the class definition but you prefix the method with a minus sign instead of a plus sign:

Interface File:

#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

+(void)writeSomething;
-(void)writeSomethingForAnObject;

@end

Implementation File:

#import "myClass.h"

@implementation myClass

@synthesize name, number;

+(void)writeSomething{
	NSLog(@"I'm writing something");
}

-(void)writeSomethingForAnObject{
	NSLog(@"I'm writing something, but only as an object");
}

@end

To use an instance method we must have an object available.

myClass *object = [[myClass alloc] init];
[object writeSomethingForAnObject];

Method Parameters

Like functions in C you can pass parameters to methods in Objective-C. The syntax looks different. To put a parameter into the method declaration you must add a colon after the method name and then declare the object type and name the parameter:

Interface File:

#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

+(void)writeSomething;
-(void)writeSomethingForAnObject;
-(void)aMethodWithThisParameter:(NSString *)param;

@end

Implementation File:

#import "myClass.h"

@implementation myClass

@synthesize name, number;

+(void)writeSomething{
	NSLog(@"I'm writing something");
}

-(void)writeSomethingForAnObject{
	NSLog(@"I'm writing something, but only as an object");
}

-(void)aMethodWithThisParameter:(NSString *)param{
	NSLog(@"%@", param);
}

@end

To use this method you would do this (this will be familiar to you):

myClass *object = [[myClass alloc] init];
[object aMethodWithThisParameter:@"Say What?"];

Multiple Parameters

You may have your methods take more than one parameter. Objective-C has a unique way of doing this where you may include a descriptive phrase in the method declaration.

Interface File:

#import <Foundation/Foundation.h>

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

+(void)writeSomething;
-(void)writeSomethingForAnObject;
-(void)aMethodWithThisParameter:(NSString *)param;
-(void)aMethodWithThisParameter:(NSString *)param 
		   andThisParameter:(int)num;

@end

Implementation File:

#import "myClass.h"

@implementation myClass
@synthesize name, number;

+(void)writeSomething{
	NSLog(@"I'm writing something");
}

-(void)writeSomethingForAnObject{
	NSLog(@"I'm writing something, but only as an object");
}

-(void)aMethodWithThisParameter:(NSString *)param{
	NSLog(@"%@", param);
}

-(void)aMethodWithThisParameter:(NSString *)param
               andThisParameter:(int)num{
	NSLog(@"%@ + %i", param, num);
}

@end

The key difference between methods with one parameter and methods with two is that starting with the second parameter each gets its own descriptive text prefix. Above it is andThisParameter: which is in front of the parameter num.

Your probably already guessed that you send a message to an object using two parameters like this:

[object aMethodWithThisParameter:@"One" andThisParameter:2];

Constructors

We know that constructers are special methods that return an instance of an object back to the system. We are already using the constructer that we inherited from NSObject, init to instantiate an object from myClass. We can create a custom constructor if it is needed.

In general, we always prefix our constructor with init. This is a matter of convention. Let’s start by defining our constructor in the myClass implementation file:

#import 

@interface myClass : NSObject

@property (strong) NSString *name;
@property (assign) int number;

+(void)writeSomething;
-(void)writeSomethingForAnObject;
-(void)aMethodWithThisParameter:(NSString *)param;
-(void)aMethodWithThisParameter:(NSString *)param 
				andThisParameter:(int)num;
-(id)initWithName:(NSString *) aName;

@end

Instead of being declared as a void type as our previous methods our constructor will be declared as an id. id means that our method will be returning a value that not yet defined. Whenever you replace the void with another type you are saying that this method will be returning a value (like a function in C).

Our constructor will also be taking a parameter which we will use to assign a name to the object’s name property. Here is how we implement this constructor:

#import "myClass.h"

@implementation myClass
@synthesize name, number;

+(void)writeSomething{
	NSLog(@"I'm writing something");
}

-(void)writeSomethingForAnObject{
	NSLog(@"I'm writing something, but only as an object");
}

-(void)aMethodWithThisParameter:(NSString *)param{
	NSLog(@"%@", param);
}

-(void)aMethodWithThisParameter:(NSString *)param 
				andThisParameter:(int)num{
	NSLog(@"%@ + %i", param, num);
}

-(id)initWithName:(NSString *) aName{
	if (self = [super init]){
		self.name = aName;
	}
	return self;
}

@end

In the if-then statement above we assign the object returned from the constructor that we inherited from NSObject to the current object (notice that there is only one equals sign). The self keyword always refers to the object in which the self keyword was placed while the super keyword refers to the class it is being inherited from (sometimes called the superclass).

Once we have successfully retrieved the object from the super init we can assign values to our properties.

Here is how you would use your new constructor to create an object:

myClass *object = [[myClass alloc] initWithName:@"MyObject"];

Hands On Time

Practice creating your class by first thinking all some attributes and behaviors could represent a person in your code. Keep it simple but meaningful. Use the techniques that you learned in this chapter to create a class definition for a person. Instantiate and use objects created from this class definition. Try using a NSMutableArray to hold a list of your person objects.

Filed Under: Objective-C Tips

Working with Multiple Targets in Xcode + Code Reuse, Part One

December 12, 2012 By Leslie

Have you ever wanted to share code between apps? I have and honestly, code reuse with Xcode (in particular between apps) is not as straightforward as you might imagine. You do have some options which I’ll talk about here and once you get something set up this problem will be solved easily.

The reason I started looking into this was because I wanted to release several variations of my app (or rather my app’s database engine).  Previously, I have done this by simply copying the core libraries as needed.  Essentially, each app of mine would have it’s own Xcode project and point (or have copies) of the code files I needed.

This solution is unsatisfying as hell and it became enough of a chore in terms of app maintenance that I ended up pulling many of my apps from the store in 2011.

So, last month I started to investigate some options that would help with code reuse among apps.  But first, let’s backup and talk about code reuse and why most developers strive to reuse code.

Multiple Targets in Xcode

Let’s Talk About Code Reuse

Coders will often be tasked with solving the same or similar problems when making software.  Since most people don’t want to code or copy the same thing over and over again we try to come up with ways of organizing code so that we can avoid repetition.  Instead of writing a few lines of code we will encapsulate that same code in a function that we can reuse over and over again.  Write once and use forever.

Not only does this help us keep our code smaller we can avoid mistakes in the future because we will build on a collection of code we already know works.  When bugs are fixed, they are fixed for anything that uses that code.  Instead of correcting an algorithm in 100 places, we correct it once.

In an Objective-C program like an iOS app, you may see code reuse implemented with functions, classes that support sub-classing and delegation, categories and blocks.  Most developers are comfortable with this practice at the app level.

Tasting Notes and the system behind the app already followed patterns that enabled code reuse since I’m a stickler for object oriented patterns.  However, a problem emerged when I wanted to expand the reach of the Tasting Notes database engine.

The Code Reuse Problem Across Apps

Here’s what I wanted to do:

I wanted a entire suite of applications that used the Tasting Notes database engine.

The database engine is about 40% of the Tasting Notes code.  Some of the apps in the suite could also reuse the user interface elements on the Storyboards, while others like the Mac version would also use the model classes.  Many apps on the app store are a part of a suite like this and I’m sure they reuse the code that they can.

I was very surprised that setting up my app suite didn’t go as smoothly as I thought.  What started as a day or two project ended up turning into a multiple weeks project where I tested my options with Xcode.  Here are the solutions I tried.

Static Library with Xcode Workspaces

Surely this was the way to go right?  My plan was to remove the database engine (and model classes) from Tasting Notes and turned this into a static library.  The same would go for the standard user interface components.  I would have started out with three separate Xcode projects that I could keep organized with one Xcode workspace.

This works in principle, but the reality of managing the three projects even at this level was a pain.  The UI part would need to reference the model part which in turn was referenced by the app.  Each one had it’s own frameworks to link.  Odd linking errors would show up.  This solution was it’s own kind of mess, however with the simplest situation it did work more or less.

Problems really started to happen when I attempted to add a Mac Cocoa app to the workspace.  Obviously, I couldn’t reuse the iOS user interface.  But it turns out that even the database engine couldn’t be added to my Mac app without a lot of very confusing configuration changes to the static library.  This was the point where I gave up to look for better solutions.

BOTTOM LINE While the most obvious solution, the static libraries added too much work to the process to make it worthwhile to use.

Pointing to Code with Workspaces

The next thing I tried still involved using Xcode workspaces (I really thought that this was the way to go).  What I did was create a group independent of any Xcode project in the workspace that held the shared code.  This was once step up from what I did before.

This didn’t really help much either.  First of – the way I set up the group folders meant that there was no Git support which I need.  Of course, I could have added this myself but I wasn’t sure if I could actually integrate with Xcode in this way.  Things were already starting to get to complicated.

Also, this solution didn’t help me as much as I wanted with or without Git.  Each project needed to add each code file and there is almost a hundred of them.  I also had to link to the other frameworks needed by my shared model classes.  Linking to other frameworks isn’t a big deal when its the built in stuff, but including the Google, Dropbox and other third-party frameworks I use because a chore with this approach.

BOTTOM LINE This approach didn’t help at all and actually made some things a bit more difficult.

Multiple Targets

This is something I really didn’t know you could do.  Or rather, I knew about multiple targets but was so entrenched in how I used to set up projects that I never really considered what the purpose or implications of multiple targets were. [Read more…]

Filed Under: Objective-C Tips Tagged With: Code Reuse, Multiple Targets in Xcode

Write to the Console with NSLog

November 29, 2012 By Leslie

Writing to the console log is something that you’ll end up doing sooner rather than later. Usually you’ll write to the log when your testing prototype code. Other times, you may be simply debugging your code (although there are better ways to debug).

NSLog

Objective and primitive type values may be reported to the console using NSLog. Each type has a different specifier that must be used as a placeholder for the value. You will type out the string that you would like to appear in the console while putting in specifiers into the string where you would like to see values reported. You can put as many specifiers into the string as you like, but you must make sure to include each value in the call to NSLog.

For example, if I had an integer variable named myInteger and a character variable named myCharacter and I wanted to report each of these values to the console I would do something like this:

NSLog(@”myCharacter = %c and myInteger = %i”, myCharacter, myInteger);

Warning Each specifier that you include in the NSLog string must have a corresponding value in the comma-seperated list to the right or the compiler will throw at error more ‘%’ conversions than data arguments at compile time.

How to Use NSLog

NOTE: you will need a Mac or iOS application set to try out these examples of NSLog .

Open up your applications main.m file. Your code will look something like this:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char *argv[]){
    @autoreleasepool {

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

Stick the code that we want to test on the next line right after the @autorelease statement.

Examples of NSLog

Add and examine these NSLog statements to your application to see different ways that NSLog is used.

//To print out primitive types:
int myInteger = 1;
NSLog(@"myInteger = %i", myInteger);
		
float myFloatingPointNumber = 2;
NSLog(@"myFloatingPointNumber = %f", myFloatingPointNumber);
NSLog(@"myFloatingPointNumber in scientific notation = %e", myFloatingPointNumber);
		
NSLog(@"myFloatingPointNumber = %f", myFloatingPointNumber);
NSLog(@"myFloatingPointNumber in scientific notation = %e", myFloatingPointNumber);
        
char myCharacter = 'A';
NSLog(@"myCharacter = %c", myCharacter);
		
//To print out the % symbol
NSLog(@"Percent Sign looks like %%");
		
//To print out Objective-C objects:
NSString *myString = @"My String";
NSLog(@"myString = %@", myString);
NSLog(@"myString's pointer = %p", myString);
		
//To print out a series of values
NSLog(@"myCharacter = %c and myInteger = %i", myCharacter, myInteger);

To test this code out, hit the Run button located in the upper lefthand area of Xcode. You should see output like this:

myInteger = 1
myFloatingPointNumber = 2.000000
myFloatingPointNumber in scientific notation = 2.000000e+00
myFloatingPointNumber = 2.000000
myFloatingPointNumber in scientific notation = 2.000000e+00
myCharacter = A
Percent Sign looks like %
myString = My String
myString's pointer = 0x35d4
myCharacter = A and myInteger = 1

How to View the Console Log

You may not be able to locate your console window at first. With Xcode you can show and hide many panes that show content, code and utility widgets. Your console window should be located at the middle bottom area of Xcode. If you can see this window make sure that the View button strip located in the upper right hand area of Xcode has the middle button depressed.

Also make sure that the bottom window’s right pane button is depressed. Check out the screenshot below for the locations of these controls in Xcode:

xcode

Table of NSLog Placeholders

You can use the same placeholder specifiers with NSLog that you would use with the corresponding C functions to write to the log. Here is a list of the most important:

Specifier Data Type
%@ Objective-C object (looks at description method)
%d, %D, %i int (signed 32-bit integer)
%u, %U unsigned int (unsigned 32-bit integer)
%f double (64-bit floating point number)
%e double (64-bit floating point number in scientific notation)
%c unsigned char (unsigned 8-bit character)
%C unichar (16-bit character)
%p Pointer printed in hexadecimal
%% Escape character so we can print the % sign

Filed Under: Objective-C Tips

Recent Posts

  • Mobile Slot Games and Your iPhone – A Perfect Match
  • Mobile Apps: What to Install
  • Remote iOS debugging – an all-around approach
  • App review – Pal
  • 100 Essential Apps