Posts Tagged ‘objective c’

I’ve recently been playing around with delegates and protocols and figured, it might be a good idea to create a simple example. The following article will show you, how you could implement a custom delegate into your own XCode project.

First, why would you want to do this? Well, there are a number of reasons. For instance, picture this: You have a class, that takes care of some calculations. Depending on how complicated these are, they can take up more or less time. Once the calculations are done, you want to send a feedback message to the class, that triggered the process. Using a custom delegate will allow you to receive that message without implementing the calling class into your calculations class. The big advantage is, that you will be able to use your calculations class in any class, send feedback message through the delegate and keep your code nice and clean.

Let’s get started, shall we?

In my sample project, I start off with a “View-based Application” template. It will give me the basic view hierarchy I need and I can get right to the fun part :)

I create a new “Objective-C” class (subclass of NSObject), name it “DelegateClass” and add it to my project. I now got two new files: DelegateClass.h and DelegateClass.m. Now I can start creating my delegate right away.

First, I want to add a protocol for my delegate. The protocol will contain the feedback method:

@protocol MyCustomDelegate <NSObject>

- (void)delegateSentFeedback;

@end

Now, I create an instance of my delegate inside @interface:

@interface DelegateClass : NSObject {
    id<MyCustomDelegate>    delegate; //create instance
}

I also need a method, that will do something. Therefore I name it “doSomething”:

- (void)doSomething;

Finally, I add @property for the delegate, so it can be assigned from any class:

@property (assign) id<MyCustomDelegate> delegate; //@property, so delegate can be assigned from any class #importing "MyCustomDelegate.h"

Inside DelegateClass.m I need to do two things:
Synthesize the delegate:

@synthesize delegate;

and add the doSomething method:

- (void)doSomething {
    if (delegate != nil && [delegate respondsToSelector:@selector(delegateSentFeedback)]) { //only trigger method IF delegate has been assigned and the method has been implemented into the target class

        //do something and then send callback message
        for (int i = 0; i < 10000; i++) {
            printf("I'm busy, I'm doing something");
        }
        [delegate performSelector:@selector(delegateSentFeedback)];
    }
}

The IF-Statement will make sure, that the delegate has been assigned from the calling class and that the calling class will implement the feedback method, named “delegateSentFeedback”.
Now, I move over to my viewController. I add a UIButton to start some process upon “TouchUpInside”. I connect it to an IBAction and end up with something like this:

- (IBAction)startProcessAction:(id)sender {
    DelegateClass *class = [[DelegateClass alloc] init];
    class.delegate = self; //IMPORTANT: if you don't assign the delegate, the feedback method will NOT be triggered!
    [class doSomething]; //start process
    [class release];
}

Btw, let’s not forget to #import “DelegateClass.h” into our ViewController’s .h file!
Last, but not least I implement the delegate feedback method, defined inside DelegateClass.h

- (void)delegateSentFeedback {
    //the process is done. let's show a simple UIAlertView
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success" message:@"The process is done! Delegate has successfully sent feedback" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alert show];
    [alert release];
}

The feedback method will show an UIAlertView, once “doSomething” method inside DelegateClass.m has reached the bottom.
Piece of cake, right?


Feel welcome to grab the sample project here, play with it, add new feedback methods and most importantly HAVE FUN! :)









In case you’ve ever played around with a sectioned UITableView and tried to delete rows from it, you’ve most likely experienced a crash once in a while.

When you read the console log, most of the time you find an entry similar to this one:

*** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (0) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).’

Usually, your code for deleting stuff from your UITableView will look like this:


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) { //let's delete something from our table
//IMPORTANT - modify data source BEFORE deleting rows from the table
[mySourceArray removeObjectAtIndex:indexPath.row]; //we assume, that mySourceArray is a NSMutableArray we use as our data source

[tableView beginUpdates];

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

[tableView endUpdates];

}

Now, things can get a bit more complicated when using a sectioned UITableView. In my case, I’ve been using a NSMutableArray (filled with NSDictionaries) as data source.
It looked like this:

NSMutableArray ->

……….-> NSDictionary:

………………..-> “headerTitle”: “A”

………………..-> “rowValue”: “RowValue1″, “RowValue2″, etc…

………..-> NSDictionary:

…………………-> “headerTitle”: “B”

