7
votes

I'm writing a simple test app to upload a video to Facebook from iOS.

I'm finding it quite hard to find examples/tutorials online for how to do this with Swift since all the documentation for the FacebookSDK is in Objective-C.

I have this so far which puts a share button on my UI but it looks disabled, from what I have read this is because there is no content set but I can't see how that is possible.

    let video_content : FBSDKShareVideoContent = FBSDKShareVideoContent()

    video_content.video = FBSDKShareVideo(videoURL: getVideoURL())

    let button : FBSDKShareButton = FBSDKShareButton()
    button.shareContent = video_content

    button.frame = CGRectMake((UIScreen.mainScreen().bounds.width - 100) * 0.5, 50, 100, 25)
    self.view.addSubview(button)

my getVideoURL() functions returns a NSURL which definitely contains the url to the video (I have printed it to console and checked it points to a video I have stored in a folder earlier).

I looked at the social framework and its a shame I can't use it because it seems it is only used for sharing photos and not able to share videos.

I'm using latest versions of Xcode, Swift and Facebook SDK.

5
I had EXACTLY same problem and I solved it! Video URL should be from Library not your app so save your video and get url from library. then it will work.KimCrab

5 Answers

9
votes

converted into swift 3 and 4 :- try this

func uploadVideoOnFacebook() {
        var pathURL: URL
        var videoData: Data
        pathURL = URL(string: "Your video url string")!
        do {
            videoData = try Data(contentsOf: URL(string: "Your video url string")!)
            print(videoData)
            var strDesc : String
            strDesc = ""
            let videoObject: [String : Any] = ["title": "application Name", "description": strDesc, pathURL.absoluteString: videoData]
            let uploadRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me/videos", parameters: videoObject, httpMethod: "POST")
            self.view!.isUserInteractionEnabled = false
            uploadRequest.start(completionHandler: {(connection: FBSDKGraphRequestConnection, result: AnyObject, error: NSError) -> Void in
                if error == error {
                    NSLog("Error")

                }
                else {
                    NSLog("Success")
                }
            } as! FBSDKGraphRequestHandler)
        } catch {
            print(error)
        }

    }
3
votes

@AngryDuck

Try this code it will work

func uploadVideoOnFacebook() {
    var pathURL: NSURL
    var videoData: NSData
    pathURL = NSURL(string: self.strUploadVideoURL)!
    videoData = NSData.dataWithContentsOfURL(NSURL(string: self.strUploadVideoURL)!)
    NSString * strDesc
    strDesc = txtCaption.text!
    var videoObject: [NSObject : AnyObject] = ["title": "application Name", "description": strDesc, pathURL.absoluteString(): videoData]
    var uploadRequest: FBRequest = FBRequest(graphPath: "me/videos", parameters: videoObject, HTTPMethod: "POST")
    self.view!.userInteractionEnabled = false
    uploadRequest.startWithCompletionHandler({(connection: FBRequestConnection, result: AnyObject, error: NSError) -> Void in
        if !error {
            NSLog("Success")
        }
        else {
            NSLog("Error")
        }
    })
}
1
votes

I've done this in objective c and I had a similar problem. Do not know if this will work well for swift.

The problem was that if for some reason the video had to be stored in NSDocumentDirectory or NSTemporaryDirectory so she could work. Not if it's your case.

Although you can use in the worst case FBSDKGraphRequest with /me/Videos

I have come to see that this way of sharing videos that you are trying to use, get links directly from the library of photos. As you can see in this example

Currently only have example in objective-c i hope this can help you

- (void)uploadVideoWithoutSettingsCredentials:(NSURL *)videoUrl withTitle:(NSString *)title withDesc:(NSString *)desc withPrivacy:(NSString *)privacy
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0), ^{
        NSError * error = nil;

        NSData * videoData = [NSData dataWithContentsOfURL:videoUrl options:0 error:&error];
        NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:4L];
        [params setObject:videoData forKey:[NSString stringWithFormat:@"%@.MOV",title]];
        [params setObject:desc forKey:@"description"];

        NSString *privacyString = @"EVERYONE";
        if (privacy.length > 0)
            privacyString = privacy;

        NSDictionary *privacyDict = [[NSDictionary alloc] initWithObjectsAndKeys: privacyString, @"value", nil];
        [params setObject:[Utils objectToJsonString:privacyDict] forKey:@"privacy"];
        dispatch_async(dispatch_get_main_queue(), ^{
            [[[FBSDKGraphRequest alloc] initWithGraphPath:@"/me/videos" parameters:params HTTPMethod:@"POST"] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {

                NSLog(@"RESPONSE!!! /me/videos");
                NSLog(@"result %@",result);
                NSLog(@"error %@",error);

                dispatch_async(dispatch_get_main_queue(), ^{
                    if (!error) {
                        [[[UIAlertView alloc] initWithTitle:@"Success" message:@"Your clip was posted!" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil] show];
                    } else {
                        [[[UIAlertView alloc] initWithTitle:@"Error!" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil] show];
                    }
                });
             }];
        });
    });
} 

You can change to swift sintax, using Xcode autocomplete functionality.

You can help yourself a little with the syntax swift with this

1
votes

I have used this code in my app and this works fine for me.

This code is for Objective-C but you can use same in swift after converting it to swift syntax.

I hope this will help you.

Try code below.

-(void) uploadVideoOnFacebook 
{
    NSURL *pathURL;
    NSData *videoData;


    pathURL = [NSURL URLWithString:self.strUploadVideoURL];
    videoData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.strUploadVideoURL]];

    NSString *strDesc;
    strDesc = txtCaption.text;

    NSDictionary *videoObject = @{@"title": @"application Name",@"description": strDesc,[pathURL absoluteString]: videoData};
    FBRequest *uploadRequest = [FBRequest requestWithGraphPath:@"me/videos" parameters:videoObject HTTPMethod:@"POST"];
    [self.view setUserInteractionEnabled:NO];

    [uploadRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
           if (!error)
               NSLog("Success");
           else
               NSLog("Error");
    }];
}
1
votes

Using SDK Facebook:

https://developers.facebook.com/docs/sharing/ios

The video URL videoURL must be an asset URL. You can get a video asset URL e.g. from UIImagePickerController.

import FBSDKCoreKit
import FBSDKShareKit
import MobileCoreServices
import Photos

        func createAssetURL(url: URL, completion: @escaping (String) -> Void) {
            let photoLibrary = PHPhotoLibrary.shared()
            var videoAssetPlaceholder:PHObjectPlaceholder!
            photoLibrary.performChanges({
                let request = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url)
                videoAssetPlaceholder = request!.placeholderForCreatedAsset
            },
                completionHandler: { success, error in
                    if success {
                        let localID = NSString(string: videoAssetPlaceholder.localIdentifier)
                        let assetID = localID.replacingOccurrences(of: "/.*", with: "", options: NSString.CompareOptions.regularExpression, range: NSRange())
                        let ext = "mp4"
                        let assetURLStr =
                        "assets-library://asset/asset.\(ext)?id=\(assetID)&ext=\(ext)"

                        completion(assetURLStr)
                    }
            })
        }

        func shareFacebbok() {
            let content: FBSDKShareVideoContent = FBSDKShareVideoContent()
            let videoURLs = Bundle.main.url(forResource: "video", withExtension: "mp4")!
            createAssetURL(url: videoURLs) { url in
                let video = FBSDKShareVideo()
                video.videoURL = URL(string: url)
                content.video = video

                let shareDialog = FBSDKShareDialog()
                shareDialog.shareContent = content
                shareDialog.mode = .native
                shareDialog.delegate = self
                shareDialog.show()
            }
        }