简体   繁体   中英

Objective-C Passing NSURL to another viewcontroller

I have two view controllers: FirstViewController and SecondViewController . The project is to record a video and attach it to an email. I can record it and have it able to email, I just need to attach it. I am able to get a URL for the video in FirstViewController , but passing it isn't working.

FirstViewController -

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{

    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:@"public.movie"])
    {
       // Saving the video to phone / // Get the new unique filename
       NSString *sourcePath = [[info objectForKey:@"UIImagePickerControllerMediaURL"]relativePath];

       UISaveVideoAtPathToSavedPhotosAlbum(sourcePath, self, /*@selector(video:didFinishSavingWithError:contextInfo:)*/nil, nil);
       self.movieURL= [[NSURL alloc] initFileURLWithPath: sourcePath];
       NSLog(@"movieURL");
       NSLog(self.movieURL.absoluteString);

       SecondViewController *sendMovie = [[SecondViewController alloc] initWithNibName:@"ViewController" bundle:nil];
       sendMovie.movieU = [[NSURL alloc] initFileURLWithPath: sourcePath];
       [[self navigationController] pushViewController:sendMovie animated:YES];

       NSLog(@"movieU");
       NSLog(sendMovie.movieU.absoluteString);
   }

   [picker dismissViewControllerAnimated:YES completion:NULL];
}

SecondViewController to attach to email -

NSLog(@"1st print");
NSLog(self.movieU);
[controller addAttachmentData:[NSData dataWithContentsOfURL:self.movieU] mimeType:@"video/MOV" fileName:@"defectVideo.MOV"];
NSLog(@"2nd print");
NSLog(self.movieU.absoluteURL);
[self presentViewController:controller animated:YES completion:nil];

SecondViewController.h property of NSURL

@property(nonatomic) NSURL *movieU; 

The movieURL is a property in the FirstViewController , but I don't believe is needed.

I can see the URL in the FirstVC , but it appears nil in the SecondVC .

Solutions -

1) define NSURL *movieU as a extern instead of property.

2) else define it as a property of AppDelegate and access it.

3) or else synthesize property movieU and do allocate like -

in your FirstViewController -

 SecondViewController *sendMovie = [[SecondViewController alloc] initWithNibName:@"ViewController" bundle:nil];
 NSURL *url = [[NSURL alloc] initFileURLWithPath: sourcePath];
 sendMovie.movieU = url;
 [[self navigationController] pushViewController:sendMovie animated:YES];

And NSLog it in your SecondViewController .

Hope this helps!

There is nothing wrong with the way you are going about passing information. Try this:

    // In you code where you create the second view controller.
    SecondViewController *sendMovie = [[SecondViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    // SecondViewController viewDidLoad method being called (movieU is still nil)

    sendMovie.movieU = [[NSURL alloc] initFileURLWithPath: sourcePath]; 

    // Do a nil test here
    if (!sendMovie.movieU) {
        NSLog(@"%@",@"It's nil here!"); // If this is the case something is wrong with "sourcePath"
    } else {
        NSLog(@"%@",@"It's not nil here!");
    }

    [[self navigationController] pushViewController:sendMovie animated:YES];
    // SecondViewController viewWillAppear method being called (movieU is NOT nil)
    // SecondViewController viewDidAppear method being called (movieU is NOT nil)

This test will tell you a lot. If its nil here then the problem is not with setting the second view controller's property but with actually creating the NSURL object. It could be a lot of things like you are overwriting it somewhere in the second view controller (eg viewWillAppear method). Just follow the trail using break points, logging, etc. to follow its life time.

Edit - Debugging Procedure

Set break points where you create Second VC, set its property, push it, and finally view it (clicking on the tab). Set break points throughout the lifecycle of the second VC ( viewDidLoad , viewWillAppear , viewDidAppear , etc). This will allow you to step through the entire lifecycle of your VC. If you haven't utilized those methods go ahead and define them anyway including a call to super . As you step through these break points keep checking the value of movieU . You will see it is nil at first, then you set it (we know this from your comments), its not nil, then it becomes nil, again, etc. If you are patient and systematic you will find it and learn a whole lot about the lifecycle of VCs. If you don't systematically step through you may miss something. For instance maybe your code is creating a whole new Second VC when you click on the tab to actually look at it. Stepping through your code this way will show that.

Edit

Make sure you are testing in the viewWillAppear / viewDidAppear methods or later so that the property has actually been set. See comments in my code.

Edit

A property of retainable object pointer type which is synthesized without a source of ownership has the ownership of its associated instance variable, if it already exists; otherwise, [beginning Apple 3.1, LLVM 3.1] its ownership is implicitly strong. Prior to this revision, it was ill-formed to synthesize such a property.

From: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#property-declarations

According to this (unless you are specifying weak on the ivar - unlikely) it should be strong by default.

Good luck.

use this

self.movieURL = [NSURL fileURLWithPath:sourcePath];

instead of

self.movieURL= [[NSURL alloc] initFileURLWithPath: sourcePath];

hope this work

I got it fixed! I decided to use a singleton which uses a shared instance through another class. I created a whole new class called Singleton and only contained the sharedinstance method:

+ (id)sharedInstance {
static id sharedInstance = nil;
if (sharedInstance == nil) {
    sharedInstance = [[self alloc] init];
}
return sharedInstance;
}

Singleton.h

 @property NSURL *movieU;
 + (id)sharedInstance;

Make sure to import the singleton class to both First and Second VC.

SecondVC.m

Singleton* single = [Singleton sharedInstance];
[controller addAttachmentData:[NSData dataWithContentsOfURL: single.movieU] mimeType:@"video/MOV" fileName:@"defectVideo.MOV"];

FirstVC.m

Singleton* single = [Singleton sharedInstance];

NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:@"public.movie"]){
    // Saving the video / // Get the new unique filename
    NSString *sourcePath = [[info objectForKey:@"UIImagePickerControllerMediaURL"]relativePath];
    UISaveVideoAtPathToSavedPhotosAlbum(sourcePath, self, /*@selector(video:didFinishSavingWithError:contextInfo:)*/nil, nil);
    self.movieURL = [[NSURL alloc] initFileURLWithPath: sourcePath];
    NSLog(@"movieURL");
    single.movieU = self.movieURL;

By doing this, it successfully would pass the url containing the information for the recorded video to be attached to the email.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM