Downloading PKPass in an iOS custom app from my server
Asked Answered
W

3

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"]]];
Wersh answered 24/6, 2013 at 13:48 Comment(2)
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.Madalynmadam
colors are defined as: "backgroundColor" : "rgb(25,143,133)", "foregroundColor" : "rgb(255,255,255)",Wersh
W
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.

Wersh answered 25/6, 2013 at 13:8 Comment(0)
K
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()
Kooky answered 13/3, 2017 at 10:37 Comment(0)
M
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                     
                                         }
            ]; 
        }
    }
}];    
Madalynmadam answered 25/6, 2013 at 1:27 Comment(4)
the weird thing is that the exact same code I've posted is working in a fresh new project...Wersh
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.Madalynmadam
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?Wersh
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.Madalynmadam
W
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.

Wersh answered 25/6, 2013 at 13:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.