I have trouble with creating Pause/Resume download methods in my Objective-C osx app, I have tried some of the answers I found here but nothing seems to work.
Here is my code: `-(void)pauseDownload:(id)sender {
if(!downloadTask) return;
[downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
if (!resumeData) return;
[self setDownloadResumeData:resumeData];
[self setDownloadTask:nil];
}];
NSString *datastring = [[NSString alloc] initWithData:downloadResumeData encoding:NSUTF8StringEncoding];
isDownloading = NO;
NSLog(#"data %#", datastring);}`
Continue method:
-(void)continueDownload:(id)sender {
if (!self.downloadResumeData) {
return;
}
self.downloadTask = [manager.session downloadTaskWithResumeData:self.downloadResumeData];
[self.downloadTask resume];
[self setDownloadResumeData:nil];}
And download request with download task:
-(void)downloadRequest:(NSString *)url toDirectory:(NSString *)directoryName atIndex:(NSInteger) rowIndex {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSString *downloadDirectoryPath = [[NSUserDefaults standardUserDefaults] objectForKey:#"downloadPath"];
NSURL *downloadURL;
if (directoryName != nil || ![directoryName isEqualToString:#""]) {
downloadURL = [self createDownloadDirectoryIn:downloadDirectoryPath withName:directoryName];
} else {
downloadURL = [NSURL URLWithString:[[NSUserDefaults standardUserDefaults] objectForKey:#"downloadFolderPath"]];
}
downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(#"%#", downloadProgress);
// [self downloadStartedWithDownloadId:downloadID andDeviceId:userDeviceID];
isDownloading = YES;
NSNumber *downloadPercentage = [NSNumber numberWithInteger:downloadProgress.fractionCompleted *100];
progressArray[rowIndex] = downloadPercentage;
[self updateProgressBars];
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
return [downloadURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
[[files objectAtIndex:self.tableOfContents.selectedRow] setIsFinishedDownloading:YES];
// [self downloadFinishedWithDownloadID:downloadID andDeviceID:userDeviceID];
NSLog(#"File downloaded to: %#", filePath);
}] ;
[downloadTask resume];}
Appreciate any help.
Is there a opportunity to add a description to a new Instagram post created via iPhone Hook?
NSString *moviePath = outputPath;
NSString *caption = #"description";
NSURL *movieURL = [NSURL fileURLWithPath:moviePath isDirectory:NO];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:movieURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
NSURL *instagramURL = [NSURL URLWithString:
[NSString stringWithFormat:#"instagram://library?AssetPath=%#&annotation=%#",
[[assetURL absoluteString] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]],
[caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]]
];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
[[UIApplication sharedApplication] openURL:instagramURL];
}
else {
NSLog(#"Can't open Instagram");
}
}];
I tried thus but it doesn't show anything in the description text field. Can you help me?
I'm trying to send a PDF using a UIActivityViewController. So far everything works fine using a fairly basic approach but the one issue I have is that when I select the send by mail option, the PDF's file name is Attachment-1 rather than Calculation.PDF which is the name that I give the file.
I don't mind too much the change in title, but the lack of a .pdf extension does seem to cause a problem when sending the file to people with Windows PC's and I'd like to fix that.
I've had a look at:
Control file name of UIImage send with UIActivityViewController
But can't see an equivalent method to:
[mailComposer addAttachmentData: UIImagePNGRepresentation(viewImage) mimeType:#"" fileName:#"myImage.png"];
that will work with a PDF file. Is this something that is not fixable without customization or is there a simple solution to this problem?
try this
NSData *pdfData = [NSData dataWithContentsOfFile:pdfFilePath];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[#"Test", pdfData] applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
and also
NSString *str = [[NSBundle mainBundle] pathForResource:#"AppDistributionGuide" ofType:#"pdf"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[#"Test", [NSURL fileURLWithPath:str]] applicationActivities:nil];
Swift
let url = NSURL.fileURLWithPath(fileName)
let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)
presentViewController(activityViewController, animated: true, completion: nil)
Swift 4.0
Here I attached code.I just added thread handling in to present "activityViewController" because of this viewcontroller present before load actual data.
let url = NSURLfileURL(withPath:fileName)
let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)
DispatchQueue.main.async {
self.present(activityViewController, animated: true, completion: nil)
}
Above listing about Swift is deprecated in Swift 3
let url = NSURL.fileURL(withPath: fileName)
let activityViewController = UIActivityViewController(activityItems: [url] , applicationActivities: nil)
present(activityViewController,
animated: true,
completion: nil)
For Objective-C tested code to share PDF
- (void)downloadPDFfile:(NSString *)fileName withFileURL:(NSString *)shareURL {
dispatch_async(dispatch_get_main_queue(), ^ {
NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *filePath = [documentDir stringByAppendingPathComponent:[NSString stringWithFormat:#"/%#",[self generateName:fileName withFiletype:#"pdf"]]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:shareURL]];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"Download Error:%#",error.description);
} else if (data && error == nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[data writeToFile:filePath atomically:YES];
[self shareFile:fileName withFilepath:filePath];
});
}
}];
[task resume];
});
}
-(void)shareFile:(NSString*)withfileName withFilepath:(NSString*)filePath {
NSMutableArray *items = [NSMutableArray array];
if (filePath) {
[items addObject:[NSURL fileURLWithPath:filePath]];
}
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[activityViewController setValue:withfileName forKey:#"subject"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
activityViewController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = activityViewController.popoverPresentationController;
popPC.sourceView = self.view;
CGRect sourceRext = CGRectZero;
sourceRext.origin = CGPointMake(self.view.frame.size.width-30, 0);
popPC.sourceRect = sourceRext;
popPC.permittedArrowDirections = UIPopoverArrowDirectionDown;
}
[activityViewController setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
}];
[self presentViewController:activityViewController animated:YES completion:nil];
}
-(NSString*)generateName:(NSString*)title withFiletype:(NSString*)type {
NSString *subject = [title stringByReplacingOccurrencesOfString:#" " withString:#"_"];
subject = [NSString stringWithFormat:#"%#.%#",subject,type];
return subject;
}
call function like below
[self downloadPDFfile:#"yourFileName" withFileURL:shareURL];
For Swift 3
You have to have a URL array with the path of the PDF you want to send.
let urlArray = [pdfPath1, pdfPath2]
Then create an UIActivityViewController:
let activityController = UIActivityViewController(activityItems: urlArray, applicationActivities: nil)
If you are using a UIBarButtonItem to make that action, you can implement this to prevent an error on iPad:
if let popover = activityController.popoverPresentationController {
popover.barButtonItem = self.barButtonItem
}
Finally you have to present the activityController:
self.present(activityController, animated: true, completion: nil)
The reply by Muruganandham K is simple and quite elegant. However, it doesn't work in iOS 9. In order to make it work, if you remove the #[#"Test" and just pass the pdfData, an attachment is made.
NSData *pdfData = [NSData dataWithContentsOfFile:pdfFilePath];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:pdfData applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];
May be try this..
#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
// Validate PDF using NSData
- (BOOL)isValidePDF:(NSData *)pdfData {
BOOL isPDF = false;
if (pdfData.length >= 1024 ) {
int startMetaCount = 4, endMetaCount = 5;
// check pdf data is the NSData with embedded %PDF & %%EOF
NSData *startPDFData = [NSData dataWithBytes:"%PDF" length:startMetaCount];
NSData *endPDFData = [NSData dataWithBytes:"%%EOF" length:endMetaCount];
// startPDFData, endPDFData data are the NSData with embedded in pdfData
NSRange startRange = [pdfData rangeOfData:startPDFData options:0 range:NSMakeRange(0, 1024)];
NSRange endRange = [pdfData rangeOfData:endPDFData options:0 range:NSMakeRange(0, pdfData.length)];
if (startRange.location != NSNotFound && startRange.length == startMetaCount && endRange.location != NSNotFound && endRange.length == endMetaCount ) {
// This assumes the checkstartPDFData doesn't have a specific range in file pdf data
isPDF = true;
} else {
isPDF = false;
}
}
return isPDF;
}
// Download PDF file in asynchronous way and validate pdf file formate.
- (void)downloadPDFfile:(NSString *) fileName withFileURL:(NSString *) url {
NSString *filePath = #"";
dispatch_async(dispatch_get_main_queue(), ^ {
NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
filePath = [documentDir stringByAppendingPathComponent:[NSString stringWithFormat:#"/Attachments/%#",[self generateName:fileName withFiletype:#"pdf"]]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"Download Error:%#",error.description);
} else if (data && error == nil) {
bool checkPdfFormat = [self isValidePDF:data];
if (checkPdfFormat) {
//saving is done on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[data writeToFile:filePath atomically:YES];
NSURL *url = [NSURL fileURLWithPath:filePath];
[self triggerShare:fileName withFilepath:filePath];
});
}
}
}];
});
}
// Trigger default share and print functionality using UIActivityViewController
-(void) triggerShare:(NSString*)fileName withFilepath:(NSString*)filePath {
* Set this available field on the activity controller */
NSMutableArray *items = [NSMutableArray array];
if (filePath) {
[items addObject:[NSURL fileURLWithPath:filePath]];
}
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[activityViewController setValue:fileName forKey:#"subject"]; // Set the mail subject.
if (IS_IPAD) {
activityViewController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = activityViewController.popoverPresentationController;
popPC.sourceView = self.view;
CGRect sourceRext = CGRectZero;
sourceRext.origin = CGPointMake(self.view.frame.size.width-30, 0 ); // I have share button in navigation bar. ;)
popPC.sourceRect = sourceRext;
popPC.permittedArrowDirections = UIPopoverArrowDirectionUp;
}
[activityViewController setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
}];
[self presentViewController:activityViewController animated:YES completion:nil];
}
-(NSString*) generateName:(NSString*)title withFiletype:(NSString*)type {
NSString *subject = [title stringByReplacingOccurrencesOfString:#" " withString:#"_"];
subject = [NSString stringWithFormat:#"%#.%#",subject,type];
return subject;
}
In one of the views of my app there's a button. When pressed it is supposed to begin taking a video, trigger a sound file to start, and hide itself from view while unhiding another button. The second button is supposed to stop the video recording and make it save. Here's the code I have for the video recording, which initially worked with no problems:
in viewDidLoad:
finishButton.hidden = TRUE;
session = [[AVCaptureSession alloc] init];
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
NSError *error;
AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self cameraWithPosition:AVCaptureDevicePositionFront] error:&error];
if (videoInput)
{
[session addInput:videoInput];
}
AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
NSError *audioError = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&audioError];
if (audioInput)
{
[session addInput:audioInput];
}
Float64 TotalSeconds = 35; //Total seconds
int32_t preferredTimeScale = 30; //Frames per second
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);
movieFileOutput.maxRecordedDuration = maxDuration;
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024;
if ([session canAddOutput:movieFileOutput])
[session addOutput:movieFileOutput];
[session setSessionPreset:AVCaptureSessionPresetMedium];
if ([session canSetSessionPreset:AVCaptureSessionPreset640x480]) //Check size based configs are supported before setting them
[session setSessionPreset:AVCaptureSessionPreset640x480];
[self cameraSetOutputProperties];
[session startRunning];
and for the button:
-(IBAction)start:(id)sender
{
startButton.hidden = TRUE;
finishButton.hidden = FALSE;
//Create temporary URL to record to
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output.mov"];
self.outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
{
//Error - handle if required
}
}
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
finally, under the last button:
[movieFileOutput stopRecording];
and here's the code to save the video:
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
NSLog(#"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
{
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
{
RecordedSuccessfully = [value boolValue];
}
}
if (RecordedSuccessfully)
{
//----- RECORDED SUCESSFULLY -----
NSLog(#"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
}
}];
}
}
}
All of this was working just fine. Then I added a few lines so that a song file would play when the start button was pressed.
in viewDidLoad:
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/Song.aiff", [[NSBundle mainBundle] resourcePath]]];
NSError *audioFileError;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&audioFileError];
player.numberOfLoops = 0;
[self.player prepareToPlay];
and under the start button:
if (player == nil)
NSLog(#"Audio file could not be played");
else
[player play];
Now when the start button is pressed the song plays with no problems, but the video capture is messed up. Before adding the AVAudioPlayer stuff I would get the "didFinishRecordingToOutputFileAtURL - enter" and "didFinishRecordingToOutputFileAtURL - success" logs when I pressed the finish button, and now I get the first log as soon as I press the start button, nothing happens when I press the finish button, and no video is recorded. If I comment out the lines that make the song play then the video capture works just fine again. Any ideas what's going on here?
- (void)setupAudioSession
{
static BOOL audioSessionSetup = NO;
if (audioSessionSetup)
{
return;
}
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
[[AVAudioSession sharedInstance] setActive: YES error: nil];
audioSessionSetup = YES;
}
- (void)playAudio
{
[self setupAudioSession];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"btnClick" ofType:#"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.audioPlayer = newPlayer;
[newPlayer release];
[audioPlayer setDelegate:self];
[audioPlayer prepareToPlay];
audioPlayer.volume=1.0;
[audioPlayer play];
}
NOTE: Add the framework: AudioToolbox.framework.
#import <AudioToolbox/AudioServices.h>
I want image on view by fetching it from some url. I want changing in given code..
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
UIImage *image = [[UIImage imageNamed:<#(NSString *)name#>
NSString * mediaUrl = [[[self appDelegate]currentlySelectedBlogItem]mediaUrl];
[[self image]setImage:[UIImage imageNamed:#"unknown.jpg"]];
if(nil != mediaUrl){
NSData* imageData;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
#try {
imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:mediaUrl]];
}
#catch (NSException * e) {
//Some error while downloading data
}
#finally {
UIImage * imageFromImageData = [[UIImage alloc] initWithData:imageData];
[[self image]setImage:imageFromImageData];
[imageData release];
[imageFromImageData release];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
self.titleTextView.text = [[[self appDelegate] currentlySelectedBlogItem]title];
self.descriptionTextView.text = [[[self appDelegate] currentlySelectedBlogItem]description];
}
Using this will give you a solution
NSURL *url = [NSURL URLWithString:#"ENTER YOUR URL HAVING THE IMAGE"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
I have used the following:
NSString *url=[NSString stringWithFormat:#"Your URL"];
//NSLog(#"URL=%#",url);
UIImage *myImage=[[UIImage alloc] initWithData:[NSData UIImage *myImage=[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString: url]]];
NSLog(#"%d byte of data", [[NSData dataWithContentsOfURL: [NSURL URLWithString: url]] length]);
if (myImage)
{
//THIS CODE WILL STORE IMAGE DOCUMENT DIRECTORY
NSString *jpegFilePath = [NSString stringWithFormat:#"%#/%#.jpg",[self pathForDocumentDirectory],[self.idOfImagesToDownload objectAtIndex:i]];
NSData *data1 = [NSData dataWithData:UIImageJPEGRepresentation(myImage, 1.0f)];//1.0f = 100% quality
[data1 writeToFile:jpegFilePath atomically:YES];
}
NOTE:[self pathForDocumentDirectory] is method returning path of document directory.