…………………-> “rowValue”: “RowValue1″, “RowValue2″, etc…

etc,…

As you can see, a datasource like that is just a bit more complex than values directly inside a NSMutableArray.

In order to avoid the crash mentioned above, I had to make sure, that I only deleted rows from my table, when there were still OTHER rows left inside the same section. In case the row I wanted to remove was the last one within a section, I had to remove the entire section. Btw, that’s exactly what the crash log said :)

Here is my method again, this time with the needed modification:


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) { //let's delete something from our tableNSDictionary *dict = [mySourceArray objectAtIndex:indexPath.section];

NSArray *array = [dict objectForKey:@"rowValue"];

int arrayCount = [array count]; //get the current count of the array
if(arrayCount == 1){ //we are removing the last item from this section - remove the ENTIRE section!

[tableView beginUpdates];

[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    [tableView endUpdates];
}
else { //just delete the row, since we've got more rows left inside this section
    [tableView beginUpdates];
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    [tableView endUpdates];}

}

Hope, you find this helpful. Feel welcome to leave a comment.

Cheers.



Hello everyone,

I’ve recently been playing with UILocalNotifications and really love them. When Apple first introduced Remote notifications (aka. push notifications), they were a real treat to both developers and users. Applications could receive information, even though they were not running at that time. However, it was (still is) a bit painful to implement them. You need to create certificates, run your own server or sign up with some company, that does the message forwarding for you.

Now, in case you only want to remind your users of something or allow them to schedule an event inside your app, UILocalNotifications are what you’ve been looking for. They are quite easy to set up and you don’t have to hassle with certificates, etc…

I’ve decided to release a little class, that easily allows you to schedule an event, delete a specific event or simply delete all events.

Ok, here we go:

My UILocalNotificaionsWrapper class consists of 3 different methods:


+ (void)addLocalNotification:(int)year:(int)month:(int)day:(int)hours:(int)minutes:(int)seconds:(NSString*)alertSoundName:(NSString*)alertBody:(NSString*)actionButtonTitle:(NSString*)notificationID;

+ (void)cancelLocalNotification:(NSString*)notificationID;

+ (void)cancelAllLocalNotifications;

The first method is the most complex one and allows you to submit several different values to customize your notification event:

  • year (integer) – e.g. 2011
  • month (integer) – e.g. 4 (April)
  • day (integer) – e.g. 29
  • hours (integer) – e.g 10 (= 10 am) – use 22 (military time) for 10 pm
  • seconds (integer) – e.g. 0
  • alertSoundName (NSString) – . e.g. nil to use custom sound name or @”NameOfTheSoundInsideYourAppBundle.wav”
  • alertBody (NSString) – e.g. @”This is a LocalNotification”
  • actionButtonTitle (NSString) – e.g. @”view” – This will appear on the button, when your local notification fires
  • notificationID (NSString) – e.g. @”12345″  (has to be unique. you could keep track of your IDs inside an array, dictionary or SQLite database

Now you can simply make a call like this to schedule a new event:


[UILocalNotificationWrapper addLocalNotification:2011 :4 :4 :19 :17 :0 :nil :@"This is a LocalNotification!":@"View":@"12345"];

In order to delete the notification you just scheduled, you could make a call like this:


[UILocalNotificationWrapper  cancelLocalNotification:@"12345"];

Finally, to delete all scheduled notifications:


[UILocalNotificationWrapper cancelAllLocalNotifications];

One more thing…

Don’t forget to add #import “UILocalNotificationWrapper.h” inside the class you are making the calls from and always test on your device (UILocalNotifications don’t work on the simulator)

Grab the source file here and enjoy :)

Feedback always welcome.

 

In my previous blog entry I wrote about Creating a multi page PDF document on iPhone/iPod Touch/iPad with encryption.

One of my readers described a problem, that caused his newly created PDF file to contain strange/weird characters. He actually tried to open an existing PDF document and added a watermark image to every single page.

After doing some research on the internet, I found out, that this issue is quite common. In fact, it has been around for quite some time (2 + years – give or take). Unfortunately, Apple hasn’t yet introduced a fix.

So, I did some more digging and read up on 3rd party libraries. Using those libraries, you can actually create/modify a PDF document without the above issues. Bad news is, that Apple might not approve your app. It’s really up to every single developer, whether he/she wants to go for a solution like that or not. Since I can not simply ask Apple, I decided to rule out that option.

So, what other solutions are left? Well, it certainly depends on the case, but in my and my reader’s situation, the following hack worked:

  1. Open the PDF-document
  2. Render it into an offscreen UIView
  3. Create a new PDF document
  4. Paste the image and add additional information (text/pictures)
  5. Save the new PDF document.

There is of course one major downside. The new PDF document no longer contains the real text, but an image displaying the text. This might turn into a problem, if zooming or copy/paste actions are needed later. However, for just reading, this works great.

For those, who want to see this in action, I’ve uploaded a demo project. Feel welcome to grab it here.

In one of my latest applications, I wanted to allow users to

A) Turn text into a PDF file (multi-page document if needed)

