Absolute Ripple
  • Absolute Ripple
  • Contact

Printing documents, images, etc in iOS

25/3/2012

0 Comments

 
Once you have implemented the ability to open a files in another app using the UIDocumentInteractionController (as described in the previous post), it doesn't take that much effort to enable printing. You essentially only need to implement two further methods in the UIDocumentInteractionController delegate protocol. (The following assume that you have already implemented UIDocumentInteractionController as described in the previous post.)
The additional codes are:
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller canPerformAction:(SEL)action
{
    if (action == @selector (print:) &&
        [UIPrintInteractionController canPrintURL: controller.URL]) {
        return YES;
    } else {
        return NO;
    }
}

- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller performAction:(SEL)action
{
    bool __block success = NO;
    if (action == @selector(print:)) {
        UIPrintInteractionController *printController = [UIPrintInteractionController sharedPrintController];
        printController.printingItem = controller.URL;
        [printController presentAnimated:YES
                       completionHandler:^(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error){
                           if (completed) {
                               success = YES;
                           } else {
                            NSLog(@"The print job did not complete.");
                           }
                       }];
    }
    return success;
}

The first method tells the UIDocumentInteractionController whether certain actions can be performed in respect of the document. The default response is 'NO'. In this case, we are telling the controller that printing is supported.
The second method is called by the controller when it wants its delegate to perform a particular action, such as printing action here.
Both of these methods make use of a class called UIPrintInteractionController, which handles the printing for you. All you need to do (as done above) is to pass it the document's url.


0 Comments

Opening files in another app

19/3/2012

4 Comments

 
It is relatively simple to get another app (a third party or one of Apple's apps) on the iPhone or iPad to open a file. The magic is mostly done by Apple in the UIDocumentInteractionController Class.
This class is part of the UIKit framework, which is included by the default xCode project setup so there is no need to link any additional framework.
This is what you need to do in terms of code:
1. Make your relevant class file conform to the UIDocumentInteractionControllerDelegate protocol and define a variable
Assuming your class is called ViewController, then in the ViewController.h file:
        @interface ViewController : UIViewController <UIDocumentInteractionControllerDelegate>
        {
            UIDocumentInteractionController *docController;
        }
2. Add the following methods in ViewController.m:
        //- set up the UIDocumentInteraction controller and set its delegate to self so we can handle the callback events
        - (UIDocumentInteractionController *) setupControllerWithURL:(NSURL *)fileURL
                                               usingDelegate:(id <UIDocumentInteractionControllerDelegate>)         interactionDelegate {
   
            UIDocumentInteractionController *interactionController =
            [UIDocumentInteractionController interactionControllerWithURL:fileURL];
            interactionController.delegate = interactionDelegate;
   
            return interactionController;
            }
       
        //- the key instance method here is the presentOptionsMenuFromBarBUttonItem
        //- it is assumed here that there is a BarButtonItem called _btnActions
        - (void)showOptionsMenu
        {
            NSURL *fileURL = [NSURL fileURLWithPath:@"THE_FILE_URL_PATH"];
            docController = [self setupControllerWithURL:fileURL
                                   usingDelegate:self];
            bool didShow = [docController presentOptionsMenuFromBarButtonItem:_btnActions
                                                             animated:YES];
            if (!didShow) {
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
                                                        message:@"Sorry. The appropriate apps are not found on this device."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles: nil];
                    [alert show];
            }
        }
3. Add a method to invoke the above when you want to show the apps that you could send the file to
In this example, a UIBarButton is wired up to the following IBActions:
    - (IBAction)ActionButtonClicked:(id)sender {
        [self showOptionsMenu];
    }
