如何将NSUrl转换为NSString?

35

在完成导出视频后,我计划获取视频路径并通过Youtube上传。但是 [GDataUtilities MIMETypeForFileAtPath:path defaultMIMEType:@"video/mp4"]; 只接受 NSString 类型的参数。是否可以将 NSUrl 转换为视频文件路径的 NSString 类型?

我尝试使用 NSString *path = [ExportoutputURL absoluteString];,但它会导致崩溃。

以下是代码:

- (void)exportDidFinish:(AVAssetExportSession*)session {
    ExportoutputURL = session.outputURL;

    _exporting = NO;
    NSIndexPath *exportCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:kProjectSection];
    ExportCell *cell = (ExportCell*)[self.tableView cellForRowAtIndexPath:exportCellIndexPath];
    cell.progressView.progress = 1.0;
    [cell setProgressViewHidden:YES animated:YES];
    [self updateCell:cell forRowAtIndexPath:exportCellIndexPath];

    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:ExportoutputURL]) {
        [library writeVideoAtPathToSavedPhotosAlbum:ExportoutputURL
                                    completionBlock:^(NSURL *assetURL, NSError *error){
                                        dispatch_async(dispatch_get_main_queue(), ^{
                                            if (error) {
                                                NSLog(@"writeVideoToAssestsLibrary failed: %@", error);
                                                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription]
                                                                                                    message:[error localizedRecoverySuggestion]
                                                                                                   delegate:nil
                                                                                          cancelButtonTitle:@"OK"
                                                                                          otherButtonTitles:nil];
                                                [alertView show];
                                                [alertView release];
                                            }
                                            else {
                                                _showSavedVideoToAssestsLibrary = YES;
                                                ExportCell *cell = (ExportCell*)[self.tableView cellForRowAtIndexPath:exportCellIndexPath];
                                                [cell setDetailTextLabelHidden:NO animated:YES];
                                                [self updateCell:cell forRowAtIndexPath:exportCellIndexPath];
                                                NSArray *modes = [[[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, UITrackingRunLoopMode, nil] autorelease];
                                                [self performSelector:@selector(hideCameraRollText) withObject:nil afterDelay:5.0 inModes:modes];
                                            }
                                        });

                                    }];
    }
    [library release];
}

- (void)uploadVideoFile {

    NSString *devKey = DEVELOPER_KEY;

    GDataServiceGoogleYouTube *service = [self youTubeService];
    [service setYouTubeDeveloperKey:devKey];

    NSURL *url = [GDataServiceGoogleYouTube youTubeUploadURLForUserID:kGDataServiceDefaultUser];

    // load the file data
    NSString *path = [ExportoutputURL absoluteString];//[[NSBundle mainBundle] pathForResource:@"video_2451" ofType:@"mp4"];//[mFilePathField stringValue];
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSString *filename = [path lastPathComponent];

    // gather all the metadata needed for the mediaGroup
    NSString *titleStr = @"Upload Test";//[mTitleField stringValue];
    GDataMediaTitle *title = [GDataMediaTitle textConstructWithString:titleStr];

    NSString *categoryStr = @"Entertainment";//[[mCategoryPopup selectedItem] representedObject];
    GDataMediaCategory *category = [GDataMediaCategory mediaCategoryWithString:categoryStr];
    [category setScheme:kGDataSchemeYouTubeCategory];

    NSString *descStr = @"GData Description";//[mDescriptionField stringValue];
    GDataMediaDescription *desc = [GDataMediaDescription textConstructWithString:descStr];

    NSString *keywordsStr = @"RAGOpoR Demo";//[mKeywordsField stringValue];
    GDataMediaKeywords *keywords = [GDataMediaKeywords keywordsWithString:keywordsStr];

    BOOL isPrivate = NO;//([mPrivateCheckbox state] == NSOnState);

    GDataYouTubeMediaGroup *mediaGroup = [GDataYouTubeMediaGroup mediaGroup];
    [mediaGroup setMediaTitle:title];
    [mediaGroup setMediaDescription:desc];
    [mediaGroup addMediaCategory:category];
    [mediaGroup setMediaKeywords:keywords];
    [mediaGroup setIsPrivate:isPrivate];

    NSString *mimeType = [GDataUtilities MIMETypeForFileAtPath:path
                                               defaultMIMEType:@"video/mp4"];

    // create the upload entry with the mediaGroup and the file
    GDataEntryYouTubeUpload *entry;
    entry = [GDataEntryYouTubeUpload uploadEntryWithMediaGroup:mediaGroup
                                                    fileHandle:fileHandle
                                                      MIMEType:mimeType
                                                          slug:filename];

    SEL progressSel = @selector(ticket:hasDeliveredByteCount:ofTotalByteCount:);
    [service setServiceUploadProgressSelector:progressSel];

    GDataServiceTicket *ticket;
    ticket = [service fetchEntryByInsertingEntry:entry
                                      forFeedURL:url
                                        delegate:self
                               didFinishSelector:@selector(uploadTicket:finishedWithEntry:error:)];
    [self setUploadTicket:ticket];
    GTMHTTPUploadFetcher *uploadFetcher = (GTMHTTPUploadFetcher *)[ticket objectFetcher];

}

