The Mobile Galaxy The New Mobile Era Has Come | Mobile – A Time To Remember

28Oct/110

10 iPhone Memory Management Tips

From:http://akosma.com/2009/01/28/10-iphone-memory-management-tips/

  • Respond to Memory Warnings
  • Avoid Using Autoreleased Objects
  • Use Lazy Loading and Reuse
  • Avoid UIImage’s imageNamed:
  • Build Custom Table Cells and Reuse Them Properly
  • Override Setters Properly
  • Beware of Delegation
  • Use Instruments
  • Use a Static Analysis Tool
  • Use NSZombieEnabled

 

 

Share
28Oct/110

iPhone Basics: Memory Management

One of the biggest sources of confusion for new iPhone developers is memory management. If you’re accustomed to using convenient, garbage-collected scripting languages, you may be wondering why memory management is even necessary. Although Cocoa does support garbage collection, it was deemed too great an overhead for a phone platform. Therefore, it’s important for developers to know how to allocate and release objects correctly.

By following some simple guidelines, you can avoid the majority of memory management problems.

1. If you allocate an object, you should release it once you’re done.

When you allocate an object, you “own” that object, and you’re responsible for releasing it when you’ve finished using it:

Widget* widget = [[Widget alloc] init];
// Do something with widget...
[widget release];

You can think of release as saying relinquish ownership of this object, rather than destroy this object. Behind the scenes, Cocoa performs reference counting to keep track of ownership. If no one claims ownership, the object will be destroyed, and the memory it occupied will be reclaimed.

2. If you did not allocate an object directly, you should not release it.

Once you get the hang of release, it’s tempting to go around releasing objects when you shouldn’t. A common example is when you’re using factory methods:

NSString* label = [NSString stringWithFormat:@"Title: %@", widget.title];
// Do something with label
[label release] // Whoops, incorrect.

In this example, a new string object has been created, but we didn’t allocate it, and we don’t own it. Therefore, we must not call release here — doing so can cause an over-release, which can crash your app.

tip: How is this object released?

Behind the scenes, NSString has called autorelease on the string before returning it, which we’ll look at in a moment.

3. If you need an object, you should retain it (and release it when you’re done).

This rule applies when we receive an object that’s been created by someone else. For example, consider a setter method:

- (void)setName:(NSString*)newName;
{
    [newName retain];   // we need the new string object.
    [name release];     // we don't need the old string any more.
    name = newName;
}

retain signals that we claim ownership of the object; it will not be destroyed when the original owner releases it. But, now that we own the object, we must release it when we no longer need it. Under the hood, retain and release update the reference count of the object, incrementing and decrementing respectively.

Following this pattern simplifies memory management a great deal. When passing an object to a method, we can assume it will be retained (if necessary) and we can release it immediately afterwards:

UIButton* button = [[UIButton alloc] initWithFrame:myFrame];
[self.view addSubview:button]    // Here we can assume that view
                                 // has retained button,
[button release]                 // we can safely release it.

Another common example arises when we use collection objects, which retain the objects added to them:

NSMutableArray* widgetList = [[NSMutableArray alloc] init];
// ...
Widget* widget = [[Widget alloc] init];
[widgetList addObject:widget];           // retains widget
[widget release];                        // we can release widget
//...
[widgetList release] // objects in collection will be released.

4. If you create an object and don’t retain control of it, use autorelease.

Say you want to create your own factory method for Widget. Here, we create a new Widget object and return it from a class method:

+ (Widget*)createBetterWidget
{
    Widget* widget = [[Widget alloc] init];
    [widget setAwesome:11];
    return [widget autorelease];
}

We’re still responsible for releasing the object, so we call autorelease before returning it. autoreleasesignals that the object should be released “eventually.” The object is added to a pool that’s cleared at the end of an application run loop.

It may seem tempting to autorelease everything as a solution for memory management, however this is not recommended, as it’s possible for your app to run out of memory before the autorelease pool is drained.

The best approach is to take a simple, unambiguous approach to allocating and releasing objects. Follow these simple rules and you’ll be well on the way to creating bug-free and efficient code.

For in-depth coverage of these topics, the Apple Memory Management Programming Guide is essential reading for new developers.

Share
26Oct/110

IOS 5 & S/MIME

In  testing, iOS 5 was able to obtain recipients’ certificates through Exchange and Active Directory automatically.

This behavior, and the settings involved, is actually quite similar to how Outlook handles S/MIME as well.

How to manage individual message signing and encryption? It is very user unfriendly to sign and encrypt individual messages, as you need to make a change in general settings-> mail, contacts… every time

Share
26Oct/110

How to Create your PKCS12 Certificate

