Printing on iOS - iphone

Hi there can any one help me with this? I am new to iOS development. I am trying to implement a print feature, but I am getting errors in it. I see nothing but .xib file with some labels. The textview is there, I just want to print that view... when i pressed the print button the program is crashing..
Here is my code:
- (NSData *)generatePDFDataForPrinting {
NSMutableData *myPdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(myPdfData, kPDFPageBounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self drawStuffInContext:ctx]; // Method also usable from drawRect:.
UIGraphicsEndPDFContext();
return myPdfData;
}
- (void)drawStuffInContext:(CGContextRef)ctx {
UIFont *font = [UIFont fontWithName:#"Zapfino" size:48];
CGRect textRect = CGRectInset(kPDFPageBounds, 36, 36);
[#"hello world!" drawInRect:textRect withFont:font];
}
- (IBAction)printFromIphone:(id)sender {
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion>4.1) {
NSData *myPdfData = [NSData dataWithContentsOfFile:myPdfData]; //check the value inside |myPdfData| and |pdfPath| is the path of your pdf.
UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
if (controller && [UIPrintInteractionController canPrintData:myPdfData]){
//controller.delegate = delegate; //if necessary else nil
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = [myPdfData lastPathComponent];
//printInfo.duplex = UIPrintInfoDuplexLongEdge;
controller.printInfo = printInfo;
controller.showsPageRange = YES;
controller.printingItem = myPdfData;
// We need a completion handler block for printing.
UIPrintInteractionCompletionHandler completionHandler = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if(completed && error){
NSLog(#"FAILED! due to error in domain %# with error code %u", error.domain, error.code);
}
};
// [controller presentFromRect:CGRectMake(200, 300, 100, 100) inView:senderView animated:YES completionHandler:completionHandler];
}else {
NSLog(#"Couldn't get shared UIPrintInteractionController!");
}
}
}

Not sure if its a typo or not but you've commented out your actual pdfData which is why its undeclared.
This line needs to be uncommented because you need myPdfData.
//NSData *myPdfData = [NSData dataWithContentsOfFile:pdfData]; //check the value inside |myPdfData| and |pdfPath| is the path of your pdf.
You can replace it with this line to use YOUR pdf instead of a file.
NSData *myPdfData = [self generatePDFDataForPrinting];

Related

Flutter image_picker choose video

I am successfully using the Flutter Plugin Image_picker to choose images so that I can use them for upload, display, etc... I wondered if anyone had any guidance on how to modify this plugin to also see videos and allow them to be chosen and use for upload, etc...
Looking for iOS and Android modifications if anyone has guidance on how to proceed or example code. I have made some progress but still need to get the camera to save video and be able to present. I will post the code changes so far. I have it selecting a video, but it will not present back to the app.
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import UIKit;
#import <MobileCoreServices/MobileCoreServices.h>
#import "ImagePickerPlugin.h"
#interface ImagePickerPlugin ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#end
static const int SOURCE_ASK_USER = 0;
static const int SOURCE_CAMERA = 1;
static const int SOURCE_GALLERY = 2;
#implementation ImagePickerPlugin {
FlutterResult _result;
NSDictionary *_arguments;
UIImagePickerController *_imagePickerController;
UIViewController *_viewController;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:#"image_picker"
binaryMessenger:[registrar messenger]];
UIViewController *viewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
ImagePickerPlugin *instance = [[ImagePickerPlugin alloc] initWithViewController:viewController];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
_viewController = viewController;
_imagePickerController = [[UIImagePickerController alloc] init];
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if (_result) {
_result([FlutterError errorWithCode:#"multiple_request"
message:#"Cancelled by a second request"
details:nil]);
_result = nil;
}
if ([#"pickImage" isEqualToString:call.method]) {
_imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
_imagePickerController.delegate = self;
_result = result;
_arguments = call.arguments;
int imageSource = [[_arguments objectForKey:#"source"] intValue];
switch (imageSource) {
case SOURCE_ASK_USER:
[self showImageSourceSelector];
break;
case SOURCE_CAMERA:
[self showCamera];
break;
case SOURCE_GALLERY:
[self showPhotoLibrary];
break;
default:
result([FlutterError errorWithCode:#"invalid_source"
message:#"Invalid image source."
details:nil]);
break;
}
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)showImageSourceSelector {
UIAlertControllerStyle style = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
? UIAlertControllerStyleAlert
: UIAlertControllerStyleActionSheet;
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style];
UIAlertAction *camera = [UIAlertAction actionWithTitle:#"Take Photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showCamera];
}];
UIAlertAction *library = [UIAlertAction actionWithTitle:#"Choose Photo"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showPhotoLibrary];
}];
UIAlertAction *cancel =
[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:camera];
[alert addAction:library];
[alert addAction:cancel];
[_viewController presentViewController:alert animated:YES completion:nil];
}
- (void)showCamera {
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePickerController.sourceType = UIImagePickerControllerCameraCaptureModeVideo;
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Camera not available."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
- (void)showPhotoLibrary {
// No need to check if SourceType is available. It always is.
//_imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_imagePickerController.mediaTypes =[UIImagePickerController availableMediaTypesForSourceType:_imagePickerController.sourceType];
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
[_imagePickerController dismissViewControllerAnimated:YES completion:nil];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
if (image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
} else {
image = [self normalizedImage:image];
}
if (videoURL == nil) {
} else {
//image = videoURL;
}
NSNumber *maxWidth = [_arguments objectForKey:#"maxWidth"];
NSNumber *maxHeight = [_arguments objectForKey:#"maxHeight"];
if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
}
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSString *tmpDirectory = NSTemporaryDirectory();
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
// TODO(jackson): Using the cache directory might be better than temporary
// directory.
NSString *tmpFile = [NSString stringWithFormat:#"image_picker_%#.jpg", guid];
NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
_result(tmpPath);
} else {
_result([FlutterError errorWithCode:#"create_error"
message:#"Temporary file could not be created"
details:nil]);
}
_result = nil;
_arguments = nil;
}
// The way we save images to the tmp dir currently throws away all EXIF data
// (including the orientation of the image). That means, pics taken in portrait
// will not be orientated correctly as is. To avoid that, we rotate the actual
// image data.
// TODO(goderbauer): investigate how to preserve EXIF data.
- (UIImage *)normalizedImage:(UIImage *)image {
if (image.imageOrientation == UIImageOrientationUp) return image;
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawInRect:(CGRect){0, 0, image.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
- (UIImage *)scaledImage:(UIImage *)image
maxWidth:(NSNumber *)maxWidth
maxHeight:(NSNumber *)maxHeight {
double originalWidth = image.size.width;
double originalHeight = image.size.height;
bool hasMaxWidth = maxWidth != (id)[NSNull null];
bool hasMaxHeight = maxHeight != (id)[NSNull null];
double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
if (shouldDownscale) {
double downscaledWidth = (height / originalHeight) * originalWidth;
double downscaledHeight = (width / originalWidth) * originalHeight;
if (width < height) {
if (!hasMaxWidth) {
width = downscaledWidth;
} else {
height = downscaledHeight;
}
} else if (height < width) {
if (!hasMaxHeight) {
height = downscaledHeight;
} else {
width = downscaledWidth;
}
} else {
if (originalWidth < originalHeight) {
width = downscaledWidth;
} else if (originalHeight < originalWidth) {
height = downscaledHeight;
}
}
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[image drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
#end
Thanks
Here is the IOS code that I have completed, I am still working on the Android if anyone wants to assist, I will post where I am at so far. This code replaces what is in the .m file of the IOS folder, no other changes are needed for this to work to pick and capture video along with images. You must figure out how to display the selected video/image in your app, but that's however you want to handle it. Again let me know if you want to assist with finishing he Android side.
#import UIKit;
#import <MobileCoreServices/MobileCoreServices.h>
#import "MediaPickerPlugin.h"
#interface MediaPickerPlugin ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#end
static const int SOURCE_ASK_USER = 0;
//static const int SOURCE_CAMERA = 0;
//static const int SOURCE_GALLERY = 0;
#implementation MediaPickerPlugin {
FlutterResult _result;
NSDictionary *_arguments;
UIImagePickerController *_imagePickerController;
UIViewController *_viewController;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel =
[FlutterMethodChannel methodChannelWithName:#"media_picker"
binaryMessenger:[registrar messenger]];
UIViewController *viewController =
[UIApplication sharedApplication].delegate.window.rootViewController;
MediaPickerPlugin *instance =
[[MediaPickerPlugin alloc] initWithViewController:viewController];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
_viewController = viewController;
_imagePickerController = [[UIImagePickerController alloc] init];
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if (_result) {
_result([FlutterError errorWithCode:#"multiple_request"
message:#"Cancelled by a second request"
details:nil]);
_result = nil;
_arguments = nil;
}
if ([#"pickImage" isEqualToString:call.method]) {
_imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
_imagePickerController.delegate = self;
_result = result;
_arguments = call.arguments;
int imageSource = [[_arguments objectForKey:#"source"] intValue];
switch (imageSource) {
case SOURCE_ASK_USER:
[self showImageSourceSelector];
break;
default:
result([FlutterError errorWithCode:#"invalid_source"
message:#"Invalid image source."
details:nil]);
break;
}
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)showImageSourceSelector {
UIAlertControllerStyle style = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
? UIAlertControllerStyleAlert
: UIAlertControllerStyleActionSheet;
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style];
UIAlertAction *camera = [UIAlertAction actionWithTitle:#"Camera"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showCamera];
}];
UIAlertAction *library = [UIAlertAction actionWithTitle:#"Gallery"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self showPhotoLibrary];
}];
UIAlertAction *cancel =
[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:camera];
[alert addAction:library];
[alert addAction:cancel];
[_viewController presentViewController:alert animated:YES completion:nil];
}
- (void)showCamera {
// Camera is not available on simulators
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
_imagePickerController.mediaTypes = [NSArray arrayWithObjects:#"public.movie", #"public.image", nil];
_imagePickerController.delegate = self;
_imagePickerController.restoresFocusAfterTransition = false;
_imagePickerController.allowsEditing = NO;
_imagePickerController.videoQuality = UIImagePickerControllerQualityTypeLow;
_imagePickerController.videoMaximumDuration = 30.0f; // 30 seconds
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Camera not available."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
- (void)showPhotoLibrary {
// No need to check if SourceType is available. It always is.
_imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_imagePickerController.mediaTypes = [NSArray arrayWithObjects:#"public.movie", #"public.image", nil];
//_imagePickerController.mediaTypes =[UIImagePickerController availableMediaTypesForSourceType:_imagePickerController.sourceType];
[_viewController presentViewController:_imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
[_imagePickerController dismissViewControllerAnimated:YES completion:nil];
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:#"public.movie"]) {
NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSString *videoString = [videoURL absoluteString];
NSLog(#"Video File:%#", videoString);
_result(videoString);
} else {
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if (image == nil) {
image = [info objectForKey:UIImagePickerControllerOriginalImage];
}
image = [self normalizedImage:image];
NSNumber *maxWidth = [_arguments objectForKey:#"maxWidth"];
NSNumber *maxHeight = [_arguments objectForKey:#"maxHeight"];
if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) {
image = [self scaledImage:image maxWidth:maxWidth maxHeight:maxHeight];
}
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSString *tmpDirectory = NSTemporaryDirectory();
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
// TODO(jackson): Using the cache directory might be better than temporary
// directory.
NSString *tmpFile = [NSString stringWithFormat:#"image_picker_%#.jpg", guid];
NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
NSLog(#"Image File:%#", tmpPath);
if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
_result(tmpPath);
} else {
_result([FlutterError errorWithCode:#"create_error"
message:#"Temporary file could not be created"
details:nil]);
}
_result = nil;
_arguments = nil;
}
_result = nil;
_arguments = nil;
}
// The way we save images to the tmp dir currently throws away all EXIF data
// (including the orientation of the image). That means, pics taken in portrait
// will not be orientated correctly as is. To avoid that, we rotate the actual
// image data.
// TODO(goderbauer): investigate how to preserve EXIF data.
- (UIImage *)normalizedImage:(UIImage *)image {
if (image.imageOrientation == UIImageOrientationUp) return image;
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawInRect:(CGRect){0, 0, image.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
//- (NSString *)normalVideo:(NSURL *)videoURL {
// NSString *normalVideo = UIImagePickerControllerMediaURL;
// return normalVideo;
//}
- (UIImage *)scaledImage:(UIImage *)image
maxWidth:(NSNumber *)maxWidth
maxHeight:(NSNumber *)maxHeight {
double originalWidth = image.size.width;
double originalHeight = image.size.height;
bool hasMaxWidth = maxWidth != (id)[NSNull null];
bool hasMaxHeight = maxHeight != (id)[NSNull null];
double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
if (shouldDownscale) {
double downscaledWidth = (height / originalHeight) * originalWidth;
double downscaledHeight = (width / originalWidth) * originalHeight;
if (width < height) {
if (!hasMaxWidth) {
width = downscaledWidth;
} else {
height = downscaledHeight;
}
} else if (height < width) {
if (!hasMaxHeight) {
height = downscaledHeight;
} else {
width = downscaledWidth;
}
} else {
if (originalWidth < originalHeight) {
width = downscaledWidth;
} else if (originalHeight < originalWidth) {
height = downscaledHeight;
}
}
}
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
[image drawInRect:CGRectMake(0, 0, width, height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
#end
I would probably add another method pickVideo to image_picker.dart, and then add the corresponding Android and iOS implementations of that in imagePickerPlugin.m and ImagePickerPlugin.java.
Inside the latter two, I would use the iOS and Android APIs for videos, e.g. something like this on iOS:
Objective c - ios : How to pick video from Camera Roll?
as of version 0.4.2, the plugin allows video to be selected
Added support for picking videos. Updated example app to show video
preview.
You can do that now using pickVideo available in image_picker
final _picker = ImagePicker();
PickedFile video = await _picker.getVideo(...)
...
Ref - https://pub.dev/packages/image_picker
you can use the image picker for recording video, and chewie library to show a video via video controller.
for more reference use this video link -
https://www.youtube.com/watch?time_continue=17&v=XSn5EwWBG-4&feature=emb_logo

Saving Annotations and Pdf to a new Pdf file in IOS 5

I'm working on a pdf annotations application and i need to save the annotation so when i tried to save the annotations and the pdf content to a new pdf , the annotations are saved but the content of the pdf is not ? here is my function :
-(void)save_doc_as_pdf:(ReaderMainToolbar *)toolbar BackButton:(UIButton *)button
{
NSError *error;
NSString *PdfPath = [document.fileURL absoluteString];
NSString *newPath = [PdfPath stringByReplacingOccurrencesOfString:#"file://localhost" withString:#""];
NSString *NewPdfPath = [thenewPath stringByReplacingOccurrencesOfString:#".pdf" withString:#"_1.pdf"];
NSData *pdfData = [NSData dataWithContentsOfFile:[document.fileURL path] options:NSDataReadingUncached error:&error];
if (pdfData == nil) {
NSLog(#"data is nil !!!!");
}
if (error)
{
NSLog(#"%#", [error localizedDescription]);
return;
}
else
NSLog(#"Data has loaded successfully.");
//If fails to create the new file, returns
if (![[NSFileManager defaultManager] createFileAtPath:NewPdfPath contents:pdfData attributes:nil])
{
return;
}
NSURL *url = [NSURL fileURLWithPath:newPath];
CGPDFDocumentRef pdf_document = CGPDFDocumentCreateWithURL ((__bridge_retained CFURLRef) url);
size_t count = CGPDFDocumentGetNumberOfPages(pdf_document);
if (count == 0)
{
NSLog(#"PDF needs at least one page");
return;
}
CGRect paperSize = CGRectMake(0, 0,842, 1190);
UIGraphicsBeginPDFContextToFile(NewPdfPath , paperSize, nil);
// CGPDFPageRef page = CGPDFDocumentGetPage(document, 1);
UIGraphicsBeginPDFPageWithInfo(paperSize, nil);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// flip context so page is right way (landscape app)
CGContextScaleCTM(currentContext, 1, -1);
// Rotate the coordinate system (rotation = M_PI or -M_PI for landscape)
//CGContextRotateCTM(currentContext, rotation/ 2);
CGPDFPageRef page = CGPDFDocumentGetPage (pdf_document, 1); // grab page 1 of the PDF
CGContextDrawPDFPage (currentContext, page); // draw page 1 into graphics context
//flip context so annotations are right way
CGContextScaleCTM(currentContext, 1, -1);
//CGContextRotateCTM(currentContext, rotation / 2);
//Render the layer of the annotations view in the context
[startdraw.layer renderInContext:currentContext];
UIGraphicsEndPDFContext();
CGPDFDocumentRelease (pdf_document);
}
hello i find a solution for saving an annotaion on a pdf document and i want to shar it with you so here is the code :
-(void)save_the_pdf:(ReaderMainToolbar *)toolbar BackButton:(UIButton *)button{
NSMutableArray *URLsTableObject=[[NSMutableArray alloc] init];
NSMutableArray *URLsTable=[[NSMutableArray alloc] init];
NSUserDefaults *DataStoreUrls;
NSString *OriginalPdfName = [document.fileName stringByReplacingOccurrencesOfString:#".pdf" withString:#""];
NSString *OriginalPdfPath = [document.fileName stringByReplacingOccurrencesOfString:#".pdf" withString:#""];
NSString* thenewPath = [[NSBundle mainBundle] pathForResource:OriginalPdfPath ofType:#"pdf"];
NSString *NewPdfPath = [thenewPath stringByReplacingOccurrencesOfString:#".pdf" withString:#"_1.pdf"];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)[[NSBundle mainBundle] URLForResource:OriginalPdfName withExtension:#"pdf"]);
const size_t numberOfPages = CGPDFDocumentGetNumberOfPages(pdf);
NSMutableData* data = [NSMutableData data];
UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);
for(size_t page = 1; page <= numberOfPages; page++)
{
// Get the current page and page frame
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdf, page);
const CGRect pageFrame = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);
// Draw the page (flipped)
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -pageFrame.size.height);
CGContextDrawPDFPage(ctx, pdfPage);
CGContextRestoreGState(ctx);
if (page == currentPage) {
[startdraw.layer renderInContext:ctx];
}
}
UIGraphicsEndPDFContext();
CGPDFDocumentRelease(pdf);
//pdf = nil;
if (![[NSFileManager defaultManager] createFileAtPath:NewPdfPath contents:data attributes:nil])
{
return;
}
// Do something with the 'data'...
DataStoreUrls=[NSUserDefaults standardUserDefaults];
if([DataStoreUrls objectForKey:#"ALLURLS"]!=NULL){
URLsTableObject=[DataStoreUrls objectForKey:#"ALLURLS"];
int index=[URLsTableObject count];
URLsTable=[[NSMutableArray alloc] initWithArray:URLsTableObject];
[URLsTable insertObject:NewPdfPath atIndex:index];
[DataStoreUrls setObject:URLsTable forKey:#"ALLURLS"];
}else{
[URLsTable addObject:NewPdfPath];
[DataStoreUrls setObject:URLsTable forKey:#"ALLURLS"];
}
[DataStoreUrls synchronize];
}

How to retrieve images from Instagram which has special hashtag?

My client wants to share an image on Instagram. I have implemeted sharing image on instagram.But i could not share it with a special hashtag. Here is my code so far.
- (IBAction)sharePhotoOnInstagram:(id)sender {
UIImagePickerController *imgpicker=[[UIImagePickerController alloc] init];
imgpicker.delegate=self;
[self storeimage];
NSURL *instagramURL = [NSURL URLWithString:#"instagram://app"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL])
{
CGRect rect = CGRectMake(0 ,0 , 612, 612);
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/15717.ig"];
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#", jpgPath]];
dic.UTI = #"com.instagram.photo";
dic.delegate = self;
dic = [self setupControllerWithURL:igImageHookFile usingDelegate:self];
dic = [UIDocumentInteractionController interactionControllerWithURL:igImageHookFile];
dic.delegate = self;
[dic presentOpenInMenuFromRect: rect inView: self.view animated: YES ];
// [[UIApplication sharedApplication] openURL:instagramURL];
}
else
{
// NSLog(#"instagramImageShare");
UIAlertView *errorToShare = [[UIAlertView alloc] initWithTitle:#"Instagram unavailable " message:#"You need to install Instagram in your device in order to share this image" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
errorToShare.tag=3010;
[errorToShare show];
}
}
- (void) storeimage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"15717.ig"];
UIImage *NewImg = [self resizedImage:picTaken :CGRectMake(0, 0, 612, 612) ];
NSData *imageData = UIImagePNGRepresentation(NewImg);
[imageData writeToFile:savedImagePath atomically:NO];
}
-(UIImage*) resizedImage:(UIImage *)inImage: (CGRect) thumbRect
{
CGImageRef imageRef = [inImage CGImage];
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
// There's a wierdness with kCGImageAlphaNone and CGBitmapContextCreate
// see Supported Pixel Formats in the Quartz 2D Programming Guide
// Creating a Bitmap Graphics Context section
// only RGB 8 bit images with alpha of kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst,
// and kCGImageAlphaPremultipliedLast, with a few other oddball image kinds are supported
// The images on input here are likely to be png or jpeg files
if (alphaInfo == kCGImageAlphaNone)
alphaInfo = kCGImageAlphaNoneSkipLast;
// Build a bitmap context that's the size of the thumbRect
CGContextRef bitmap = CGBitmapContextCreate(
NULL,
thumbRect.size.width, // width
thumbRect.size.height, // height
CGImageGetBitsPerComponent(imageRef), // really needs to always be 8
4 * thumbRect.size.width, // rowbytes
CGImageGetColorSpace(imageRef),
alphaInfo
);
// Draw into the context, this scales the image
CGContextDrawImage(bitmap, thumbRect, imageRef);
// Get an image from the context and a UIImage
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap); // ok if NULL
CGImageRelease(ref);
return result;
}
- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL*) fileURL usingDelegate: (id <UIDocumentInteractionControllerDelegate>) interactionDelegate
{
UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
interactionController.delegate = self;
return interactionController;
}
- (void)documentInteractionControllerWillPresentOpenInMenu:(UIDocumentInteractionController *)controller
{
}
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller canPerformAction:(SEL)action
{
// NSLog(#"5dsklfjkljas");
return YES;
}
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller performAction:(SEL)action
{
// NSLog(#"dsfa");
return YES;
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
{
// NSLog(#"fsafasd;");
}
Note : This is working fine.
I have followed their documentation on http://instagram.com/developer/iphone-hooks/ but couldn't get better idea from it!. Now don't know what to do next step for sharing an image with hashtag and other information.
Secondly I want to retrieve all the images shared with a particular hashtag into the application.
Please guide me! Thanks in advance!
First, from iPhone Hooks, under 'Document Interaction':
To include a pre-filled caption with your photo, you can set the annotation property on the document interaction request to an NSDictionary containing an NSString under the key "InstagramCaption". Note: this feature will be available on Instagram 2.1 and later.
You'll need to add something like:
dic.annotation = [NSDictionary dictionaryWithObject:#"#yourTagHere" forKey:#"InstagramCaption"];
Second, you'll need to take a look at Tag Endpoints if you want to pull down images with a specific tag.

iOS AirPrint - print multiple URLs

Following the question from this post:
Unable to display printer options with AirPrint
There were few questions I had:
1) One of the answers were to set Controller.printItem to a URL. Similarly, Can I set multiple URLs? Basically, I have a set of URLs I need to print at one shot. Is it possible to set controller.printitems to an array of URLs? Also, I know controller.printItem takes a type 'data', so how do I convert a web based image URL to a type 'data'?
2) For some weird reason, by default, doubled sided is set to on every time I reach the print dialog. What is the variable I need to set that off? It would be great if I could just not show the option to the user.
Try this code may help to you
- (IBAction)btnPrintTapped:(id)sender {
NSData *imageData = UIImagePNGRepresentation(self.imgV.image);
[self printItem:imageData];
}
#pragma mark - Printing
-(void)printItem :(NSData*)data {
printController = [UIPrintInteractionController sharedPrintController];
if(printController && [UIPrintInteractionController canPrintData:data]) {
printController.delegate = self;
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = [NSString stringWithFormat:#""];
printInfo.duplex = UIPrintInfoDuplexLongEdge;
printController.printInfo = printInfo;
printController.showsPageRange = YES;
printController.printingItem = data;
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if (!completed && error) {
//NSLog(#"FAILED! due to error in domain %# with error code %u", error.domain, error.code);
}
};
[printController presentFromBarButtonItem:self.item animated:YES completionHandler:completionHandler];
}
}
- (BOOL)presentFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated completionHandler:(UIPrintInteractionCompletionHandler)completion {
return YES;
}
- (BOOL)presentFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated completionHandler:(UIPrintInteractionCompletionHandler)completion {
return YES;
}
I know its late but might help if someone needs this:
Create array of URLs and assign it to "printingItems" property of "UIPrintInteractionController" class.

EXC_BAD_ACCESS at the end of a method

In this method I add the content of UITextFields, images and other strings in a sqlite database. Everything works fine. I mean, when i press the "Add" button, the "OK" image appear, the sound play and all the contents are added to the database (I can check restarting the application). But after all of this, I have this error in the "main.m"
This is the method:
-(IBAction)addItem:(id)sender { //gestione pulsante aggiunta elemento
if (([itemNameField.text length] == 0) || ([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0) || ((incomeOutcome.selectedSegmentIndex != 0) && (incomeOutcome.selectedSegmentIndex != 1))) {
if ([itemNameField.text length] == 0) {
statusLabel.text = [[NSString alloc] initWithFormat: #"Specificare un nome."];
} else if (([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0)) {
statusLabel.text = [[NSString alloc] initWithFormat: #"Specificare un prezzo."];
} else if ((incomeOutcome.selectedSegmentIndex != 0) && (incomeOutcome.selectedSegmentIndex != 1)) {
statusLabel.text = [[NSString alloc] initWithFormat: #"Specificare \"Income/Outcome\" ."];
}
if (!categoriaLabel.hidden) {
[self hideThemAll];
}
[incomeOutcome setSelectedSegmentIndex:-1];
statusLabel.hidden = NO;
error = true;
[self playSound];
[ok setImage:[UIImage imageNamed:#"error.png"]];
ok.hidden = NO;
return;
}
//apriamo il database
sqlite3 *db;
int dbrc; //Codice di ritorno del database (database return code)
iWalletAppDelegate *appDelegate = (iWalletAppDelegate*) [UIApplication sharedApplication].delegate;
const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc = sqlite3_open(dbFilePathUTF8, &db);
if (dbrc) {
NSLog(#"Impossibile aprire il Database!");
return;
}
//database aperto! Inseriamo valori nel database.
sqlite3_stmt *dbps; //Istruzione di preparazione del database
NSString *insertStatementsNS;
if (incomeOutcome.selectedSegmentIndex == 0) {
insertStatementsNS = [NSString stringWithFormat: #"insert into \"shoppinglist\" (item, price, groupid, incout, path, dateadded) values (\"%#\", \"%#\", \"Entrata\", %d, \"%#\", DATETIME('NOW'))", itemNameField.text, priceField.text, incomeOutcome.selectedSegmentIndex, imagePath];
} else if ([categoryNameField.text length] != 0) {
insertStatementsNS = [NSString stringWithFormat: #"insert into \"shoppinglist\" (item, price, groupid, incout, path, dateadded) values (\"%#\", \"%#\", \"%#\", %d, \"%#\", DATETIME('NOW'))", itemNameField.text, priceField.text, categoryNameField.text, incomeOutcome.selectedSegmentIndex, imagePath];
} else {
insertStatementsNS = [NSString stringWithFormat: #"insert into \"shoppinglist\" (item, price, groupid, incout, path, dateadded) values (\"%#\", \"%#\", \"Varie\", %d, \"%#\", DATETIME('NOW'))", itemNameField.text, priceField.text, incomeOutcome.selectedSegmentIndex, imagePath];
}
const char *insertStatement = [insertStatementsNS UTF8String];
dbrc = sqlite3_prepare_v2(db, insertStatement, -1, &dbps, NULL);
dbrc = sqlite3_step(dbps);
//faccio pulizia rilasciando i database
sqlite3_finalize(dbps);
sqlite3_close(db);
// Pulisci i campi e indica successo nello status
statusLabel.hidden = NO;
statusLabel.text = [[NSString alloc] initWithFormat: #"Aggiunto %#", itemNameField.text];
itemNameField.text = #"";
priceField.text = #"";
categoryNameField.text = #"";
imagePath = #"";
[incomeOutcome setSelectedSegmentIndex:-1];
error = false;
[self hideThemAll];
[self playSound];
[ok setImage:[UIImage imageNamed:#"ok.png"]];
ok.hidden = NO;
nome = #"";
prezzo =#"";
[photoPreview setImage:[UIImage imageNamed:#"noPhoto.png"]];
[[self parentViewController]dismissModalViewControllerAnimated:YES];
}
EDIT
Thanks to Isaac I (maybe) found the issue: I wasn't retaining the picture I took from the camera.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
int r = arc4random() % 9999;
NSDate *date = [NSDate date];
NSString *photoName = [dateNameFormatter stringFromDate:date];
photoName = [photoName stringByAppendingString:[NSString stringWithFormat:#"%d", r]];
if (imagePath) {
[imagePath release];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
imagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", photoName]];
[imagePath retain];
UIImage *picture = [info objectForKey:UIImagePickerControllerOriginalImage];
// ----- CODE FOR SCALE THE IMAGE ----- //
if (picture.size.width == 1936) {
picture = [picture scaleToSize:CGSizeMake(480.0f, 720.0f)];
} else {
picture = [picture scaleToSize:CGSizeMake(720.0f, 480.0f)];
}
photoPreview.image = picture;
photoPreview.contentMode = UIViewContentModeScaleAspectFit;
CGRect frame = photoPreview.frame;
if (picture.size.width == 480) {
frame.size.width = 111.3;
frame.size.height =167;
} else {
frame.size.width = 167;
frame.size.height =111.3;
}
photoPreview.frame = frame;
// ----- ----- - END CODE - ----- ----- //
NSData *webData = UIImagePNGRepresentation(picture);
CGImageRelease([picture CGImage]);
[webData writeToFile:imagePath atomically:YES];
[picture retain]; // <-- This little thing here!
//imgPicker = nil;
}
Now it works! But if you can see other problems, please let me notice them.
There is no reason to create NSString like this:
statusLabel.text = [[NSString alloc] initWithFormat: #"Specificare un nome."];
Simply write
statusLabel.text = #"Specificare un nome.";
Maybe it's not a cause of EXC_BAD_ACCESS, but at least you can avoid several memory leaks.
Typically an EXC_BAD_ACCESS occurs when you are trying to access memory that has been deallocated. In your code sample, I don't see any [object release] calls (that's another problem entirely, unless you happen to be using ARC). But my guess it that this error is the result of a call that is being made outside of the scope of this method - something is being released prematurely.
You could paste your entire class, or, consider using the Instruments tool 'Zombies' to identify the dangling pointer which is (probably) causing this.
In my opinion isaac is right. I just want to add one guess. Most likely the error occurs when you invoke
[[self parentViewController]dismissModalViewControllerAnimated:YES];
By this moment, I think, something in you parentViewController is already released, so when you try to show it back, program turns to released variable and gives you a crash.
You can quite easily detect it just with the help of breakpoints.