Objective-C to Swift: Facebook iOS API requestUserInfo method - objective-c

Hi I am trying to figure out how to rewrite this in swift:
- (IBAction)requestUserInfo:(id)sender
{
// We will request the user's public picture and the user's birthday
// These are the permissions we need:
NSArray *permissionsNeeded = #[#"public_profile", #"user_birthday", #"email"];
// Request the permissions the user currently has
[FBRequestConnection startWithGraphPath:#"/me/permissions" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error){
// Parse the list of existing permissions and extract them for easier use
NSMutableArray *currentPermissions = [[NSMutableArray alloc] init];
NSLog(#"The fucking class is: %#", [result class]);
NSArray *returnedPermissions = (NSArray *)[result data];
for (NSDictionary *perm in returnedPermissions) {
if ([[perm objectForKey:#"status"] isEqualToString:#"granted"]) {
[currentPermissions addObject:[perm objectForKey:#"permission"]];
}
} // cut cut here
}
EDIT:
I was having trouble trying to get the required data out of the FBGraphObject but figured it out after some further inspection. I have posted the swift version below so that people can just cut and paste it and get on with using swift. Hope it saves someone some time.

Here:
#IBAction func requestUserInfo(sender: AnyObject){
// These are the permissions we need:
var permissionsNeeded = ["public_profile", "user_birthday", "email"]
// Request the permissions the user currently has
FBRequestConnection.startWithGraphPath("/me/permissions", completionHandler: {(connection, result, error) -> Void in
if error == nil{
// Parse the list of existing permissions and extract them for easier use
var theResult = result as? [String:[AnyObject]]
var currentPermissions = [String]()
let returnedPermissions = theResult?["data"] as [[String:String]]
for perm in returnedPermissions {
if perm["status"] == "granted" {
currentPermissions.append(perm["permission"]!)
}
}
// Build the list of requested permissions by starting with the permissions
// needed and then removing any current permissions
println("Needed: \(permissionsNeeded)")
println("Current: \(currentPermissions)")
var requestPermissions = NSMutableArray(array: permissionsNeeded, copyItems: true)
requestPermissions.removeObjectsInArray(currentPermissions)
println("Asking: \(requestPermissions)")
// TODO PUT A POPUP HERE TO TELL WHAT PERMISSIONS WE NEED!
// If we have permissions to request
if requestPermissions.count > 0 {
// Ask for the missing permissions
FBSession.activeSession().requestNewReadPermissions(requestPermissions, completionHandler: {(session, error) -> Void in
if (error == nil) {
// Permission granted, we can request the user information
self.makeRequestForUserData()
} else {
// An error occurred, we need to handle the error
// Check out our error handling guide: https://developers.facebook.com/docs/ios/errors/
println("error: \(error?.description)")
}
})
} else {
// Permissions are present
// We can request the user information
self.makeRequestForUserData()
}
} else {
// An error occurred, we need to handle the error
// Check out our error handling guide: https://developers.facebook.com/docs/ios/errors/
println("error: \(error?.description)")
}
})
}
private func makeRequestForUserData() {
FBRequestConnection.startForMeWithCompletionHandler({(connection, result, error) -> Void in
if (error == nil) {
// Success! Include your code to handle the results here
println("user info: \(result)")
} else {
// An error occurred, we need to handle the error
// Check out our error handling guide: https://developers.facebook.com/docs/ios/errors/
println("error: \(error?.description)")
}
})
}
// Show an alert message
func showMessage(text : NSString, title : NSString){
var alert = UIAlertController(title: title, message: text, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
UIApplication.sharedApplication().delegate?.window!?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}

Related

FBSDKLoginManagerLoginResult return nil iOS 11

With iOS 11 FBSDKLoginManager (v.4.25.0) use SFAuthenticationSession instead of SFSafariViewController, if user cancel Sign In, FBSDKLoginManagerLoginResult always return nil and result.isCancelled code not work:
[[FBSDKLoginManager new] logInWithReadPermissions:#[PERMISSIONS]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
//Error happen
}
else if (result.isCancelled) {
//User cancel
}
else {
//Login success
}
}];
In this case always happen error with description 'com.apple.SafariServices.Authentication Code=1 "(null)"'. So, in this case, we can't discern really error from SFAuthenticationSession error. Any ideas how to handle different errors? Or just need to wait FBSDK update?
I'm using FBSDK version [ 4.17.0 ] with ios 11 and it works fine
let facebookLogin = FBSDKLoginManager()
facebookLogin.logOut()
facebookLogin.logIn(withReadPermissions: ["public_profile","email", "user_friends"], from:self, handler:
{
(facebookResult, facebookError) -> Void in
if facebookError != nil
{
print("Facebook login failed. Error \(String(describing: facebookError))")
}
else if (facebookResult?.isCancelled)!
{
print("Facebook login was cancelled.")
}
else
{
}
})

Google Drive API IOS Permissions of GTLRDriveService

I am playing around with the google drive API and trying to build a simple app that uploads a picture to my google drive. The app is supposed to upload a picture once the user is signed in, however it gives an error of
"2017-09-14 00:55:20.342237-0400 driveTest[6705:1647551] An error
occurred: Error Domain=com.google.GTLRErrorObjectDomain Code=403
"Insufficient Permission"
UserInfo={GTLRStructuredError=GTLRErrorObject 0x1c4251d30:
{message:"Insufficient Permission" errors:[1] code:403},
NSLocalizedDescription=Insufficient Permission}"
I have tried to pass it the service which is of type GTLRDriveService to the initSetup() function of the userSetUp class, but to no avail. Could someone please point me to the right track as to why my permissions are not working even though I have logged on correctly, and the part where I am passing in the GTLRDriveService is in the code that runs after a sucessful login.
I instantiate a userSetUp object and I
let setUpUser = userSetUp()
setUpUser.initSetup(service)
I have userSetUp written in objective c as such and it is bridged correctly as I am able to instantiate it in my viewcontroller file which is written in swift.
UserSetUp:::::::
#import "userSetUp.h"
#import <GoogleSignIn/GoogleSignIn.h>
#import GoogleAPIClientForREST;
#implementation userSetUp
- (void) initSetup:(GTLRDriveService *) driveService {
printf("heloooooaiosuoiadoidauoalo");
//GTLRDriveService *driveService = [GTLRDriveService new];
//NSData *fileData = [[NSFileManager defaultManager] contentsAtPath:#"files/apple.jpg"];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"apple" ofType:#"jpg"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
GTLRDrive_File *metadata = [GTLRDrive_File object];
metadata.name = #"apple.jpg";
//metadata.mimeType = #"application/vnd.google-apps.document";
GTLRUploadParameters *uploadParameters = [GTLRUploadParameters uploadParametersWithData:fileData
MIMEType:#"image/jpeg"];
uploadParameters.shouldUploadWithSingleRequest = TRUE;
GTLRDriveQuery_FilesCreate *query = [GTLRDriveQuery_FilesCreate queryWithObject:metadata
uploadParameters:uploadParameters];
query.fields = #"id";
[driveService executeQuery:query completionHandler:^(GTLRServiceTicket *ticket,
GTLRDrive_File *file,
NSError *error) {
if (error == nil) {
//NSLog(#"File ID %#", file.identifier);
printf("it worked");
} else {
NSLog(#"An error occurred: %#", error);
}
}];
printf("upload complete!");
}
#end
And Viewcontroller. swift
import GoogleAPIClientForREST
import GoogleSignIn
import UIKit
class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {
// If modifying these scopes, delete your previously saved credentials by
// resetting the iOS simulator or uninstall the app.
private let scopes = [kGTLRAuthScopeDriveReadonly]
let service = GTLRDriveService()
let signInButton = GIDSignInButton()
let output = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
// Configure Google Sign-in.
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().scopes = scopes
GIDSignIn.sharedInstance().signInSilently()
signInButton.frame = CGRect(x: view.frame.width/2 - signInButton.frame.width , y: view.frame.height/2, width: signInButton.frame.width, height: signInButton.frame.height)
// Add the sign-in button.
view.addSubview(signInButton)
// Add a UITextView to display output.
output.frame = view.bounds
output.isEditable = false
output.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)
output.autoresizingMask = [.flexibleHeight, .flexibleWidth]
output.isHidden = true
view.addSubview(output);
//let itsASetup()
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
withError error: Error!) {
if let error = error {
showAlert(title: "Authentication Error", message: error.localizedDescription)
self.service.authorizer = nil
} else {
self.signInButton.isHidden = true
self.output.isHidden = false
self.service.authorizer = user.authentication.fetcherAuthorizer()
listFiles()
}
}
// List up to 10 files in Drive
func listFiles() {
let query = GTLRDriveQuery_FilesList.query()
query.pageSize = 10
service.executeQuery(query,
delegate: self,
didFinish: #selector(displayResultWithTicket(ticket:finishedWithObject:error:))
)
}
// Process the response and display output
#objc func displayResultWithTicket(ticket: GTLRServiceTicket,
finishedWithObject result : GTLRDrive_FileList,
error : NSError?) {
if let error = error {
showAlert(title: "Error", message: error.localizedDescription)
return
}
var text = "";
if let files = result.files, !files.isEmpty {
text += "Files:\n"
for file in files {
text += "\(file.name!) (\(file.identifier!))\n"
}
} else {
text += "No files found."
}
output.text = text
let setUpUser = userSetUp()
setUpUser.initSetup(service)
}
// Helper for showing an alert
func showAlert(title : String, message: String) {
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertControllerStyle.alert
)
let ok = UIAlertAction(
title: "OK",
style: UIAlertActionStyle.default,
handler: nil
)
alert.addAction(ok)
present(alert, animated: true, completion: nil)
}
}
try to Change your scope like:
class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate
{
// If modifying these scopes, delete your previously saved credentials by
private let scopes = ["https://www.googleapis.com/auth/drive"]
...
}

how can i convert code to objective c for SMS verification

I want to parse data for twilio url,which will be used for SMS verification
Please help to convert swift to objective for following code:
#IBAction func pressedSend(sender: AnyObject) {
let code = arc4random_uniform(8999) + 1000
var data = [
"To" : textTo.text as String,
"From" : "<replace with your Twilio local number>",
"Body" : String(code) as String
]
var swiftRequest = SwiftRequest()
swiftRequest.post("https://api.twilio.com/2010-04-01/Accounts/ACc4e304c952c972c26699b927422e668953/Messages",
auth: ["username" : "ACc4e304c952c972c26699b927422e668953", "password" : "5ab5312824b1d057dea249668e2c4189"],
data: data,
callback: {err, response, body in
if err == nil {
println("Success: (response)")
} else {
println("Error: (err)")
}
})
}
Thanks for help
I do think it should be something like this. not sure about swiftRequest so I assumed its your network request class.
-(IBAction)pressedSend:(id) sender{
NSInteger code = arc4random_uniform(8999)+1000;
NSDictionary *data = #{#"To":textTo.text, // guessing this is a label?
#"From":"<replace with your Twilio local number>",
#"Body":[NSString stringWithFormat:#"%d",code]
};
SwiftRequest *swiftRequest = [SwiftRequest new];
[swiftRequest Post:#"https://api.twilio.com/2010-04-01/Accounts/ACc4e304c952c972c26699b927422e668953/Messages"
auth:#{#"username" : #"ACc4e304c952c972c26699b927422e668953",
#"password" : #"5ab5312824b1d057dea249668e2c4189"}
callback:(NSerror *error, id response){
if(error != nil){
// has error
}
else{
// has no error
}
}
}];
}//end method

