1

I've setup a server which returns a PKPass. If I copy the URL to the browser, a pass is shown (both in my Mac and in my iPhone). The code I'm using to download the pass is the following one:

NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:kAPIPass]];
if (nil != data) {
    PKPass *pass = [[PKPass alloc] initWithData:data error:nil];
    PKAddPassesViewController *pkvc = [[PKAddPassesViewController alloc] initWithPass:pass];
    pkvc.delegate = self;
    [self presentViewController:pkvc
                       animated:YES
                     completion:^{
                         // Do any cleanup here
                     }
     ];
}

Anyway, when I run this code I have the following error:

* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'

I don't know what is the bug... The pass seems ok when I download it with Safari and even the code seems ok (there are just 3 simple rows...) Someone experienced with Passkit could help me?

EDIT: the weird thing is that the exact same code is working in a fresh new project

EDIT 2: removing the following line from the AppDelegate, remove the crash, that's weird!

[[UINavigationBar appearance] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"navbar_bg_gen.png"]]];
Luca Torella
  • 7,974
  • 4
  • 38
  • 48
  • Can you post a link to your .pkpass bundle? Sounds like you may be using base16 hash values for your coulours, instead of RGB values, but would need to see the pass.json to be sure. – PassKit Jun 24 '13 at 15:06
  • colors are defined as: "backgroundColor" : "rgb(25,143,133)", "foregroundColor" : "rgb(255,255,255)", – Luca Torella Jun 24 '13 at 21:31

3 Answers3

3

Swift 3

Here is the code to download the .pkpass (passbook file) from server with completion handler and show pkpassviewcontroller for further adding into the apple wallet.

import PassKit


let url : NSURL! = NSURL(string: "YOUR .pkpass URL GOES HERE")
        let request: NSURLRequest = NSURLRequest(url:
            url as URL)
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)

    let task : URLSessionDataTask = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in

        var error: NSError?
        let pass = try? PKPass(data: data!, error: &error)
        if error != nil {
            DispatchQueue.main.async {
                let alertView = UIAlertView(title: "Error", message: (error?.localizedDescription)!, delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")
                alertView.show()
            }
        }
        else {
            let passLibrary = PKPassLibrary()
            if passLibrary.containsPass(pass!) {
                DispatchQueue.main.async {
                    let alertView = UIAlertView(title: "Already Exist", message: "This pass already added in wallet. Thanks!", delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")
                    alertView.show()
                    self.hideLoading()
                }
            } else {
                let pkvc = PKAddPassesViewController(pass: pass!)
                pkvc.delegate = self
                self.present(pkvc, animated: true, completion: {() -> Void in
                    // Do any cleanup here
                    self.hideLoading()
                })

            }
        }

    })
    task.resume()
Shoaib Bagwan
  • 413
  • 5
  • 7
2

Your code in it's current state does not make a call to PKAddPassesViewController to present the pass to the user.

Assuming that the Pass Library is available, the following works with the url you provided in iOS6 & iOS7:

NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:kAPIPass]];

if (nil != data) {
    PKPass *pass = [[PKPass alloc] initWithData:passData error:&error];

    if(error) {

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK"otherButtonTitles:nil];
        [alertView show];

    } else {

        PKAddPassesViewController *pkvc = [[PKAddPassesViewController alloc] initWithPass:pass];
        pkvc.delegate = self;
        [self presentViewController:pkvc
                           animated:YES
                         completion:^{
                                      // Do any cleanup here                     
                                     }
        ]; 
    }                       
}

Alternatively, you could load it asynchronously so as not to block the main thread.

[NSURLConnection sendAsynchronousRequest:_request 
                                   queue:_browser 
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    if (nil != error) {
        // handle error
    } else if (nil != data) {
        PKPass *pass = [[PKPass alloc] initWithData:passData error:&error];

        if(error) {

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"OK"otherButtonTitles:nil];
            [alertView show];

        } else {

            vc = [[PKAddPassesViewController alloc] initWithPass:pass];
            pkvc.delegate = self;
            [self presentViewController:pkvc
                               animated:YES
                             completion:^{
                                          // Do any cleanup here                     
                                         }
            ]; 
        }
    }
}];    
PassKit
  • 12,231
  • 5
  • 57
  • 75
  • the weird thing is that the exact same code I've posted is working in a fresh new project... – Luca Torella Jun 25 '13 at 10:20
  • Looking at it, I can see no reason why it shouldn't. May be the error is not Pass Kit related but is being triggered by something else in your original project. – PassKit Jun 25 '13 at 10:30
  • Yes, removing this line [[UINavigationBar appearance] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"navbar_bg_gen.png"]]]; from the appdelegate, everything works again, do you know why? – Luca Torella Jun 25 '13 at 10:35
  • 1
    Sounds like an iOS bug - your `[UINavigationBar appearance]` should either be applied or ignored, depending on how much Apple want to lock down the `PKAddPassesViewController`, but it should not cause a crash. – PassKit Jun 26 '13 at 04:40
0

So the problem was this line in the AppDelegate:

[[UINavigationBar appearance] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"navbar_bg_gen.png"]]];

It seems that the image, which work perfectly till I added passbook, is not liked by the controller displaying the pass.

Luca Torella
  • 7,974
  • 4
  • 38
  • 48