B) Optionally set a password to protect this very PDF file

C) Set permissions to copy/print the PDF file

Since I haven’t played with PDF content creation on the iPhone/iPod Touch/iPad before, I fired up google and discovered THIS source. It was very helpful for understanding multi-page PDF creation. However there were two problems:

  1. The created PDF document ignored the chosen font and size.
  2. It did not contain information on how to password protect the PDF file.

After playing with this code for a while, I discovered a loop hole. If you “Push” your context, you can use the following method to draw a string with the correct font/size:


UIGraphicsPushContext(pdfContext);
    [myNSString drawInRect:bounds withFont:[UIFont fontWithName:fontName size:fontSize]];
UIGraphicsPopContext();

Problem (1) was solved now and after reading Apple’s documentation on PDF file creation, I had an idea how password protection might work as well.

Ok, now that I had all the ingredients, it was time to get this thing up and running.

Before you read on, please keep in mind, that part of the code below has been thrown together, in order to get useful results real quick. I somehow got a feeling, that there is (must be) a more elegant way to do this.

Anyways, here we go…

I created 2 different methods:

1:


- (void) createPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)font andColor:(UIColor *)color:(BOOL)allowCopy:(BOOL)allowPrint:(NSString*)password;

This method accepts the following variables:

  • fileName: the name we want to assign to our PDF file (e.g. “myPDF.pdf”).
  • content: the text (string) we want to write to our PDF document.
  • fontSize: size of our font (9, 10, 12, 14, 16, etc…)
  • font: name of the font, we want to use (e.g. “Helvetica”).
  • color: the color, we want to use (black, blue, etc…)
  • allowCopy: YES/NO – whether we want to allow copy for this document
  • allowPrint: YES/NO – whether we want to allow print for this document
  • passoword: a user defined password to unlock content of the pdf file.

2:


- (NSString *)stringToDraw:(NSString*)fontName:(int)fontSize;

This method will be called from our method (1) and will return a NSString object. More on that later…

Before we take a closer look at method (1), we need to add the following lines to the .m file (right below #import lines), we’re working in:


//defines our default PDF page layout

#define LEFT_MARGIN 25

#define RIGHT_MARGIN 25

#define TOP_MARGIN 35

#define BOTTOM_MARGIN 50

#define BOTTOM_FOOTER_MARGIN 32

#define DOC_WIDTH 595

#define DOC_HEIGHT 842

We also need a NSString object, that will hold some text for us later, a BOOL value, named “done” and a NSMutableArray. Simply create those in your viewDidLoad method or wherever you initialize your class:


//in .h

NSString *tempContentString;

NSMutableArray *textArray;

BOOL done;

@property (nonatomic, retain) NSString *tempContentString;

@property (nonatomic, retain) NSString *textArray;

//in .m

@synthesize tempString;

@synthesize textArray;

- (void)viewDidLoad {

tempContentString = [[NSString alloc] init];

textArray = [[NSMutableArray] alloc] init];

}

- (void)dealloc {

[tempContentString release];

[textArray release];

[super dealloc];

}

Now, let’s assume, that we have a UITextView element, named “myTextView” and this UITextView is filled with text.

Before we call method (1), we need to prepare a few things