This Library is designed to use a PKCS12 format Certificate file, which includes the Private Key and Certificate in a single container. This page will show you how to generate this file using the Certificates you downloaded from iPhone Developer Program Portal in either OSX's Keychain or using OpenSSL.

Details

OSX Keychain

After you've created the appropriate Push Notification Certificate in iPhone Developer Program Portal you should have downloaded a file named something like apn_developer_identity.cer. If you have not done so already, you should open/import this file into Keychain, into your login section.

Finally, if you filter Keychain to show your login container's Certificates, you should see your Certificate listed. Expand the certificate, and there should be a Key underneath/attached to it.

Right Click or Ctrl+Click on the appropriate Certificate and choose Export. Keychain will ask you to choose a password to export to. Pick one and remember it. You should end up with a .p12 file. You will need this file and the password you picked to use the Notification and Feedback Libraries here.

OpenSSL

Here is how to create a PKCS12 format file using open ssl, you will need your developer private key (which can be exported from the keychain) and the CertificateSigningRequest???.certSigningRequest (Note your filename may differ)

  1. Convert apn_developer_identity.cer (der format) to pem:

openssl x509 -in apn_developer_identity.cer -inform DER -out apn_developer_identity.pem -outform PEM

  1. Next, Convert p12 private key to pem (requires the input of a minimum 4 char password):

openssl pkcs12 -nocerts -out private_dev_key.pem -in private_dev_key.p12

  1. (Optional): If you want to remove password from the private key:

openssl rsa -out private_key_noenc.pem -in private_key.pem

  1. Take the certificate and the key (with or without password) and create a PKCS#12 format file:

openssl pkcs12 -export -in apn_developer_identity.pem -inkey private_key_noenc.pem -certfile CertificateSigningRequest??.certSigningRequest -name "apn_developer_identity" -out apn_developer_identity.p12

Share
25Oct/110

A tutorial of using Git inside your XCode Project

From: http://www.icodeblog.com/2011/03/23/using-git-versioning-inside-your-xcode-project/ by (ELC)

his tutorial will show you how to automatically fill in CFBundleVersion and CFBundleShortVersionString, when using Git.
This has been tested in Xcode 3.2.5 (Updates for Xcode 4 at the bottom)

Git Setup
First off you need a project that is checked into git, and is also tagged with an initial version number.

If you already have git setup for your project, skip down to XCode Setup

To locally setup up git, without a remote repository, after installing git, issue the following commands
cd into your project directory
and type “git init”
create a file in this directory called “.gitignore” and add the following lines to it

# xcode noise
build/*
*.pbxuser
*.mode1v3
xcuserdata

# auto git version noise
InfoPlist.h

# old skool
.svn

# osx noise
.DS_Store
profile

Then you can type:

git add *
git add .gitignore
git commit -a -m "Initial Version"

To make the first commit.

Type the following to give us our initial version tag

git tag -a "0.0.1" -m "Version 0.0.1"

When tagging, for this script to work, you should be using the form X.Y.Z, where X,Y, and Z are all numbers.

XCode Setup
Now that we have a local Git Project, or if you are already used to git and skipped to here, we can set up our project to auto generate our CFBundleVersion and CFBundleShortVersionString

Right click on Targets, and select Add -> New Target
Choose Shell Script Target
Enter a name. I chose GenGitVersion
Close the Target “GenGitVersion” Info screen that popped up, and expand the GenGitVersion under Targets in the Groups & Files view.
Double click on Run Script to open the “Run Script Phase for “GenGitVersion” Info” Screen.

Paste the following into the “Script” Section

git=/usr/local/git/bin/git
touch Info.plist
version=`$git describe --dirty`
version=`echo $version | sed 's/[a-zA-Z]*//'`
versionNum=`echo $version | sed 's/\-[0-9]*\-[a-zA-Z0-9]*//'`
echo "#define GIT_VERSION $version" > InfoPlist.h
echo "#define APP_VERSION $versionNum" >> InfoPlist.h

 

Change Info.plist to the name of your Info.plist, and also the git= string to the location of git on your system.
This script will use the “git describe” command to take the name of the latest tag you have committed of the form 0.0.0 and create a short version string of the form 0.0.1-X-abcdefgh-dirty, where the 0.0.1 is the latest tag, -X is the number of commits since that tag, and the -dirty is whether you have committed all your latest changes or not. The version string created by this script will just be the latest tag name, for example 0.0.1.

If you used my .gitignore, then you already have InfoPlist.h added, otherwise add InfoPlist.h to your .gitignore
Right click on your main Target and choose Get Info
Under the General Tab, you want to add the GenGitVersion Target as a Direct Dependent of your main Target
You would do this by clicking the + sign under the Direct Dependencies section and choosing GenGitVersion, and then clicking Add Target.

