How to share text of a label from iPhone app to facebook? - iphone

I have written a simple Xcode project in swift for my iPhone . I am trying to send the text of my label to facebook using facebook share option .
Below is my code
import UIKit
import Social
class ViewController: UIViewController {
#IBOutlet weak var musicDescription: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func faceBookShareButton(sender: UIButton) {
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook) {
let fbShare:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
let text = musicDescription.text
fbShare.setInitialText(text)
self.presentViewController(fbShare, animated: true, completion: nil)
} else {
let alert = UIAlertController(title: "Accounts", message: "Please login to a Facebook account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
But i am not able to see the text of the label in my facebook timeline. Someone guide me here . Why is the text not posting in facebook ?
Edit:Update
I downloaded FBSDK files and added them to my project . I imported FBSDKShareKit into my ViewController.h file.
Here is my code
#IBAction func faceBookShareButton(sender: UIButton) {
if UIApplication.sharedApplication().canOpenURL(NSURL(string: "fb:")!) {
var content: FBSDKShareLinkContent = FBSDKShareLinkContent()
var Subject: String = String(format: "FBSDKShareKit is an alternative to this issue")
content.contentTitle = "FBSDKShareKit"
content.contentDescription = Subject
var dialog: FBSDKShareDialog = FBSDKShareDialog()
dialog.fromViewController = self
dialog.shareContent = content
dialog.mode = FBSDKShareDialogModeWeb
dialog.show()
}
I am getting an error "Use of unresolved identifier FBSDKShareDialogModeWeb"
.
Anyone help please !

You have to check return value of setInitialText(_:) method.
That function can return false. Apple document describes following.
Return Value
Returns a Boolean value indicating whether the text was successfully set.

Using FBSDKShareKit is not an complete alternative but it helps to show your pre-filled content on the share dialog screen.
For basic check the following link cocoapods.Open your terminal install cocoapods
$ sudo gem install cocoapods
open your project directory,like this eg: cd/desktop/TestSwift,
Then to create pod file in your project after opening your project directory add the following line pod init this will create a podfile inside your project
Open the podfile in TextEdit from finder.to install FBSDK add pod 'FBSDKShareKit' the entire podfile will look like this
platform :ios, '8.0'
use_frameworks!
target 'TestSwift' do
pod 'FBSDKShareKit','~> 4.8.0'
pod 'FBSDKCoreKit','~> 4.8.0'
end
target 'TestSwiftTests' do
end
target 'TestSwiftUITests' do
end
Now in your terminal inside your project directory type pod install add hit enter this will install all the pod's added in your podfile.
Installing FBSDKShareKit (4.8.0)
NOTE: After installing pod in your project .xcworkspace file will be created. Instead of using .xcodeproj you have to use .xcworkspace for further process of your project
Since we are using swift we have to add Bridging Header to over project.it helps in adding Objective-C frame work in swift project.
How to create bridging header: Use Command ⌘ + N the under ios-source choose header file name it as *BridgingHeader.h** select location and then create it.
Then import your pod-file inside the bridging header file it should look like as follows
#ifndef BridgingHeader_h
#define BridgingHeader_h
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKShareKit/FBSDKShareKit.h>
#endif /* BridgingHeader_h */
Now we have successfully created bridging header to make sure your bridging header is added successfully open Targets then select your target open Build Settingtab in search bar type bridging.In search result under Objective-C BridgingHeader you should have your ProjectName/BridgingHeader.h
Now add the code in your button action as follows:
if UIApplication.sharedApplication().canOpenURL(NSURL(string: "fb:")!) {
let content : FBSDKShareLinkContent = FBSDKShareLinkContent()
content.contentURL = NSURL(string: "https://google.com")
content.contentTitle = "Test"
content.contentDescription = "FBSDKShareKit is an alternative to this issue"
content.imageURL = NSURL(string:"https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg")
let ShareKit: FBSDKShareDialog = FBSDKShareDialog()
ShareKit.fromViewController = self;
ShareKit.shareContent = content
ShareKit.mode = FBSDKShareDialogMode.FeedBrowser
ShareKit.show()
}
Use of unresolved identifier FBSDKShareDialogModeWeb to fix this replace dialog.mode as follows
ShareKit.mode = FBSDKShareDialogMode.FeedBrowser
I'am using .FeedBrowser,because is working fine for me.
FBShareDialogue:
FBTimeline:
Now we got everything in timeline.Title,Description,Image,SiteURL.

Related

Unable to save images to Egnyte/Google Drive/Dropbox - Swift/Xcode

UPDATE
I tried the following code solution and it allows for me to save to Google Drive now, but Egnyte and Dropbox are still greyed out.
func exportPhotosToFileLocation() {
var fileURLArray = [URL]()
for data in reviewDataController.tableViewReviewData {
guard let imageData = data.image.jpegData(compressionQuality: 1.00) else {
print("ERROR: Unable to print convert image to jpegData in exportPhotosToFileLocation!")
return
}
let fileManager = FileManager.default
do {
let fileURL = fileManager.temporaryDirectory.appendingPathComponent("\(data.imageTitle)").appendingPathExtension("jpeg")
try imageData.write(to: fileURL)
fileURLArray.append(fileURL)
print("Successfully created file from jpegData in exportPhotosToFileLocation!")
} catch {
print("ERROR: Unable to create file from jpegData in exportPhotosToFileLocation!")
return
}
}
if #available(iOS 14, *) {
let controller = UIDocumentPickerViewController(forExporting: fileURLArray)
present(controller, animated: true)
}
else {
let controller = UIDocumentPickerViewController(urls: fileURLArray, in: .exportToService)
present(controller, animated: true)
}
}
Here is the developer documents for Egnyte. Unfortunately, none of it makes sense to me as a beginner.
Egnyte Developer Documentation
----------------------------------------------------------------------------------------------
ORIGINAL POST
In my app, I'm trying to allow the user to select a save location (so choose a folder). Whenever I use this code, Egnyte/Google Drive/Dropbox are all "greyed" out and inaccessible.
let supportedTypes : [UTType] = [UTType.folder]
let documentPickerController = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes)
documentPickerController.delegate = self
self.present(documentPickerController, animated: true, completion: nil)
If I change supportedTypes to
let supportedTypes : [UTType] = [UTType.text]
It does let me access them. Does anyone have a solution for this? I obviously need the user to be able to select a folder in these applications... you can see why that is important.
This is up to the file provider extension (Google Drive, etc.). To allow picking a folder, the file provider has to lay content in its directory in a hierarchical manner... if they do this, they need to specify NSExtensionFileProviderSupportsPickingFolders in their Info.plist to tell the system it's allowed to choose folders.
Do you need to choose a save location and persist it? If yes, then you'll be blocked on the file provider implementing the necessary API. If not, the type you pass should the type of the document you are actually saving. The document will be saved once in the chosen folder (without any additional requirements on the file provider extension), and you will have to use the document picker again to save the next document.
If you are trying to select Dropbox as a location to import files from in the Apple File Importer but it does not advance to the file selection screen I found that restarting my iPhone seemed to resolve that issue.