- (void)preparePDFCreation {

NSString *fileName = @"myPDF.pdf"; //set whatever name you like

NSString *content = myTextView.text; //this is the UITextView, containing our text.

int fontSize = 20; //set your fontSize here

NSString *font = @"Papyrus"; //set your font name here (Helvetica, Georgia, etc...)

UIColor *myColor = [UIColor blackColor]; //set your color here (blueColor, brownColor, etc...)

NSString *password = @"test"; //set your password

//prepare saving our PDF file to documents directory

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *saveDirectory = [paths objectAtIndex:0];

NSString *saveFileName = fileName;

NSString *newFilePath = [saveDirectory stringByAppendingPathComponent:saveFileName];

tempContentString = content; //we assign our content (text we want to draw to our PDF file) to the tempContentString, we created earlier

BOOL pdfAllowCopy = YES; //allow/forbid copy

BOOL pdfAllowPrint = NO; //allow/forbid print

//important: if you forbid copy or print, you definitely need to set a password. Otherwise it won't work!

done = NO;

[textArray removeAllObjects]; //clean the textArray

[textArray setArray:[content componentsSeparatedByString:@" "]]; //split our text into single words...we will find out why we do this in method (2)

//Now, let's call our method (1)

[self createPDF:newFilePath withContent:tempContentString forSize:fontSize andFont:font andColor:myColor:pdfAllowCopy:pdfAllowPrinting:password];

}

- (void) createPDF:(NSString *)fileName withContent:(NSString *)content forSize:(int)fontSize andFont:(NSString *)font andColor:(UIColor *)color:(BOOL)allowCopy:(BOOL)allowPrint:(NSString*)password {

CGContextRef pdfContext; //our pdfContext

CFStringRef path;

CFURLRef url;

CFStringRef passwordString = (CFStringRef)password;

CGRect pageRect = CGRectMake(0, 0, DOC_WIDTH, DOC_HEIGHT);

CFMutableDictionaryRef myDictionary = NULL; //the dictionary, which will later contain some important meta data, like password, etc...

const char *filename = [fileName UTF8String];

// Create a CFString from the filename we provide to this method when we call it

path = CFStringCreateWithCString (NULL, filename,

kCFStringEncodingUTF8);

// Create a CFURL using the CFString we just defined

url = CFURLCreateWithFileSystemPath (NULL, path,

kCFURLPOSIXPathStyle, 0);

// This dictionary contains extra options mostly for 'signing' the PDF

myDictionary = CFDictionaryCreateMutable(NULL, 0,

&kCFTypeDictionaryKeyCallBacks,

&kCFTypeDictionaryValueCallBacks);

CFDictionarySetValue(myDictionary, kCGPDFContextTitle, (CFStringRef)mainDelegate.rootViewController.writeViewController.titleTextField.text);

CFDictionarySetValue(myDictionary, kCGPDFContextCreator, (CFStringRef)mainDelegate.rootViewController.writeViewController.authorTextField.text);

if (![password isEqualToString:@""]) CFDictionarySetValue(myDictionary, kCGPDFContextOwnerPassword, passwordString);

if (![password isEqualToString:@""]) CFDictionarySetValue(myDictionary, kCGPDFContextUserPassword, passwordString);

if (!allowCopy) CFDictionarySetValue(myDictionary, kCGPDFContextAllowsCopying, kCFBooleanFalse); //kCGPDFContextAllowsCopying is set to TRUE by default

if (!allowPrint) CFDictionarySetValue(myDictionary, kCGPDFContextAllowsPrinting, kCFBooleanFalse); //kCGPDFContextAllowsPrinting is set to TRUE by default

// Create our PDF Context with the CFURL, the CGRect we provide, and the above defined dictionary

pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary);

// Cleanup our mess

CFRelease(myDictionary);

CFRelease(url);

//Now, this is a tricky part. We make use of a do - while loop in order to create as many pages as needed

do {

CGContextBeginPage (pdfContext, &pageRect); //begins a new PDF page

//create layout for our page

CGRect bounds = CGRectMake(LEFT_MARGIN,

TOP_MARGIN,

DOC_WIDTH - RIGHT_MARGIN - LEFT_MARGIN,

DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN);

UIGraphicsPushContext(pdfContext); //pushing the context, as explained at the beginning of this post

CGContextSaveGState(pdfContext);

CGContextTranslateCTM(pdfContext, 0, bounds.origin.y);

CGContextScaleCTM(pdfContext, 1, -1);

CGContextTranslateCTM(pdfContext, 0, -(bounds.origin.y + bounds.size.height));

if ([tempContentString length] > 0) [[self stringToDraw] drawInRect:bounds withFont:[UIFont fontWithName:font size:fontSize]]; //THIS IS THE NASTY PART

CGContextRestoreGState(pdfContext);

UIGraphicsPopContext();

CGContextEndPage (pdfContext); //ends the current page

}