Under the Build tab, you also need to select, Under Packaging, the checkbox for “Preprocess Info.plist File”, and right above that make sure to enter in InfoPlist.h as the “Info.plist Preprocessor Prefix File”

The last thing you need to do is change your Info.plist file to use the following for CFBundleVersion and CFBundleShortVersionString
CFBundleVersion = APP_VERSION
CFBundleShortVersionString = GIT_VERSION

Now when you use the following in your application, you will have git populating the strings, based on the version numbers of the latest tag and commits.

NSString *shortVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];

NSLog(@"Short: %@", shortVersion);
NSLog(@"Version: %@", version);

Xcode 4 Changes
There is not a Shell Script Target anymore in Xcode 4, unless you are opening an Xcode 3 project inside Xcode 4, however what I found to work is to create a new Aggregate Target, and in this target you can, under Build Phases, Add A Build Phase of the type, “Add a Run Script”. This gives you a “Run Script” section to place the script. You then set this aggregate target as a Target Dependency of your main Target, which will run the script before your main target is built.

Share
25Oct/110

Failed with PKI

PKI? CA or RA :)

I got the key, but the communication is broken. sad. :)

This is a secure message. :)

 

Share
Filed under: Other No Comments
25Oct/110

Using reflection in Objective-C

// Without reflection
  Foo *foo = [[Foo alloc] init];
  [foo hello];
  // With reflection
  Class cls = NSClassFromString(@"Foo");
  id foo = [[cls alloc] init];
  SEL selector = NSSelectorFromString(@"hello");
  [foo performSelector:selector withObject:nil];

Declared Properties in The Objective-C Programming Language

Property Type String

 

 

Share
24Oct/110

NSLog log function name, file name and line number

NSLog(@”[%s:%s:%d] log is here”,__FUNCTION__,__FILE__,__LINE__);

Share
24Oct/110

Regular Expression for objective-c function name

Retrieving all functions in an Objective C file

In a simplified example, an objective C function may have two forms:

  1. - (IBAction)nameofthefunction:(id)parameter
  2. - (void) nameofthefunction

We will try to make a pattern from those forms:

  • Hyphens and parentheses have special meanings in regular expressions, hence we need to escape them, i.e. to put before each of them a backslash, so that they will be interpreted as normal characters.

    Thus, - ( is matched by: \- \(

  • IBAction or void are a non empty sequence of alphabetical characters. We have already seen something similar in the previous example.

    They are matched by: [a-z]+, that is one or more characters in the range of a to z.

  • Another parenthesis matched by: \).
  • A space or no space at all, it is matched by: *, that is a space followed by an asterisk, which means 0 or more times the preceding character.
  • A non empty sequence of characters, matched by [a-z]+ as already seen.
  • A colon or no colon at all, which is matched by: [:]*.

Thus the whole POSIX regular expression is: \- \([a-z]+\) *[a-z]+[:]*

Share
24Oct/110

OCMock static library

Logic tests and application tests

Apple distinguishes two different types of tests: logic tests and application tests. In a nutshell, logic tests run just like normal unit tests, but are severely limited in functionality they can use from frameworks like UIKit; trying to get a font, for example, causes a crash. Application tests are a bit harder to set up and can only run on the actual device but have full access to all functionality. For more detail on the test types and how to set them up for a project please readthis section of the iOS Development Guide.

OCMock fully supports both types of tests. For projects that require only logic tests the OCMock framework can be used in the same way it is used for OS X development. Detailed instructions on how to set up OCMock in this way for an iPhone project can be found in Colin Barrett's tutorial. If you need application tests you have to use the static library instead of the framework, which is described in the next few sections.

OCMock static library

The OCMock Xcode project contains additional targets that build a static library of OCMock. When a test project links against this library (and not the framework) the OCMock classes are included in the binary itself, which means they can be run on an iOS device. The default library is built "fat", containing binary code for i386, which is required for the simulator, and armv7, which is required for running on the device. Thus, if a project requires both logic and application tests, it can do this by using the same library; the framework is not needed for either of them.

To use the library in an iOS project, you have to make the actual library, ie. libOCMock.a, as well as the header files available to the project containing the tests. One way of achieving this is to copy the library and headers into a directory named "Libraries" in the project directory (this does not exist by default) and then adding the following flags to the project:

HEADER_SEARCH_PATHS = $(PROJECT_DIR)/Libraries/Headers
LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/Libraries"

Due to some issues, which are described in this Apple Technical Q&A, you also have to add the following flags:

OTHER_LDFLAGS = -ObjC -force_load $(PROJECT_DIR)/Libraries/libOCMock.a

If you have copied the library or headers to a different place all of these settings must be adjusted accordingly.

Share