That is it. When the button is clicked an action sheet will appear (all powered by the Apple's UIDocumentInteractionController class) that shows the apps (if any) that you could send the file to.

You can optionally implement the following delegate methods:
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
- (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller
4 Comments

Generating PDF in iOS

15/3/2012

0 Comments

 
The ability to export a PDF document, created using data generated through the app, can be a useful feature to have in an app.  There are a number of ways to create the PDF:
(i) External way - the PDF document can be created with the help of a server. In this case, the app simply send the data (suitably structured) to a server which generates the PDF file using some server side script. Once the file is generated, it can be sent back to the app for further actions, such as forwarding it via email to someone. Indeed, the server could send the file directly to whomever.
(ii) Internal way - the PDF document is generated within the app on the iPhone or iPad (without involving an external server).
Which way is better depends on your requirements. The involvement of a server is sometimes necessary if you need to combine external data to create the PDF document. An external server may be more efficient if the document is complex or large.
This note is about the internal way.
Generating PDF directly on the iPhone and iPad
PDF document can be created in iOS. The Quartz 2D drawing engine is developed with PDF document creation, display and parsing in mind. The process of creating a PDF document is perhaps not as obvious as other things in iOS, but it is certainly not difficult and you can create nice looking document just by knowing a few things.
There are two ways to generate a PDF document on iOS:
(i) Use Core Graphics functions; and
(ii) Use UIKit framework.
The UIKit framework is certainly much easier to use that calling Core Graphics functions, but the latter could be more flexible and powerful. Again, the better approach depends on your requirements and it can be matter of personal taste.
This is an excellent online tutorial: Generate PDF programmatically in iPhone/iPad SDK. It shows you how to draw lines, border, text and image.
For those who like to write even less code and leverage the graphical user interface of Interface Builder, you can use UILabel to display text on the PDF document. Here is how.
A Simple Example
This example creates a landscape page with an image on the left and some text on the right hand side.
1. Create a UILabel object in Interface Builder. i.e. simply drag a UILabel object onto the view controller in Interface Builder.
2. Create the setter and getter for this label in the class files of the view controller using the standard @property and @synthesize technique, i.e.
        @property (strong, nonatomic) IBOutlet UILabel *textLabel;
        @synthesize textLabel = _textLabel;
(Remember to connect this to the actual UILabel in Interface Builder. As an aside, it is quite easy to forget to do this, at least I often do. This is why I prefer to let xCode creates the @property and @syntheize code automatically by using the 'control click and point' technique. Another advantage of this approach is that xCode will add the relevant memory management code automatically too - one less thing to do).
3. Enter the following codes in viewDidLoad:
    // defines the path for the saved pdf file
    NSString *docDirectory =
        [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *pdfPath = [docDirectory stringByAppendingPathComponent:@"pdfFile.pdf"];

    // set the size of the page (the page is in landscape format)
    CGRect pageBounds = CGRectMake(0.0f, 0.0f, 792.0f, 612.0f);

    // sets the size and position of the image and text
    CGRect imageBounds = CGRectMake(30.0f, 50.0f, 500.0f, 375.0f);
    CGRect textBounds = CGRectMake(550.0f, 50.0f, 182.0f, 375.0f);

    // create an UIImage object using a photo named "sampleImage.jpg"
    UIImage *theImage = [UIImage imageNamed:@"sampleImage.jpg"];
    // set the text
    _textLabel.text = @"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.";
   
    // create and save the pdf file
    UIGraphicsBeginPDFContextToFile(pdfPath, pageBounds, nil);
    {
        UIGraphicsBeginPDFPage();
        [theImage drawInRect:imageBounds];
       
        [_textLabel drawTextInRect:textBounds];
       
    }
    UIGraphicsEndPDFContext();

4. One final step. Select the UILabel in Interface Builder, and in the Attribute Inspector, make sure that the attributes are set with the following values:
    Lines: 0   (setting to zero means that it is unbounded)
    Line Breaks: Character Wrap
    Font: System 14.0  (you can use other size or font)
    Text Color: (use default or pick a color)

Run the code in the Simulator and the PDF file will be saved inside the app's Documents folder. You can then add code to email or do whatever you want with the PDF file.

Drawing an NSString directly to the pdf context is more flexible, but an advantage of using UILabel as describe here is that it allows you to change the font, size, style, color, etc graphically in Interface Builder. This can be quite useful when you want to knock up something fast. Doing similar using NSString requires more coding and, as far as I know, you cannot simple things like 'bolding' the text without using Core Text and NSAttributedString (which is not that friendly to use). Again, the better approach to use depend on your requirement.


0 Comments

Making the Popover View Modal

2/3/2012

0 Comments

 
By default, popover view is dismissed when the user clicks anywhere outside of the view. Depending on your context, this may or may not be a desirable UI behavior.
You can make the popover view modal. Doing so prevents the user from clicking outside the popover view to dismiss the view. Of course, under this approach, you need to provide a mechanism to dismiss the popover.

The following assumes that we have a view (whose class is viewController) where a 'button' is located, and on clicking this button a popover view appears. This popoverview's class is popoverViewController.
1. Inside @implementation of the popover viewcontroller class file,
    - (void)viewDidAppear:(BOOL)animated
    {
        self.modalInPopover = YES;
    }
Note: self.modalInPopover must be in viewDidAppear. It won't work in viewDidLoad. Setting this property to 'YES' makes the view modal.

2. Create a protocol
Inside the popover view controller .h file, before @interface,
    @protocol PopoverViewControllerDelegate;
Under @interface, create a property,
    @property (nonatomic, weak) id<PopoverViewControllerDelegate>delegate;
After @end,
    @protocol PopoverViewControllerDelegate <NSObject>
    - (void)PopoverViewController:(PopoverViewController *)controller didClick:(BOOL)clicked;
    @end
Next, synthesize the delegate. Inside the controller .m file, after @implementation,
    @synthesize delegate;

3. You need to create a button that the user can click once they are finished doing whatever they need to do inside the popover view. This can be a button that triggers further actions such as saving some information that the user has entered or a 'cancel' button. But you need to provide a button as this allows you to link it to the mechanism that dismisses the popover.
Assuming that it is a 'Done' button, you could have a method like this in the popover view controller class file:
    - (IBAction)btnDone:(id)sender {
            [[self delegate] PopoverViewController:self
                                      didClick:YES];
    }

4. You need to obtain a reference to the popover segue so that you can dismiss the popover.
Under @interface of viewController.h,
    @property (strong, nonatomic) UIStoryboardPopoverSegue* popSegue;
Synthesize this property in viewController.m,
    @synthesize popSegue = _popSegue;
Inside (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender,
    if ([segue.identifier isEqualToString:@NAME_OF_YOUR_SEGUE]) {
        self.popSegue = (UIStoryboardPopoverSegue *)segue;
    }

5. Finally, you need to implement the protocol inside the viewController class.
Import the header for PopoverViewController,
    #import "PopoverViewController.h"
Make this class confirms to the PopoverViewControllerDelegate protocol, by adding <PopoverViewControllerDelegate> after @interface, such that it looks something like:
    @interface ViewController: UIViewController <PopoverViewControllerDelegate>
Add the protocol method insider @implementation
    - (void)PopoverViewController:(PopoverViewController *)controller didClicked:(BOOL )clicked
    {
        if ([self.popSegue.popoverController isPopoverVisible])
        {
            [self.popSegue.popoverController dismissPopoverAnimated:YES];
        }
    }
0 Comments

Using Custom URL Scheme to Launch Application

17/2/2012

2 Comments

 
I first came across this thing called Custom URL Scheme when I was going through the Facebook SDK, which uses it to reopen the app after the user has finished signing-in using mobile Safari during the Single-Sign-On (SSO) process. This is such a useful technique. To launch your app all you need to do is to define a Custom URL Scheme and use this scheme in the browser to trigger the launching of your app.

Defining the Custom URL Scheme (in xCode 4.2)
1. Go to you app info.plist. Add a new row and choose "URL types" as the key (if it doesn't already have this key - by default, it is not there unless you are editing someone else app which already have a URL Scheme defined).
2. Expand 'Item 0' and add in 'URL identifier' from the list.
3. Provide a value for this URL identifier. It can be anything. Although the convention is to use the reverse domain name style, e.g. com.absoluteripple.appname. (I am unclear as to the significance of this identifier as the URL scheme can be used to launch the app with or without this identifier as far as I can tell from my limited testing.)
4. Add another row, and choose 'URLSchemes' from the list. Now, the important bit. Provide the name that will become your custom URL scheme. If you put down 'myappname', then the url scheme will be 'myappname://'.
5. That is it.

Triggering the Launch of your App
Now that you have defined a custom URL scheme, you can use it to launch your app. This is just like any other url and you should (as far as I know) be able to use it like any other url. i.e. instead of 'http://', you use 'myappname://' (or whatever your scheme is). Whereas http:// opens a webpage, myappname:// opens your app. Try it out. e.g. if you type 'myappname://' in the mobile Safari it will open you app (after you have complied your app and put it on the iPhone/ iPad first of course).

Even More Useful:  It can be Used to Send Instructions to your App
Just launching the app is good but not that interesting. You can actually use it to pass variables to your app. How you use those variables is entirely up to you and your imagination. The point is that you can use this to get the app to do certain things. e.g. going to a specific location in your app and display certain information. And all this from an external url link.
The magic happens because of the following method (in the UIApplicationDelegate Protocol):
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
          sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
This method gets called by iOS whenever the app is launched in response to your custom URL scheme.
A particular interesting variable is the 'url'. This is the url that you use to launch the app. As said above, this is just like any url, so it can have component paths. e.g. myappname://your/path/12345
So by structuring the component paths appropriate based on the needs of your app, you can send your app certain instructions and so get it to do things from an external url.
Notice also, you can tell which application is initiating the launch of your app with the values in 'sourceApplication' which is the bundle ID of the requesting app. You can also use the 'annotation' to to pass in information. This a property-list object. This opens the way for another app to communicate with your app.

Note: For iOS4.2 or before you need to use:
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
        (this is now depreciated)

Is the App you wish to launch installed?
From another app you can use [[UIApplication sharedApplication] canOpenURL: [NSURL URLWithString:@"YOUR_CUSTOM_URL_SCHEME"]] to determine whether the app you wish to launch is installed. This results a bool value.
So the code would look like:
    BOOL isAppInstalled = [[UIApplication sharedApplication]
                        canOpenURL: [NSURL URLWithString:@"YOUR_CUSTOM_URL_SCHEME"]];
    if(isAppInstalled) { // launch the app }
    else { // do nothing or send user to app store to download the app }

Is it possible to tell whether an app is installed from a browser? Don't know how or even if this is possible.

Useful Reference:
  • code samples for common URL schemes

2 Comments

Diabling Automatic Reference Counting (ARC) in selected class files

15/2/2012

0 Comments

 
Scenario: You are using Automatic Reference Counting (ARC) in iOS 5 for your project, but you are also using some old class files or open-source libraries that are not ARC compliant. Your project won't compile.

Solution: Disable ARC on those files that are not ARC compliant by inserting a compiler flag. (Of course, the onus is then on you to ensure that those files adopt the appropriate memory management practice.)

To disable ARC on a per file basis:
1. Select the project in the Project Navigator
2. Select the relevant Targets (there should just be one if you have just created the project)
3. Click "Build Phases" tab along the top on the right hand side
4. Click the "Compile Sources" tab
5. Locate the implementation (.m) file you want to disable ARC and double click it
6. Type or paste in "-fno-objc-arc" on the dialog box that appears

0 Comments

Removing the icon gloss effect in iOS 5

14/2/2012

0 Comments

 
Simply, set "Icon already includes gloss effect" under "Primary Icon" under "Icon files (iOS 5)" in info.plist to YES.

Note:
- "Icon already includes gloss effect" MUST be under "Primary Icon" for this to work. I I was lost for awhile and unable to remove the gloss effect until I realize this!
- You may also need to delete the app from the Simulator/devices and perform a clean build (Product > Clean) for the changes to show up.
0 Comments

Link to app in the Apple app store from inside your app

13/2/2012

0 Comments

 
Create a helper method:
- (void)openWithLink:(NSString *)urlLink
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlLink]];
}

Call the method:
[self openWithLink:@"THE_LINK"];

Replaces THE_LINK with the actual link, which can take a number of forms:

1. (Link directly to the app - method 1) http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=YOUR_APP_ID        e.g. http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=498871441
2. (Link directly to the app - method 2) http://itunes.apple.com/app/idYOUR_APP_ID
   e.g. http://itunes.apple.com/app/id488561581
3. (Link directly to the app - method 3) http://itunes.com/apps/YOUR_APP_NAME
    e.g. http://itunes.com/apps/memorable
4. (Link to your company) http://itunes.com/apps/YOUR_COMPANY_NAME
    e.g. http://itunes.com/apps/absoluterippleptyltd
5. (Link to the rating page of your app)
    NSString *str = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa";
    str = [NSString stringWithFormat:@"%@/wa/viewContentsUserReviews?", str];
    str = [NSString stringWithFormat:@"%@+Software&id=", str];
    //- replace the following with your app id from iTunes Connect
    str = [NSString stringWithFormat:@"%@YOUR_APP_ID", str];

One point to note about all these url scheme is that they can (and do) change. You must test the link out inside your app to make sure it is working.

Optional:
You can replace 'http' with 'items-apps'. e.g. itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=498871441
This will supposedly  open the App Store app directly, whereas the 'http' will first invoke Safari and then redirect to the App Store app. In practice, this doesn't seem to happen all the time.

See: Technical Q&A QA1633 Creating easy-to-read links to the App Store for your applications and company

0 Comments
Forward>>

    Archives

    August 2013
    July 2013
    June 2013
    May 2013
    January 2013
    October 2012
    September 2012
    March 2012
    February 2012

    Categories

    All
    Apple Policy
    In App Purchase
    Ios Programming
    Our Apps

    RSS Feed

    Disclaimers

    Here are some resources that I find useful in writing iOS apps. These are not necessarily unique as they are based on various sources online.
    This is mainly to provide a source of reference to myself and my associates but if it can be of use to someone else, that is good.
    Note that information is provided here as is. Use at your own risk. There is no guarantee that it is accurate. We will update the information as time and resources permit.

    Powered by Create your own unique website with customizable templates.