while (!done);

// We are done with our context now, so we release it

CGContextRelease (pdfContext);

CFRelease(path);

}

Now, it’s getting messy. We’re about to explore the “stringToDraw” method. Before we go into detail, let me explain, what this method does.

When we draw text to our page, we have a huge problem. We do not know how much text will fit on a single page. This depends on length of the words used, font and size.

So, I figured, there must be a way to calculate this. And here is what I came up with:

Step by step…

  1. create a CGSize, named tempSize.
  2. create a CGSize, named theTextSize.
  3. use  – sizeWithFont:constrainedToSize: method to determine, whether the text we want to draw, is too big for one page or not
  4. create if/else statements for results of (3)

Here is the complete method with documentation:


- (NSString *)stringToDraw:(NSString*)fontName:(int)fontSize {

CGSize tempSize;

CGSize theTextSize;

tempSize.width = DOC_WIDTH - RIGHT_MARGIN - LEFT_MARGIN; //define width of our document

tempSize.height = 10000000; //we use some unreal number, to make sure our text will definitely fit into this temporary "document"

//now we take the text we want to draw and use the method described in (3) to fit it on our temporary document

theTextSize = [tempContentString sizeWithFont: [UIFont fontWithName:fontName size:fontSize] constrainedToSize: tempSize];

//Depending on length of the text, it will fit on a single page or not.

if (theTextSize.height > DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN) { //the text we want to draw DOES NOT fit on a single page

BOOL pageFilled = NO;

int wordCount = 0;

float currentHeight = 0.0f;

float previousHeight = 0.0f;

NSString *returnString = [[[NSString alloc] init]autorelease];

NSString *tempReturnString = [[[NSString alloc] init]autorelease];

//Now, the following is a bit messy. However, it works :) 

do { //repeat this loop, till our page is filled with words...

if ([textArray count] > wordCount + 1) { //if there are more words inside our textArray than the current word count + 1

returnString = (wordCount > 0) ? [returnString stringByAppendingString:[NSString stringWithFormat:@" %@", [textArray objectAtIndex:wordCount]]] : [NSString stringWithFormat:@"%@", [textArray objectAtIndex:wordCount]];

theTextSize = [returnString sizeWithFont: [UIFont fontWithName:font size:fontSize] constrainedToSize: CGSizeMake(DOC_WIDTH - RIGHT_MARGIN - LEFT_MARGIN, DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN)];

currentHeight = theTextSize.height;

if (theTextSize.height >= DOC_HEIGHT - TOP_MARGIN - BOTTOM_MARGIN) {

pageFilled = YES; // our page is now filled with words

}

if (currentHeight == previousHeight && currentHeight > 700.0f) { //this is a workaround. sometimes the above if statement fails and does not correctly detect a filled page. i noticed, that it happens most of the time, when using large fonts, like zapfino. so, what we do here, is simply check, if the height of our text stays the same when comparing two loops - hence "currentHeight" and "previousHeight". if that's the case and our text height is greater than 700 (look at if statement), we have a filled page.

pageFilled = YES; //page is now filled with words

wordCount --; //we subtract one word from our wordCount, because the filled page has not been correctly detected above

returnString = tempReturnString;

}

wordCount ++; //increase the wordCount

}

else {

pageFilled = YES; //we now have a correctly filled page

}

previousHeight = theTextSize.height; //set previousHeight, so we can compare it when running our next loop

tempReturnString = returnString;

}

while (!pageFilled); //repeat this loop until pageFilled = YES

for (int i = 0; i < wordCount; i++) { //remove all words, we put on our page from our textArray

[textArray removeObjectAtIndex:0];

}

if ([textArray count]) { //if there are words in our textArray

tempContentString = [textArray componentsJoinedByString:@" "]; //update our content string

}

else {

tempContentString = @"";

done = YES;

}

if ([returnString length] == 0) returnString = @" ";

return returnString;

}

else {

done = YES;

return tempContentString;

}

return tempContentString;

}

