Discussion Forums  >  Plugins, Customizing, Source Code

Replies: 16    Views: 129

GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
11/10/12 07:45 PM (13 years ago)

Code, code, and more code!

I'd like to start off by saying that I reek of desperation. Felt good to get that off my chest. I need a hand from the Buzztouch community. My 1st app was released on October 1st and my 2nd app was waiting in review. A couple of days ago, I developer rejected both an update to my 1st app and my 2nd app submission in its entirety. Reason: AirPrint continuously prints the same document regardless of which PDF file is chosen. In fact, for both my apps, it prints the very 1st PDF file found in Xcode. This is the guide I followed to the tee in implementing AirPrint: http://jc-evans.com/blog/2012/07/13/new-tutorial-adding-a-print-button-to-an-app/ I've tried all kinds of code. Being a relative "code noobie", I feel like my efforts for the past 2 days on most hours has equaled to no progress whatsoever. I stumbled upon this guide as well: http://vivianaranha.com/airprinting-tutorial-in-3-steps/ --- But I had little or no luck as well. There are other guides online, but none seem to do the trick. Once more, I stink of desperation and I need to be cleansed! Metaphorically, of course. I'm nearly at the point of pleading over here, you could smell my desperation from a mile away! Sincerely with hope dwindling, Nicholas
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/11/12 12:30 AM (13 years ago)
Hi in Canada. So, the code example you posted (Jeff's) is a good one. But, it makes perfect sense that you're getting the "same" document from the printer each time - assuming you're using this example. Why? Because it clearly shows (clearly to us nerds) what is printing - the first "pdf" it finds in the NSBundle. Consider this: A bunch of PDF's in your project, that code is NSArray *components = [shareTitle componentsSeparatedByString:@"."]; NSString *newString = [components objectAtIndex:0]; NSString *path = [[NSBundle mainBundle] pathForResource:newString ofType:@”pdf”]; NSData *myData = [NSData dataWithContentsOfFile: path]; I'll try to explain: Line 1: "components" is "an array with two parts. The first part is everything to the left of the "." and the second is everything to the right, including the dot. So, components is a two index array. Index 0 (zero) is the file name of the variable shareTitle (whatever that is). Line 2: "newString" is an NSString object that now holds the first part of the two part array, in this case it's probably the file name of the document, without the .pdf Line 3: Path: This is the file path in the project bundle (the Xcode bundle) to the file with this name and type .pdf Line 4: "myData" is an NSData object that gets printed. This just means that I'll be your not changing the value of "shareTitle" - whatever that is. Try this. Instead of using a variable to hold the file name, just hard-code the name of the PDF you want to print. This should prove to you that you can print whatever you want. Like this: NSString *path = [[NSBundle mainBundle] pathForResource:@"myPdfFileName" ofType:@”pdf”]; NSData *myData = [NSData dataWithContentsOfFile: path]; Don't include the .pdf when you enter the file name, just the name itself. If this works, you could the figure out a way to set the file name with a variable that you control.
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 12:52 AM (13 years ago)
Hey in California! I'm happy that at least between the two of us, one of us can clearly understand the code. ;) Thanks for the detailed explanation, I sorta had "some" idea what each function may serve, but this really makes a lot more sense. That being said, I tried replacing: NSString *path = [[NSBundle mainBundle] pathForResource:newString ofType:@”pdf”]; NSData *myData = [NSData dataWithContentsOfFile: path]; with NSString *path = [[NSBundle mainBundle] pathForResource:@"myPdfFileName" ofType:@”pdf”]; NSData *myData = [NSData dataWithContentsOfFile: path]; I receive the following error for the NSString *path line "Expected ';' at end of declaration" By the way, if this did work, then I'm guessing it would only print that one document that I specified (in this case "Bleachers"). Would I have to add this code for each of my 200 PDF files or would there be an alternative method - there must be or surely this is madness! ;) Thanks again, David, I appreciate the small steps in the right direction. Nicholas
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 12:59 AM (13 years ago)
Wait! I might have fumbled on this. Currently testing it out!
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/11/12 01:00 AM (13 years ago)
Yeah, this is step one to make sure you can print something you actually tried to print. Funny. When this works, we'll move on to figure out how to print the .pdf in the currently displayed web view. I've not done much with iOS printing so we're in this together until it works :-) I don't see anything wrong with that path line? But, if I look closely at the forum post, the quotation marks around the pdf look different than the quotations around the myPdfFileName - not sure why? If you copy / pasted this it could be confusing Xcode...try typing the entire line by hand to make sure the quotation marks are the ones coming from your keyboard. Yup...this worked (after fixing those funky quotation marks): NSString *path = [[NSBundle mainBundle] pathForResource:@"myPdfFileName" ofType:@"pdf"];
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 01:03 AM (13 years ago)
Wait! I might have fumbled on this. Currently testing it out!
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 01:07 AM (13 years ago)
Hey David, It was my fault completely on that one, I somehow missed the @ in front of my PDF file name. I'm glad to have the support and firepower behind me on this one! So the code does work in the form that you suggested. Regardless of which document I choose to print, it now prints out the game "Bleachers", which is the name of the game I replaced "myPdffilename" with. ... didn't think I'd be this happy to print out a different game than the one I've been stuck with all along! lol Moving on! :)
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 01:15 AM (13 years ago)
Sorry for the double-post, refreshed the page. :)
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/11/12 01:19 AM (13 years ago)
OK, good. Try to get your head around this. Forget about "pdf" or "html" or "text" or whatever kind of document we humans are used to seeing. iOS print deals with data, as in NSData, as in Binary data. This line: NSData *myData = [NSData dataWithContentsOfFile: path]; is telling iOS, hey, the "myData" variable is of type NSData and it's what I want you to print. This is important because it means we can print any NSData we feel like. And, because we are programmers, we can turn any "file path" into it's NSData counterpart. Have a look at the -(void)loadBundleData method on line 342 (or so) of the BT_screen_pdfDoc.m file. It's using the BT_fileManager to help us find the path to a file in the bundle. All we need to do is pass the file name to this method for the file we are looking for and the BT_fileManager will return it's path. We can then use this path to load up some NSData. Like... NSString *pathToFile = [BT_fileManager getBundlePath:[self saveAsFileName]]; And, because the "saveAsFileName" variable already exists in this class file, it will always equal the name of the file that the UIWebView is displaying. Whoo hoo. You could create a simple print method in your BT_screen_pdfDoc.m class like this: -(void)printFileInBundle{ [BT_debugger showIt:self:[NSString stringWithFormat:@"printing file in bundle: %@", self.saveAsFileName]]; NSString *pathToFileToPrint = [BT_fileManager getBundlePath:[self saveAsFileName]]; //use the BT_fileManager class to see if this file exists (may not be downlaoded yet)... if([BT_fileManager doesFileExistInBundle:saveAsFileName]){ //load up an NSData object from the file path... NSData *printData = [NSData dataWithContentsOfFile: pathToFileToPrint]; //print the data here... } } I'll be this works. All you'll need to do is connect your print button to your new printFileInBundle method and add the "print code" for the myData variable.
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/11/12 01:27 AM (13 years ago)
I'll re-check this tomorrow - it's after midnight here and I'm crashing soon. I think you can take it from here! LOL. re-post to confirm or if you're still stuck :-)
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 01:43 AM (13 years ago)
That was surely a good deal of information to get my head around, but not "too" overwhelming. ;) I understood a good portion of the previous post, but I'm not too sure about the last line. What I did is remove the previous code: -(IBAction)printdoc { NSArray *components = [shareTitle componentsSeparatedByString:@"."]; NSString *newString = [components objectAtIndex:0]; NSString *path = [[NSBundle mainBundle] pathForResource:newString ofType:@”pdf”]; NSData *myData = [NSData dataWithContentsOfFile: path]; UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController]; if(pic && [UIPrintInteractionController canPrintData: myData] ) { pic.delegate = self; UIPrintInfo *printInfo = [UIPrintInfo printInfo]; printInfo.outputType = UIPrintInfoOutputGeneral; printInfo.jobName = [path lastPathComponent]; printInfo.duplex = UIPrintInfoDuplexLongEdge; pic.printInfo = printInfo; pic.showsPageRange = YES; pic.printingItem = myData; void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) { //self.content = nil; if (!completed && error) { NSLog(@”FAILED! due to error in domain %@ with error code %u”, error.domain, error.code); } }; [pic presentAnimated:YES completionHandler:completionHandler]; } } and replaced it with: -(void)printFileInBundle{ [BT_debugger showIt:self:[NSString stringWithFormat:@"printing file in bundle: %@", self.saveAsFileName]]; NSString *pathToFileToPrint = [BT_fileManager getBundlePath:[self saveAsFileName]]; //use the BT_fileManager class to see if this file exists (may not be downlaoded yet)... if([BT_fileManager doesFileExistInBundle:saveAsFileName]){ //load up an NSData object from the file path... NSData *printData = [NSData dataWithContentsOfFile: pathToFileToPrint]; //print the data here... } } For the following line NSData *printData = [NSData dataWithContentsOfFile: pathToFileToPrint];, I receive an issue message "Unused variable 'printData'". I compiled and built the app anyways and ran it through the simulator. When I chose the Print button on any of the documents, the app did not respond and instead Xcode took me to the main.m file. Points to the following line: int retVal= UIApplicationMain(argc,argv,@"UIApplication",@"basketballpe_appDelegate"); With the following message: "Thread 1: Program received signal: "SIGABRT". I suppose I might need some more clarification on the whole connecting the print button to the new printFileInBundle method as well as adding the "print code" for the myData variable - sorry :P As a side note, should I be removing any of the other code used from the previous guide I used? i.e. IBAction, @synthesize ShareTitle, etc.? Yeah... I should be getting to bed as well, 3:45 am here in the East Coast. Chances are I'll be sleeping in. Eagerly anticipating your next post tomorrow. ;) Good night!
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/11/12 01:58 AM (13 years ago)
Seeing this....before passing out. How are you connecting the print button to the method? I ask because you may be using all code, interface builder, etc. It can get tricky but it's generally not tough to connect a button to a method. 1) Connect the button to the method 2) comment out all the code in the method to make sure the button fires the method (and the app doesn't crash) use the console to make sure something prints to the output when the button is tapped. 3) if the button taps, uncomment line by line while you debug to figure out where it's crashing. The "unused" myData variable message means you're not passing this data object to your print code. I didn't include any of the print code in the example, just how to get the NSData so you CAN print it. Looking at thread tomorrow, get your button firing the event without crashing the app :-)
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/11/12 02:06 AM (13 years ago)
To be honest, I don't have the slightest idea when I'm connecting something to something else... lol! Might be problematic, but what I can say for sure is that I simply followed the guide (http://jc-evans.com/blog/2012/07/13/new-tutorial-adding-a-print-button-to-an-app/) line by line, so I would assume the connection between the print button and the method is pure code, no interface builder or other shenanigans. I'm not sure if this gives you any more info that you could find useful, but I'm not certain what I should be looking for. From the previous guide, viewutilities was used to assign a print button for every PDF file that was given the "home" button in the BT control panel. I'll see what I can do tomorrow, I fear though that I won't know where to start... Forget learning how to walk before running, I need to learn how to crawl! lol I'll await further instructions tomorrow - officially 4 am and time to sleep. Until tomorrow! :)
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/12/12 11:18 AM (13 years ago)
Any more nuggets of knowledge? :)
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/12/12 12:03 PM (13 years ago)
Not really. Try to get through these steps... 1) Create a new method to connect to your print button. Make this method empty so it doesn't do anything, just prints to the console so you can make sure it's running when you tap the button. 2) Add the NSData logic to the method. Test again, does it crash? 3) Keep adding a few pieces of logic (like when to print) to isolate exactly which line of code is causing the crash.
 
GraciousWolf_PE
Aspiring developer
Profile
Posts: 372
Reg: Feb 15, 2012
Montreal
10,720
like
11/13/12 12:30 PM (13 years ago)
Finally figured it out (with some assistance)! Literally one line away from getting the AirPrint function to print what I wanted, which was all the PDFs. What I did: Took: NSArray *components = [shareTitle componentsSeparatedByString:@"."]; Changed it to: NSArray *components = [self.localFileName componentsSeparatedByString:@"."]; Also removed: NSString *shareTitle; @property (nonatomic, retain) NSString *shareTitle; AND @synthesize shareTitle; as they were no longer needed! Thanks for all the help, David, I appreciate it! Nicholas
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/14/12 12:28 AM (13 years ago)
you rock!!!
 

Login + Screen Name Required to Post

pointerLogin to participate so you can start earning points. Once you're logged in (and have a screen name entered in your profile), you can subscribe to topics, follow users, and start learning how to make apps like the pros.