Got an error when dragging files using NSEvent. (macOS)

I wanna drag files to my window and then perform actions.
I tried to use snippets below provided in this answer to distinguish whether you're dragging a file or a window.
// In my window controller
class MyWindowController: NSWindowController {
init() {
// Some initialization steps below are omitted
let win = NSWindow(...)
super.init(window: win)
let contentView = DropView(frame: win.frame)
win.contentView?.addSubview(contentView)
registerGlobalMouseEvent()
}
func registerGlobalMouseEvent() {
self.window?.acceptsMouseMovedEvents = true
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// Codes below will cause errors
let pasteBoard = NSPasteboard(name: .drag)
guard let fileNames = pasteBoard.propertyList(forType: .init(rawValue: "NSFilenamesPboardType")) as? NSArray else { return }
let changeCount = pasteBoard.changeCount
if fileNames.count > 0 && lastChangeCount != changeCount {
lastChangeCount = changeCount
// My actions when dragging
}
})
}
}
Then I ran my codes and started dragging, I got three errors:
[sandbox] Failed to get a sandbox extension
[Framework] Failed to issue sandbox extension for /Users/roy/Downloads/test.txt with error 1
[default] Failed to issue sandbox token for URL: 'file:///Users/roy/Downloads/test.txt' with error: 'Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedDescription=Cannot issue a sandbox extension for file "/Users/roy/Downloads/test.txt": Operation not permitted}'
 
But when I just do
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
// My actions
})
, then everything went fine.
 
The first error seems harmless since it didn't prevent my app from running.
The second and the third ones are deadly and directly caused my app to crash.
I wonder if there are any problems in his code? Any useful thoughts would be great! :)
 
You need to know about Bookmarks and Security Scoped URLs when working with sandbox . A dragged URL gives your app process permission just once to read or read/write a “user selected file” depending on how you configure entitlements.
You can save a bookmark (blob of data) to keep access over subsequent sessions as long as the file isn’t updated by another process at which point the bookmark becomes stale and you will need to encourage the user to select the file again.
Handing a URL to another process across an XPC boundary like sharing requires that you own the file so may involve a copy to your sandbox cache.
e.g:
let dragurl = url_of_dragged_file //at this point you have at-least read access
let cachepath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
let cachedir = URL(fileURLWithPath: cachepath)
let cacheurl = cachedir
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension(dragurl.pathExtension)
try FileManager.default.copyItem(at: dragurl, to: cacheurl)
At this point you have a copy in your local sandbox cache that can be handed off to a share sheet.
So I finally got a solution for this. :)
It appears that it indeed have something to do with the snippets I mentioned above, and here's the correction:
NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged, handler: { [self] event in
let pasteboard = NSPasteboard(name: .drag)
let changeCount = pasteboard.changeCount
if lastChangeCount != changeCount {
lastChangeCount = changeCount
if pasteboard.canReadObject(forClasses: [NSURL.self], options: [:]) {
/// actions
}
}
})
In this way, I got no errors and my codes run perfectly!

Unable to get Model from Request<VIMVideo>(VimeoNetworking)

I have integrated in a ios app VimeoNetworking , using the code from the git directly because i cannot integrate using cocoapods (not compatible use of use_frameworks! with other pods) for getting private link to some videos (i have a pro account).
I'm able to authenticate and request video info. When the request is returned and assigned to the class (VIMVideo) the object is not loaded correctly.
If i get the response returned returns correctly a dictionary of 30 items with the video info.
I have checked the same code from the VimeoNetworking example code and it's works in the other project (using same credentials, only different one use pod of Vimeo and the other not)
If i compare the two json responses, both have the same data but in a different order. I have the feeling that the problem is with the de-serialization used by AFNetworking (3.1.0)
Previous authentication
let authenticationController = AuthenticationController(client: VimeoClient.defaultClient, appConfiguration: AppConfiguration.defaultConfiguration, configureSessionManagerBlock: nil)
authenticationController.accessToken(token:tkn) { result in
switch result
{
case .success(let account):
print("authenticated successfully: \(account)")
break;
case .failure(let error):
print("failure authenticating: \(error)")
}
}
Video Request
let requestdir: Request<VIMVideo> = Request<VIMVideo>(path: "/videos/XXXXXXXX")
let _ = VimeoClient.defaultClient.request(requestdir) { [weak self] result in
switch result
{
case .success(let response):
//Here videodir have not value, but
var videodir: VIMVideo! = response.model
case .failure(let error):
let title = "Video Request Failed"
let message = "\(requestdir.path) could not be loaded: \(error.localizedDescription)"
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(action)
strongSelf.present(alert, animated: true, completion: nil)
}
}
Console capture (1)
Pod file from VIMEO EXAMPLE (Extract)
def shared_pods
pod 'AFNetworking', '3.1.0'
pod 'SwiftLint', '0.25.1'
pod 'VimeoNetworking', :path => '../VimeoNetworking'
end
Pod file from my project (Extract)
target 'LibroDig' do
pod 'RestKit', '~> 0.27.3'
pod 'JSONModel'
pod 'SDWebImage', '~>3.8'
pod 'AFNetworking', '3.1.0'
end
I expected the VIMVideo load correctly all the properties. I'm unable to find the difference between the 2 implementations.
Thanks in advance
If everything else is the same, you might be running into issues from opting out of using use_frameworks!.
For example, when I remove this from the Podfile used in the VimeoNetworking example project, I'll see this warning:
The Swift pod VimeoNetworking-iOS depends upon AFNetworking-iOS, which do not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set use_modular_headers! globally in your Podfile, or specify :modular_headers => true for particular dependencies.
This article explains the need for use_modular_headers! and mentions interoperability with Objective-C. VimeoNetworking relies on model classes defined in Objective-C, and I wonder if mapping to those models is being affected.

how to open an app from Mac from Xcode project (Cocoa App)

Today I have created an Cocoa Application for the very first time . I want to create a simple App which will open an APP from my Mac , if the file not found it will show a Link in a Label to download the App. Here is my code below which I am struggling with .
if let fileCheck = NSURL.fileURL(withPath: "/Applications/Mango.app") {
if NSWorkspace.shared().open(fileCheck as URL) {
print("url successfully opened")
}
} else {
self.downloadLink.insertText("Invalid Path")
}
NSURL.fileURL(withPath: "/Applications/Mango.app") giving me Conditional Binding Must be Optional , I don't know how to fix that. And I am struggling with how to show a link on my Label either. Any kind hearted Dev please help.
got the solution by someone , I don't know why he deleted that !
if FileManager().fileExists(atPath: "/Applications/Mango.app") {
NSWorkspace.shared().open(NSURL(fileURLWithPath: "/Applications/Mango.app") as URL)
} else {
downloadLink.isHidden = false
}

Open another Mac app

In my app I would like to open another app that is installed on the User's Mac (such as iPhoto). I am not sure what I should be looking for in the documentation. What is this called and how should I do it?
Thank you
Swift 5 or later
import Cocoa
func openPhotos() -> Bool {
if let photosApp = FileManager.default.urls(
for: .applicationDirectory,
in: .systemDomainMask
).first?.appendingPathComponent("Photos.app") {
return NSWorkspace.shared.open(photosApp)
}
return false
}
Usage:
if openPhotos() {
print(true)
}
Or using launchApplication with the app name parameter in the method:
import Cocoa
func openApp(_ named: String) -> Bool {
NSWorkspace.shared.launchApplication(named)
}
Usage:
if openApp("Photos") {
print(true)
}
XCode 11 • MacOS Catalina 10.15 • Swift 5
NSWorkspace.shared.launchApplication is deprecated and starting from the MacOS 10.15 the new function NSWorkspace.shared.openApplication shall be used.
Example - open terminal application by its bundle id
guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.Terminal") else { return }
let path = "/bin"
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = [path]
NSWorkspace.shared.openApplication(at: url,
configuration: configuration,
completionHandler: nil)
Example - open terminal application by its path
let url = NSURL(fileURLWithPath: "/System/Applications/Utilities/Terminal.app", isDirectory: true) as URL
let path = "/bin"
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = [path]
NSWorkspace.shared.openApplication(at: url,
configuration: configuration,
completionHandler: nil)
You can use NSWorkspace class written by Swift/Cocoa.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/index.html#//apple_ref/occ/instm/NSWorkspace/launchApplication:
let task = NSTask.launchedTaskWithLaunchPath(<#path: String#>, arguments: <#[AnyObject]#>) will probably do what you want
I second the answer by vookimedlo - unfortunately, I cannot yet comment (silly reputation limit) so I post this as an extra answer.
This is just one caveat, which might not affect too many: while launchApplication() accepted a path to an executable (e.g. "MyApp.app/Contents/MacOS/MyApp"), this will result in an error (lacking privileges) with openApplication(::). You have to supply the path to the app bundle ("MyApp.app") instead.
Of particular interest when you try to make a helper ("launcher") to add as a login item. See the following and keep my comment in mind:
https://theswiftdev.com/2017/10/27/how-to-launch-a-macos-app-at-login/
(GREAT article by Tibor Bödecs)
BTW, as for vookimedlo's code: in my experience, you don't need to specify the OpenContext.arguments with [path], you can simply pass a default NSWorkspace.OpenContext()...
There are different ways to do that. The most efficient is to use fvork and execve - see man vfork and man execve.
Less efficient but more flexible is to use the system library call. What that actually does is runs a shell - like bash - then passes the string you provide, to bash. So you can set up pipelines, redirection and such.
Or you can send an Apple Event to the Finder: "Tell Finder Open iPhoto".
In the first two cases you want to launch the executable inside the bundle, that is, /Applications/iPhoto.app/Contents/MacOS/iPhoto.
Try the above from the command line, in the Terminal:
$ /Applications/iPhoto.app/Contents/MacOS/iPhoto
You'll see the iPhoto App launch.