出现错误 EXC_BAD_ACCESS,位于

NSString *path = [ExportoutputURL absoluteString];

1
这应该可以工作,也许你之前释放了NSURL?你能够展示一些代码吗? - MByD
1
你正在做的应该是可以工作的。请发布更多的代码。 - madmik3
你的NSURL实例是否不为nil? - user529758
@H2CO3 好的,如果向NSURL对象发送消息会导致崩溃,那么它肯定不是nil。如果它是nil,就不会崩溃。 - Peter Hosey
@Dimme 你假定那是正确的保留位置,这不是一个好的假设。更好的方法是在需要保留的地方添加保留语句,如果需要的话;如果问题是过度释放,正确的解决方法是移除它。 - Peter Hosey
显示剩余5条评论
5个回答

59
是的。给它发送一个"absoluteString"消息即可将NSUrl转换为视频文件路径的NSString对象。
如果您想要一个路径,请向URL发送“path”消息。 代表URL的字符串通常不是有效的路径; 如果您想要路径,请请求它。
至于崩溃,这并不意味着“absoluteString”是错误的。 向NSURL对象发送“absoluteString”是获取表示URL的NSString对象的正确方法。 问题出在其他地方。
错误EXC_BAD_ACCESS。
NSString *path = [ExportoutputURL absoluteString];
这可能意味着ExportoutputURL指向的不是nil,但也不是一个有效的对象。它可能曾经指向过NSURL对象,但现在不是了。
我猜问题出在这里:
ExportoutputURL = session.outputURL;
你将URL分配给ExportoutputURL实例变量,但没有保留该对象或制作自己的副本。因此,你不拥有这个对象,这意味着你没有让它存活。它可能在任何时候死亡,最有可能是在这个方法(exportDidFinish:)返回后。
崩溃发生是因为你稍后调用了uploadVideoFile,而此时URL对象已经不存在了。你仍然持有一个指向它的指针,但那个对象不再存在了,所以发送消息给它 - 任何消息 - 都会导致崩溃。
有三种简单的解决方案:
1.在将其分配给实例变量时保留URL对象。 2.制作URL对象的副本,并将其分配给实例变量。 3.将ExportoutputURL声明为属性,带有strong关键字或copy关键字,并将对象分配给属性,而不是实例变量。这将调用属性的setter,如果你合成或正确地实现它,将为你保留或复制URL。
无论哪种方式,你都将拥有这个对象,这将使它保持活动状态,直到你释放它。因此,在使用完毕后(在dealloc中或更早),你需要释放它,以避免泄漏。
所有这些都假定你没有使用ARC。如果你正在使用Xcode 4.2或更高版本,并且可以要求iOS 4或更高版本,你应该将项目迁移到ARC,因为它使很多事情变得简单。如果使用ARC,就不需要保留或复制此对象,这意味着现在迁移到ARC是第四个解决方案(但肯定是一个更大规模的解决方案)。

13

MiekNepster 所述,请使用 absolutePathpath。从他们的回答中可以得知,两者的区别在于前缀。

NSString* string1 = [url absoluteString]; // @"file:///Users/jackbrown/Music/song name.mp3"
NSString* string2 = [url path]; // @"/Users/jackbrown/Music/song name.mp3"`

11
NSString *path = [[NSString alloc] initWithString:[url path]];  ?

1

使用这个。我认为它会对你有所帮助。

在 Objective-C 中

NSString *testString = testUrl.absoluteString;

在Swift中

var testString : String = testUrl.absoluteString

0

你可以简单地像这样做。

NSString *myString = [myURL absoluteString];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接