Get UTI of NSPasteboardTypeFileURL - cocoa

NSFilenamesPboardType got deprecated on 10.14 and the suggestion is to use NSPasteboardTypeFileURL. This gives me filename as
file:///.file/id=6571367.12885025918
and NSWorkspace is unable to get UTI out of it.
How to get UTI from NSPasteboardTypeFileURL?
Old code:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
NSDragOperation resultingDragMask = NSDragOperationNone;
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
NSArray <NSString *>*list = [pboard propertyListForType:NSFilenamesPboardType];
NSString *firstItem = [list objectAtIndexedSubscript:0];
NSError *error;
NSString *UTI = [[NSWorkspace sharedWorkspace] typeOfFile:firstItem error:&error];
if (!error) {
if ([[NSImage imageTypes] containsObject:UTI]) {
resultingDragMask = NSDragOperationCopy;
}
}
} else if ([[pboard types] containsObject:NSPasteboardTypeTIFF]) {
resultingDragMask = NSDragOperationCopy;
}
if (sourceDragMask & NSDragOperationCopy && resultingDragMask & NSDragOperationCopy) {
return NSDragOperationCopy;
}
return NSDragOperationNone;
}
With NSPasteboardTypeFileURL I get error which states file doesn't exist. Dragged from pasteboard:
Printing description of error:
Error Domain=NSCocoaErrorDomain Code=260 "The file “id=6571367.12885025918” couldn’t be opened because there is no such
file." UserInfo={NSURL=file:/.file/id=6571367.12885025918 --
file:///Users/xxx/Library/Containers/com.xxx.imageviewfix/Data/,
NSFilePath=/Users/xxx/Library/Containers/com.xxx.imageviewfix/Data/file:/.file/id=6571367.12885025918,
NSUnderlyingError=0x600000c70d80 {Error Domain=NSPOSIXErrorDomain
Code=2 "No such file or directory"}}

I am late to this question but I found this works:
NSArray<Class> *classes = #[[NSURL class]];
NSDictionary *options = #{};
NSArray<NSURL*> *files = [pboard readObjectsForClasses:classes options:options];
for (NSURL *url in files)
{
NSString *str = [url path];
// TODO: do something with str.
}
Unlike the other answer, dropping multiple files works with this approach.

Getting path of NSURL object gets the original filename. The only thing missing is the array of file paths which NSFilenamesPboardType used to give.
NSString *fileURL = [[NSURL URLFromPasteboard:pboard] path];
Updated code:
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
NSDragOperation resultingDragMask = NSDragOperationNone;
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSPasteboardTypeFileURL]) {
NSString *fileURL = [[NSURL URLFromPasteboard:pboard] path];
NSError *error;
NSString *UTI = [[NSWorkspace sharedWorkspace] typeOfFile:fileURL error:&error];
if (!error) {
if ([[NSImage imageTypes] containsObject:UTI]) {
resultingDragMask = NSDragOperationCopy;
}
}
} else if ([[pboard types] containsObject:NSPasteboardTypeTIFF]) {
resultingDragMask = NSDragOperationCopy;
}
if (sourceDragMask & NSDragOperationCopy && resultingDragMask & NSDragOperationCopy) {
return NSDragOperationCopy;
}
return NSDragOperationNone;
}

Related

Stop Activity Indicator while no row in Xcode

I am using the code below to retrieve data from Url via PHP file, the tableview controller will start the Activity Indicator. What I am trying to do is to stop the indicator As soon as there are no data has been loaded to the tableview.
Her is the code;
NSString *urlString = [NSString stringWithFormat:#"http:/MyWebSite/ChoseMyLike.php?userName=%#", myString];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!data) {
NSLog(#"connection error: %#", error);
return;
}
NSError *parseError;
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
if (!json) {
NSLog(#"JSON Parsing error: %#", parseError);
NSLog(#"data = %#", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
return;
}
NSMutableArray *results = [[NSMutableArray alloc]init];
for (int i = 0; i < json.count; i++) {
NSString *cQasidaName = json[i][#"qasidaName"];
NSString *cQasidaShaerName = json[i][#"qasidaShaerName"];
NSString *cQasidaBody = json[i][#"qasidaBody"];
NSString *cQasidaDate = json[i][#"myDate"];
NSString *cQasidaTime = json[i][#"myTime"];
NSString *cQasidaRate = json[i][#"myRate"];
NSString *cQasidaId = json[i][#"qasidaId"];
NSString *cQasidaUserName = json[i][#"userName"];
NSString *cTheUserId = json[i][#"theUserId"];
NSString *cTheUserNameArabic = json[i][#"userNameArabic"];
[results addObject:[[ListOfObjects alloc] initWithQasidaName: (NSString *) cQasidaName andQasidaShaerName: (NSString *) cQasidaShaerName andQasidaBody: (NSString *) cQasidaBody andQasidaDate: (NSString *) cQasidaDate andQasidaTime: (NSString *) cQasidaTime andQasidaRate: (NSString *)cQasidaRate andQasidaId:cQasidaId andQasidaUserName:cQasidaUserName andTheUserId:cTheUserId andTheUserNameArabic:cTheUserNameArabic]];
}
dispatch_async(dispatch_get_main_queue(), ^{
self.listArray = results;
[self.tableView reloadData];
[spinner stopAnimating];
});
}];
[task resume];
}
At the moment the indicator is not stopping. What do I need to do?
Thanks
Simply call [spinner stopAnimating]; for all return paths:
if (!data) {
NSLog(#"connection error: %#", error);
[spinner stopAnimating];
return;
}
and
if (!json) {
NSLog(#"JSON Parsing error: %#", parseError);
NSLog(#"data = %#", [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding]);
[spinner stopAnimating];
return;
}
Note: it's much easier to have a single return statement and then you can always call [spinner stopAnimating]; at the end of the method... consider restructuring your code.

setExposureMode xcode iOS 8

I am using the following code below to capture an image. Everything works fine but my commands to set the exposure and whitebalance in setCameraSettings() are ignored. They get executed but they have no effect. My command to set the session image resolution works fine.
#import "CaptureSessionManager.h"
#import <ImageIO/ImageIO.h>
// based on https://github.com/jj0b/AROverlayImageCapture
#implementation CaptureSessionManager
#synthesize captureSession;
#synthesize previewLayer;
#synthesize stillImageOutput;
#synthesize stillImage;
#synthesize imageWidth;
#synthesize imageHeight;
#synthesize imageBrightnessValue;
#synthesize imageExposureTime;
#synthesize imageApertureValue;
#synthesize imageISOSpeedRatings;
#synthesize playShutterSound;
/*************************************************************************************/
- (id)init {
if ((self = [super init])) {
AVCaptureSession *session = [[AVCaptureSession alloc] init];
// [session beginConfiguration];
if ([session canSetSessionPreset:AVCaptureSessionPresetHigh]) {
session.sessionPreset = AVCaptureSessionPresetHigh; // AVCaptureSessionPresetHigh; // AVCaptureSessionPresetLow;
}
// [session commitConfiguration];
[self setCaptureSession:session];
}
return self;
}
/*************************************************************************************/
- (void)addVideoPreviewLayer {
[self setPreviewLayer:[[AVCaptureVideoPreviewLayer alloc] initWithSession: [self captureSession]]];
[[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
/*************************************************************************************/
- (void)addVideoInputFrontCamera:(BOOL)front {
NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *frontCamera;
AVCaptureDevice *backCamera;
for (AVCaptureDevice *device in devices) {
NSLog(#"Device name: %#", [device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionBack) {
NSLog(#"Device position : back");
backCamera = device;
}
else {
NSLog(#"Device position : front");
frontCamera = device;
}
}
}
NSError *error = nil;
if (front) {
AVCaptureDeviceInput *frontFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
if (!error) {
if ([[self captureSession] canAddInput:frontFacingCameraDeviceInput]) {
[[self captureSession] addInput:frontFacingCameraDeviceInput];
currentCaptureDevice = frontCamera;
} else {
NSLog(#"Couldn't add front facing video input");
}
}
} else {
AVCaptureDeviceInput *backFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
if (!error) {
if ([[self captureSession] canAddInput:backFacingCameraDeviceInput]) {
[[self captureSession] addInput:backFacingCameraDeviceInput];
currentCaptureDevice = backCamera;
} else {
NSLog(#"Couldn't add back facing video input");
}
}
}
}
/*************************************************************************************/
- (void)addStillImageOutput
{
[self setStillImageOutput:[[AVCaptureStillImageOutput alloc] init]];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey,nil];
[[self stillImageOutput] setOutputSettings:outputSettings];
[[self captureSession] addOutput:[self stillImageOutput]];
for (AVCaptureConnection *connection in [[self stillImageOutput] connections]) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo]) {
videoConnection = connection;
[self setCameraSettings];
return;
}
}
}
}
/*************************************************************************************/
- (void)setCameraSettings:(long)expTime1000thSec iso:(int)isoValue
{
if ( currentCaptureDevice ) {
[captureSession beginConfiguration];
NSError *error = nil;
if ([currentCaptureDevice lockForConfiguration:&error]) {
if ([currentCaptureDevice isExposureModeSupported:AVCaptureExposureModeLocked]) {
CMTime minTime, maxTime, exposureTime;
if ( isoValue < minISO ) {
isoValue = minISO;
} else if ( isoValue > maxISO ) {
isoValue = maxISO;
}
exposureTime = CMTimeMake(expTime1000thSec, EXP_TIME_UNIT); // in 1/EXP_TIME_UNIT of a second
minTime = currentCaptureDevice.activeFormat.minExposureDuration;
maxTime = currentCaptureDevice.activeFormat.maxExposureDuration;
if ( CMTimeCompare(exposureTime, minTime) < 0 ) {
exposureTime = minTime;
} else if ( CMTimeCompare(exposureTime, maxTime) > 0 ) {
exposureTime = maxTime;
}
NSLog(#"setting exp time to %lld/%d s (want %ld) iso=%d", exposureTime.value, exposureTime.timescale, expTime1000thSec, isoValue);
[currentCaptureDevice setExposureModeCustomWithDuration:exposureTime ISO:isoValue completionHandler:nil];
}
if (currentCaptureDevice.lowLightBoostSupported) {
currentCaptureDevice.automaticallyEnablesLowLightBoostWhenAvailable = NO;
NSLog(#"setting automaticallyEnablesLowLightBoostWhenAvailable = NO");
}
// lock the gains
if ([currentCaptureDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked]) {
currentCaptureDevice.whiteBalanceMode = AVCaptureWhiteBalanceModeLocked;
NSLog(#"setting AVCaptureWhiteBalanceModeLocked");
}
// set the gains
AVCaptureWhiteBalanceGains gains;
gains.redGain = 1.0;
gains.greenGain = 1.0;
gains.blueGain = 1.0;
AVCaptureWhiteBalanceGains normalizedGains = [self normalizedGains:gains];
[currentCaptureDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:normalizedGains completionHandler:nil];
NSLog(#"setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains g.red=%.2lf g.green=%.2lf g.blue=%.2lf",
normalizedGains.redGain, normalizedGains.greenGain, normalizedGains.blueGain);
[currentCaptureDevice unlockForConfiguration];
}
[captureSession commitConfiguration];
}
}
/*************************************************************************************/
- (void)captureStillImage
{
NSLog(#"about to request a capture from: %#", [self stillImageOutput]);
[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments) {
NSLog(#"attachements: %#", exifAttachments);
} else {
NSLog(#"no attachments");
}
NSLog(#"name: %#", [currentCaptureDevice localizedName]);
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[self setStillImage:image];
NSDictionary *dict = (__bridge NSDictionary*)exifAttachments;
NSString *value = [dict objectForKey:#"PixelXDimension"];
[self setImageWidth:[NSNumber numberWithInt:[value intValue]]];
NSString *value1 = [dict objectForKey:#"PixelYDimension"];
[self setImageHeight:[NSNumber numberWithInt:[value1 intValue]]];
NSString *value2 = [dict objectForKey:#"BrightnessValue"];
[self setImageBrightnessValue:[NSNumber numberWithFloat:[value2 floatValue]]];
NSString *value3 = [dict objectForKey:#"ExposureTime"];
[self setImageExposureTime:[NSNumber numberWithFloat:[value3 floatValue]]];
NSString *value4 = [dict objectForKey:#"ApertureValue"];
[self setImageApertureValue:[NSNumber numberWithFloat:[value4 floatValue]]];
NSArray *values = [dict objectForKey:#"ISOSpeedRatings"];
[self setImageISOSpeedRatings:[NSNumber numberWithFloat:[ [values objectAtIndex:0] floatValue]]];
// must be at end
[[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:nil];
}];
}
/********************************************************************************/
- (void)dealloc {
[[self captureSession] stopRunning];
// [super dealloc];
}
/************************************************************************************/
#end
You need to tell the device you want to use custom settings.
Like this :
if([device isExposureModeSupported:AVCaptureExposureModeCustom])
{
[device setExposureMode:AVCaptureExposureModeCustom];
[device setExposureModeCustomWithDuration:exposureTime ISO:exposureISO completionHandler:^(CMTime syncTime) {}];
[device setExposureTargetBias:exposureBIAS completionHandler:^(CMTime syncTime) {}];
}
You are skipping the setExposureMode..
Hope this works.

NSPersistentStoreCoordinator database storage location applicationSupportFolder issue

Right now my App is placing the database in the ~/Library folder but I would like it to place it in a more organized manner ~/Library/App Name but I can not figure out how to do that with this block of code.
(NSPersistentStoreCoordinator *) persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSFileManager *fileManager;
NSString *applicationSupportFolder = nil;
NSString *dataFilePath;
NSURL *url;
NSError *error;
fileManager = [NSFileManager defaultManager];
applicationSupportFolder = [self applicationSupportFolder];
if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
[fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil];
}
dataFilePath = [applicationSupportFolder stringByAppendingPathComponent: #"sample.dat"];
if( NO == [[ NSFileManager defaultManager ] fileExistsAtPath: dataFilePath ] )
{
[[ NSFileManager defaultManager ] copyPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: #"sample.dat"]
toPath: dataFilePath handler: NULL ];
}
url = [NSURL fileURLWithPath:dataFilePath];
if( url )
{
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]){
[[NSApplication sharedApplication] presentError:error];
}
}
return persistentStoreCoordinator;
}
This code works it just places the database in a pretty terrible location IMO. I am new to Obj-C and just inherited this code set from a another developer.
UPDATE:
Adding the final working code below.
(NSPersistentStoreCoordinator *) persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSFileManager *fileManager;
NSString *applicationSupportFolder = nil;
NSString *dataFilePath;
NSURL *url;
NSError *error;
fileManager = [NSFileManager defaultManager];
applicationSupportFolder = [self applicationSupportFolder];
NSString *aappSupportFolder = [applicationSupportFolder stringByAppendingPathComponent: #"APP"];
if ( ![fileManager fileExistsAtPath:aappSupportFolder isDirectory:NULL] ) {
[fileManager createDirectoryAtPath:aappSupportFolder attributes:nil];
}
dataFilePath = [aappSupportFolder stringByAppendingPathComponent: #"sample.dat"];
if( NO == [[ NSFileManager defaultManager ] fileExistsAtPath: dataFilePath ] )
{
[[ NSFileManager defaultManager ] copyPath: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: #"sample.dat"]
toPath: dataFilePath handler: NULL ];
}
url = [NSURL fileURLWithPath:dataFilePath];
if( url )
{
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]){
[[NSApplication sharedApplication] presentError:error];
}
}
return persistentStoreCoordinator;
}
Well it is very simple just you have to create folder name APP inside library folder of your machine and then you have to move your app inside the same path . Please try below:-
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *pathString= [paths objectAtIndex:0];
NSError *err=nil;
//below is your application previous path which we will move to new path
NSString *dataFilePath = [pathString stringByAppendingPathComponent: #"sample.dat"];
NSString *applicationSupportFolder = [pathString stringByAppendingPathComponent: #"App"];
//Here we have created directory folder as App inside Library below
if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
[fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil];
}
if ([fm moveItemAtPath:dataFilePath toPath:applicationSupportFolder error:&err])
{
NSLog(#"success");
}
else
{
NSLog(#"%#",[err localizedDescription]);
}

Using multiple imagepickers on one view

I have a working imagepicker that upon button click and hold gesture, allows the user to upload an image to the disk, and the user can change the image using the same gesture. The only issue is, however, I need this to be done twice on the same view (i.e. I have two imageviews, two buttons to change each of the imageviews, etc.), and I am stumped on how to get the second one to work. This is essentially what the view looks like:
Here is my current code:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//
// Saving into Documents folder
//
NSString* path = [NSHomeDirectory() stringByAppendingString:#"/Documents/first.png"];
BOOL ok = [[NSFileManager defaultManager] createFileAtPath:path
contents:nil attributes:nil];
if (!ok) {
NSLog(#"Error creating file %#", path);
} else {
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[myFileHandle writeData:UIImagePNGRepresentation(info [UIImagePickerControllerOriginalImage])];
[myFileHandle closeFile];
}
//
// Loading from documents
//
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
UIImage* loadedImage = [UIImage imageWithData:[myFileHandle readDataToEndOfFile]];
self.chosenImage = loadedImage;
[self.imageView setImage:self.chosenImage];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)onLongTile:(UILongPressGestureRecognizer *)gesture
{
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:{
NSString *actionSheetTitle = #"Photo Options"; //Action Sheet Title
NSString *type = #"Upload Photo";
NSString *cancelTitle = #"Cancel";
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:actionSheetTitle
delegate:self
cancelButtonTitle:cancelTitle
destructiveButtonTitle:nil
otherButtonTitles:type, nil];
[actionSheet showInView:self.view]; }
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Photo"]) {
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
[self.imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
}
Updated code with tags:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if (self.imageViewOne.tag == 100)
{
//
// Saving into Documents folder
//
NSString* path = [NSHomeDirectory() stringByAppendingString:#"/Documents/one.png"];
BOOL ok = [[NSFileManager defaultManager] createFileAtPath:path
contents:nil attributes:nil];
if (!ok) {
NSLog(#"Error creating file %#", path);
} else {
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[myFileHandle writeData:UIImagePNGRepresentation(info [UIImagePickerControllerOriginalImage])];
[myFileHandle closeFile];
}
//
// Loading from documents
//
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
UIImage* loadedImage = [UIImage imageWithData:[myFileHandle readDataToEndOfFile]];
self.chosenImageOne = loadedImage;
[self.imageViewOne setImage:self.chosenImageOne];
[self dismissViewControllerAnimated:YES completion:nil];
}
if (self.imageViewTwo.tag == 200)
{
//
// Saving into Documents folder
//
NSString* path = [NSHomeDirectory() stringByAppendingString:#"/Documents/two.png"];
BOOL ok = [[NSFileManager defaultManager] createFileAtPath:path
contents:nil attributes:nil];
if (!ok) {
NSLog(#"Error creating file %#", path);
} else {
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[myFileHandle writeData:UIImagePNGRepresentation(info [UIImagePickerControllerOriginalImage])];
[myFileHandle closeFile];
}
//
// Loading from documents
//
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
UIImage* loadedImage = [UIImage imageWithData:[myFileHandle readDataToEndOfFile]];
self.chosenImageTwo = loadedImage;
[self.imageViewTwo setImage:self.chosenImageTwo];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
From what I understood of the question, set tags to your UIImageView and change is accordingly. something like:
[self.imageViewOne setTag:100];
[self.imageViewTne setTag:200];
And then in your delegates you can check the tag value and do the needful:
if ( imageView.tag == 100)
{
// Code for first imageView
}

didReceiveData only getting called once on resuming download

I have a problem which I could really do with some help with please
I am using NSURLconnection to download a large file (27MB). the code work fine when there is no network interruption. In order to allow for network issues and only partially downloaded file I have added code to check to see how much of the file is downloaded and then using a server request to download the missing portion.
The code works as it should IF I download part of file, stop the program running and then run again - the download then commences where it left off and i have complete file.
However if I hit the download button a second time without stopping the program then didReceiveData only gets called once and adds just 200KB to the file and it tells me file has been succesfully downloaded.
Help please - I have spent ages trying to figure out what I'm doing wrong.
Code below:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"Response code = %d",httpResponse.statusCode );
file = [NSFileHandle fileHandleForUpdatingAtPath:filename] ;// file is in .h
if (file) {
[file seekToEndOfFile];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if (file) {
[file seekToEndOfFile];
NSLog(#"file is %#",file);
}
[self.file writeData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if([[NSFileManager defaultManager] fileExistsAtPath:filename])
{
[file closeFile];
file = nil;
theConnection = nil;
filename = nil;
theRequest = nil;
}
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[file closeFile];
file = nil;
theConnection = nil;
filename = nil;
}
- (IBAction)downloadFile:(id)sender {
filename = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:movie1]; // filename is in .h file
theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:movieDownload1] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSUInteger downloadedBytes = 0;
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:filename]) {
NSError *error = nil;
NSDictionary *fileDictionary = [fm attributesOfItemAtPath:filename error:&error];
if (!error && fileDictionary)
downloadedBytes = [fileDictionary fileSize];
} else {
[fm createFileAtPath:filename contents:nil attributes:nil];
}
if (downloadedBytes > 0) {
NSString *requestRange = [NSString stringWithFormat:#"bytes=%d-",downloadedBytes];
[theRequest setValue:requestRange forHTTPHeaderField:#"Range"];
}
theConnection = nil;
theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];
}
Instead of using seekToEndOfFile in didReceiveResponse and didReceiveData, you can try the following code snippet. It worked well for me.
- (id)initWithURL:(NSString *)downloadString
{
if (![super init])
return nil;
// Construct the URL to be downloaded
self.downloadURL = [[NSURL alloc]initWithString:downloadString];
self.downloadData = [[NSMutableData alloc] init];
self.downloadedFilename = [[self.downloadURL path] lastPathComponent];
[self downloadFile];
return self;
}
-(void) downloadFile
{
// set the filePath
docFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: #"Documents/%#", self.downloadedFilename]];
self.downloadStream = [NSOutputStream outputStreamToFileAtPath:docFolderPath append:NO];
if (!self.downloadStream)
{
self.error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier
code:-1
userInfo:#{#"message": #"Unable to create NSOutputStream", #"function" : #(__FUNCTION__), #"path" : self.downloadedFilename}];
return;
}
[self.downloadStream open];
self.downloadConnection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self];
[self.downloadConnection start];
}
//code snippet for the Resume functionality after your downloading gets paused/cancel
-(void) resumeInterruptedDownload
{
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:docFolderPath])
{
NSError *error = nil;
NSDictionary *fileDictionary = [fm attributesOfItemAtPath:docFolderPath
error:&error];
if (!error && fileDictionary)
self.downloadedBytes = [fileDictionary fileSize];
} else
{
[fm createFileAtPath:docFolderPath contents:nil attributes:nil];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
// Define the bytes we wish to download.
if(self.downloadedBytes != 0)
{
NSString *range = [NSString stringWithFormat:#"bytes=%i-", self.downloadedBytes];
[request setValue:range forHTTPHeaderField:#"Range"];
}
// Data should immediately start downloading after the connection is created.
self.downloadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE];
}
It worked perfectly for me in case of the large files in Mbs but for the small files in Kbs it sometimes fails. You don't have to try much in all these delegate methods of NSURLConnection. One thing you can do is that set the macros for each state i.e, cancel, pause, downloading,downloaded so that you can come to know that when do you want to resume the downloading. Also you can try the following http://nachbaur.com/blog/resuming-large-downloads-with-nsurlconnection.
I know it is too late to reply, but I just got into IOS. If you try this, please let me know whether it worked or not. Thanks :) :)

Resources