How to set User Profile Image In Quickblox objective c

[QBRequest signUp: user successBlock: ^ (QBResponse * response, QBUUser * user) {
// your file - this is an image in our case
NSData * imageData = UIImageJPEGRepresentation([UIImage imageNamed: #"Profile Picture"], 0.8 f);
[QBRequest TUploadFile: imageData fileName: #"ProfilePicture"
contentType: #"image/jpeg"
isPublic: YES successBlock: ^ (QBResponse * response, QBCBlob * blob) {
// File uploaded, do something
// if blob.isPublic == YES
NSString * url = [blob publicUrl];
}
statusBlock: ^ (QBRequest * request, QBRequestStatus * status) {
// handle progress
}
errorBlock: ^ (QBResponse * response) {
NSLog(#"error: %#", response.error);
}
];
I have been trying to sing up a user, and upload an profile image but can not figure out the right way to do it. Do I have to upload it to custom data, or content module??? I already have a field created in CustomData. The code is running the file is getting saved somewhere but i don know where.
What am I missing, please help>about to go crazy>>>thank you
After you uploaded your picture (TUploadFile), in successBlock set [blob ID] to your QBUUser blobID property. After that just perform update user:
QBUpdateUserParameters *params = [QBUpdateUserParameters new];
params.blobID = [blob ID];
[QBRequest updateCurrentUser:params successBlock:^(QBResponse * _Nonnull response, QBUUser * _Nullable user) {
// success block
} errorBlock:^(QBResponse * _Nonnull response) {
// error block
NSLog(#"Failed to update user: %#", [response.error reasons]);
}];
Swift 4.2 :
This answer is for those who want to set/get user profile image from url (set url of image)
we can use customData property of QBUUser class. it will hold a String.
Set :
set customData while signUp.
let newUser = QBUUser()
newUser.login = "Saifan"
newUser.fullName = "Nadaf"
//Set your image url string here
newUser.customData = "https://homepages.cae.wisc.edu/~ece533/images/arctichare.png"
newUser.password = "Pass#1234"
QBRequest.signUp(newUser, successBlock: { [weak self] response, user in
guard let self = self else {
return
}
//SignUp Sucessfull Call Login Method Here
}, errorBlock: { [weak self] response in
response.status.rawValue == 422 {
// The User With Existent Login Was Created Earlier
// Call Login Method Here
return
}
})
if we want to set/Update for existing users we can update user profile using QBUpdateUserParameters()
let updateUserParameter = QBUpdateUserParameters()
//Set ur Image URL to customData
updateUserParameter.customData = "https://homepages.cae.wisc.edu/~ece533/images/arctichare.png"
//Use updateCurrentUser() to update user parameters
QBRequest.updateCurrentUser(updateUserParameter, successBlock: { [weak self] response, user in
guard let self = self else {
return
}
//*** This is Success Block ***//
//variable user is current updated User you can check on admin panel also
print("updated custom data \(user.customData)")
//Connect to chat using QBChat.instance.connect()
}, errorBlock: { [weak self] response in
//Handle Error Here
})
Get :
fetch users profile image using recipientID from QBChatDialog class if Dialog is created.
QBRequest.user(withID: UInt(chatDialog.recipientID), successBlock: { (res, user) in
if let imgUrl = user.customData {
// Here we will get imageUrl
print(imgUrl)
} else {
// Set Default image here
}
}) { (response) in }
fetch user profile image using customData from QBUUser class
if let imgrUrl = user.customData{ // here user is a QBUUser()
// Here we will get imageUrl
print(imgUrl)
} else {
// Set Default image here
}
Check on admin panel leftSide->user->ID->

Location Manager Crashing when No Internet

The program runs fine when the user is connected to the internet. However, when the user is not connected, the app crashes with:
Error:The operation couldn’t be completed. (kCLErrorDomain error 8.)
fatal error: unexpectedly found nil while unwrapping an Optional value
I'd like the catch the error before it crashes and display an alertcontroller
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.displayLocationInfo(pm)
currentLoc = manager.location
currentLocGeoPoint = PFGeoPoint(location:currentLoc)
var query = PFQuery(className:"Restaurant") //default: Restaurant
query.whereKey("RestaurantLoc", nearGeoPoint:currentLocGeoPoint, withinMiles:setDistanceMiles) //filter by miles
query.limit = 1000 //limit number of results
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if objects.isEmpty {
//NO RESULTS
let alertController = UIAlertController(title: "Unavailable Area", message:
"This app is not available in your area yet. We'll try our best to have it up and running as soon as possible.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
self.navigationController!.popViewControllerAnimated(true)
} else {
newArray = objects
}
self.hideActivityIndicator(self.view)
}
} else {
println("error: \(error)")
}
})
}
The problem is your if statement. You are saying this:
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 { // ...
Well, there was an error. And you were told that there was an error. But you didn't listen! You didn't stop! You just go right on as if nothing had happened, and try to access the placemarks variable - which wasn't returned. You need to use logic here so that you exit if there's an error:
if (error != nil) {
println("Error:" + error.localizedDescription)
return // go no further!
}
if placemarks.count > 0 { // ...
Note, however, that it would be better to check placemarks for nil first:
if placemarks == nil {
// check error
// return
}
if placemarks.count > 0 { // ...
I believe you need to implement locationManager:didFailWithError which tells the delegate when it is unable to retrieve the location. Then, you just need to handle the error with appropriate response.
For references: CLLocationManagerDelegate apple docs