Static Libraries & Workspaces

November 29th, 2011 by Ricardo Silva No comments »

They say that you should not duplicate your code, but when it comes to iOS development what I see is a lot of duplicated files from third party libraries… For example, JSON and ASIHTTPRequest. So we end up with loads of duplicated files or, if not duplicated, very similar, differing in version.

Static Libraries would help the programmer with this problem.

To create your static library project, you choose the Cocoa Touch Static Library template under Framework & Library. What you need to note about this project is:

  • Set the headers (you want to be public) to public. This can be set during the Copy Headers under Build Phases of your static library target.
  • Set the Installation Directory to $(BUILT_PRODUCTS_DIR).
  • Skip Install should be set to Yes.
  • Public Headers Folder Path should be set to $(TARGET_NAME).

This project can then be used by other projects. I recommend you to set up a workspace for this. You can either save a current project as a workspace or create a workspace and drag and drop your project (the .xcodeproj file) to it. Be careful when you drag the static library project not to drag it inside another project. It should be at the same level of the main project.

Then, follow these steps for your project:

  • Add your library to Link Binary With Libraries.
  • Set User Header Search Paths to $(BUILT_PRODUCTS_DIR) recursively.
  • You may need to add -ObjC to Other Linker Flags if you use categories. You may also need to add -all_load and -force_load in some situations.

Automatic Reference Counting and Frameworks

October 12th, 2011 by Ricardo Silva No comments »

ARC is a compile-time technology, which actually results in a notable performance benefit. The compiler generates calls to retain/release/autorelease on your behalf, instead of you inserting them manually. Nothing new happens at run-time, which is why ARC can be enabled/disabled on a file-by-file basis when compiling an Xcode project.

If you need to use other third party frameworks that are not available as static libraries and don’t support ARC in projects supporting ARC, you can specify compile flags per files.

With Xcode 4.2, you can use -fno-objc-arc only for the framework, like JSONKit, for example.

Steps:

  1. Select project;
  2. Select target;
  3. Open “Build Phases” tab;
  4. Open “Compile Sources (nn items)”;
  5. On second column, you can specify “Compiler Flags”. Set to -fno-objc-arc for each file you want.

Good bye, EXC_BAD_ACCESS!

August 28th, 2011 by Ricardo Silva No comments »

The EXC_BAD_ACCESS error means that a message was sent to a point in the memory where there’s no instance of a class to execute it. Thus “bad access”. Most of the times, the message was sent to an abject that has been already released or was never initialised.

In the over released objects situations, zombies are very handy… When you enable this feature, a dummy object (a zombie) is kept on the place of every released object, allowing to debug objects which were released already. To enable the zombies, edit the scheme: in “Run”, open “Arguments” tab and add NSZombieEnabled with value YES in the “Environment Variables” section. Voila!

Important: remind not to leave the zombies enabled when you submit your app to the App store. Also, it’s a good practice to disable them if you don’t really need them.

Correct use of MapKit

June 24th, 2011 by Ricardo Silva No comments »

I’ve seen some apps being rejected because MapKit was used in a way it violates the Google’s terms of service for Maps. Commonly it is because the Google logo is hidden or covered.

When using MapKit you need to make sure that Google logo will be visible always. You can prevent it being hidden by resizing operations using the following resizing mask:

mapView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);

Presenting HttpServletResponse as file download

June 17th, 2011 by Ricardo Silva No comments »

The following code will present the response as a file to be download instead of being displayed in the browser. The key here is the Content-disposition header.

protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException
{
	byte[] data = null;
	// load data
 
	resp.reset();
	resp.setContentType("image/png");
	resp.setHeader("Content-disposition", "attachment; filename=image.png");
 
	final OutputStream output = resp.getOutputStream();
	output.write(data);
	output.close();
}

Conditional Compilation

June 16th, 2011 by Ricardo Silva No comments »

Sometimes you need different settings for different purposes (for example, when you’re testing your app). You could use a server for development and another for production, try to do something hard code when you are testing In App Purchases or something else…

Conditional compilation is very useful in these scenarios. While blocks of “if” from programming languages are part from the binary file but only one block is executed at time (but both could be, in different moments), the conditional “if” is executed during compilation and so the negated block won’t be part of te binary file.

You need to add a compilation flag in your project settings. In the example below, the flag -DDEBUG_BUILD was added to the target settings.

#ifdef DEBUG_BUILD
    #define SERVER_URL_STRING @"http://development.server.com"
#else
    #define SERVER_URL_STRING @"http://production.server.com"
#endif

NSLog(“Hello world!”)

May 27th, 2011 by Ricardo Silva No comments »

Everybody knows logging is an import step during any software development, specially in the debug phase. However, its removal can be very tricky after the debug phase is finished and logging is no longer needed and you might need to get rid of it. That’s when macros are very helpful…

#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif
 
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

With the code above, you can use DLog to log only while debugging and ALog to log always.

You can put this code to your .pch file or creat a new file (for example, Log.h) that you can reuse among various projects and import it whenever you need or in the .pch file again.

#import “Log.h”

For this to work you need to add the -DDEBUG flag in the “Other C Flags” option in your project’s configuration.

Another simpler way would be:

#ifdef DEBUG
#	define DLog(...) NSLog(__VA_ARGS__)
#else
#	define DLog(...) /* */
#endif
#define ALog(...) NSLog(__VA_ARGS__)