I’ve successfully implemented this code into my latest app and so far it did a great job. I managed to create PDF files with hundred pages or more in about 3-5 seconds on my iPad.

If you find this source helpful, manage to improve it or have questions/feedback, please do not hesitate to leave a comment.

[UPDATE: I've created a little demo project, showing this code in action. Grab it here.]

If you’re developing an iPhone, iPod Touch or iPad app and get stuck, the internet definitely is your friend. You can find lots of helpful resources on different coding forums or sites like this one.

However, sometimes the information there is just not enough or you might have an idea and don’t know how to get started.
Well, this is where our new service might come in handy.

As of now, you can schedule a 1 on 1 session with one of our coders and he/she will help you.

Sessions will be held via iChat and our coder will share his/her screen with you. This way, you can exactly see what is going on and therefore learn much faster. If you like, we’ll also do a screen recording for free, so you can watch it later again and again at no extra cost.

Some session examples:

* Your first app: How to build proper view hierarchy.
* SQLite database programming.
* Server communication – How to submit and retrieve data from a webserver.
* In app purchases.
* Push notifications.
* 3D game development
* etc…

Our live coding sessions are available in both english and german language.

If you’re interested, just send an email to lindmandesignsupport[at]me.com and we’ll provide you with details on pricing, etc…

Implementing Apple push notifications into your iPhone/iPod Touch or iPad app can be quite the challenging task. You really have to pay close attention to the official docs when setting it up and even then it might not work right out of the box.

If you’re new to APNS, you might want to check out the tutorials, I mentioned in one of my previous posts:

http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/
and
http://mobiforge.com/developing/story/programming-apple-push-notification-services

I can only repeat myself by saying, that these tutorials really rock and should definitely get you started.

If you don’t plan on running your own server, check out Urban Airship. They currently offer two different plans, which should perfectly fit your needs.

However, implementing APNS on your own server is most fun, as you’re likely going to face some issues :)

Rule #1, if nothing you tried so far works: Get some open source package and learn from the professionals: EasyAPNS is exactly what you might want to check out in this kinda situation.

Don’t forget to watch the video tutorial, which can be found right on the landing page.

Some additional hints and suggestions:

If your iPhone/iPod Touch/iPad app communicates with your server (maybe via php scripts), check out ASIHTTPRequest. This is some awsome package, that you can easily integrate into your existing XCode project. It’s perfect for contacting your server via POST requests. However, ASIHTTPRequest can do much more – just check out the official docs, which can be found on the developer’s website.

If you’re testing push notifications with your beta testers, make sure that you’re using the correct APNS certificate on your server. By correct I mean: Development certificate or Production certificate. In case you followed the tutorials above, you probably created both. In order to clear things up, check out the steps below:

  • If your iPhone/iPod Touch/iPad app communicates with your server (maybe via php scripts), check out ASIHTTPRequest. This is some awsome package, that you can easily integrate into your existing XCode project. It’s perfect for contacting your server via POST requests. However, ASIHTTPRequest can do much more – just check out the official docs, which can be found on the developer’s website.
  • If you’re testing push notifications with your beta testers, make sure that you’re using the correct APNS certificate on your server. By correct I mean: Development certificate or Production certificate. In case you followed the tutorials above, you probably created both. In order to clear things up, check out the steps below:
  1. Find your Provisioning certificate and the AdHoc one, you are using for your beta testers: Open up XCode and go to “Window”->”Organizer”. Now click on your Provisioning certificate, then right click -> “Reveal in Finder”. Do the same for your AdHoc certificate.
  2. Open up both files with TextEdit (DON’T EVER CHANGE ANYTHING IN THERE!!!) and look for the following string: “Environment”.
  3. Right below you should see either “Development” or “Production”.
  4. If you want your beta testers to receive push notifications and their AdHoc certificate says “Production”, you now know that you will have to use the APNS Production certificate on your server. Otherwise push messages won’t get delivered.

Happy pushing :)

NSFileManager offers a convenient way to write images to and load them from the documents directory.

If you’re frequently doing that in your project, I suggest to wrap up NSFileManager support in three simple methods:


//saving an image

- (void)saveImage:(UIImage*)image:(NSString*)imageName {

NSData *imageData = UIImagePNGRepresentation(image); //convert image into .png format.

NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it

NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory

NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]]; //add our image to the path

[fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; //finally save the path (image)

NSLog(@"image saved");

}

//removing an image

- (void)removeImage:(NSString*)fileName {

NSFileManager *fileManager = [NSFileManager defaultManager];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", fileName]];

[fileManager removeItemAtPath: fullPath error:NULL];

NSLog(@"image removed");

}

//loading an image

- (UIImage*)loadImage:(NSString*)imageName {

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", imageName]];

return [UIImage imageWithContentsOfFile:fullPath];

}

Now, you can easily save an image like:


[self saveImage: myUIImage: @"myUIImageName"];

or load it like:


myUIImage = [self loadImage: @"myUIImageName"];

or remove it like:


[self removeImage: @"myUIImageName"];

Usually, iPhone apps are built using some kinda hierarchy:

  • ->AppDelegate
  • ->-> RootViewController
  • ->->->OtherViewController(s)
  • ->->->->Views

On various occasions, you might want to get some information from your AppDelegate (e.g. values, array infos, etc…).

You might already know, that there is a simple line of code, which gives you access to your AppDelegate:


AppDelegate *mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];

If you need access to your AppDelegate only once or twice in a View or ViewController, this is the best way to go. However, if you have several methods in your View or ViewController and some of them need AppDelegate access, you always have to repeat the above line of code first.

In order to avoid that, there is a simple way, to permanently implement AppDelegate access in your View or ViewController:


//this example assumes, that we are using a ViewController

//inside .h file

//below #import lines

@class AppDelgate;

@interface MyViewController : UIViewController {

AppDelegate *mainDelegate;

}

//@property (nonatomic, retain) AppDelegate *mainDelegate; //error correction here - no need to @property

@end

//inside .m file

//below #import lines

#import "AppDelegate.h"

@implementation MyViewController

@synthesize mainDelegate;

- (void)viewDidLoad {

mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];

}

- (void)dealloc {

//[mainDelegate release]; //error correction here - the mainDelegate object does not need to be released, since we do not call alloc init on it.

[super dealloc];

}

//now you have access to your AppDelegate in every method

//example: we assume, that our AppDelegate holds three different integer values we want to grab

- (void)methodA {

int numberA = mainDelegate.numberA;

}

- (void)methodB {

int numberB = mainDelegate.numberB;

}

- (void)methodC {

int numberC = mainDelegate.numberC;

}

As you can see, it’s slightly more work to implement AppDelegate access than just using that single line of code over and over again. However, in my opinion it’s well worth the time, especially if your .m file holds many methods.

Your code appears much cleaner that way.

[IMPORTANT: The information below is no longer up to date. Apple does now no longer allow you to use UIGetScreenImage(). Instead you need to use a different method. You can read about that on the official developer forum, located at developer.apple.com]

Not too long ago Apple decided to make on of their private APIs public. They now officially allow developers to make use of a very handy method:

+ (UIImage *)imageWithScreenContents;

Before they released it, grabbing screen contents could be a real nightmare. In some (rare) situations, it was pretty much impossible.
When you were using lots of openGL stuff in your project and wanted to grab the current state of your screen, you had to use glReadPixels();
This worked fine most of the time, but when you were dealing with transparency, it could make you pull your hair off :)

Anyways, those times are finally over.

To make use of this API, simply add the following lines to the .m file where you want to call it later:

//right below #import lines
CGImageRef UIGetScreenImage();
@interface UIImage (ScreenImage)
+ (UIImage *)imageWithScreenContents;
@end

@implementation UIImage (ScreenImage)
+ (UIImage *)imageWithScreenContents
{
    CGImageRef cgScreen = UIGetScreenImage();
    if (cgScreen) {
        UIImage *result = [UIImage imageWithCGImage:cgScreen];
        CGImageRelease(cgScreen);
        return result;
    }
    return nil;
}
@end

Now you can easily do something like this:

- (void)saveScreenshotToPhotolibrary {
	UIImageWriteToSavedPhotosAlbum([UIImage imageWithScreenContents], nil, nil, nil);
}

Congrats! You just saved an image with screen contents to your iPhone photo library.

An App, you might like:
We recommend…
You might also like…
Get Adobe Flash playerPlugin by wpburn.com wordpress themes