Working using swift and logInWithPublishPermissions - swift2

I have this code:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], handler: { (result: FBSDKLoginManagerLoginResult!, error: NSError!) -> Void in
if error != nil {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})
This code worked ok, but I have this warning message:
'logInWithPublishPermissions(_:handler:)' is deprecated: use logInWithPublishPermissions:fromViewController:handler: instead
I tried to fix this warning but I could not. Someone knows how to fix it?

According to the FBSDK API:
The way you're using the method is deprecated. It wants you to use the new way it indicated in its documentation, as seen below:
- (void)
logInWithPublishPermissions: (NSArray *)permissions
handler: (FBSDKLoginManagerRequestTokenHandler)handler
__attribute__((deprecated("use logInWithPublishPermissions: fromViewController:handler: instead")));
Therefore you would use it like so:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], fromViewController: self, handler: { (response: FBSDKLoginManagerLoginResult!, error: NSError!) in
if (error != nil) {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})

You need to call the function like this:
let login: FBSDKLoginManager = FBSDKLoginManager()
login.logInWithPublishPermissions(["publish_actions"], fromViewController: self, handler: { (result: FBSDKLoginManagerLoginResult!, error: NSError!) -> Void in
if error != nil {
NSLog(error.localizedFailureReason!)
} else if result.isCancelled {
NSLog("Canceled")
} else if result.grantedPermissions.contains("publish_actions") {
self.loginFacebookButtin.hidden = true
}
})

Related

RXSwift why loading variable return wrong value?

Here is my view model:
let loadMoreTrigger = PublishSubject<Void>()
let refreshTrigger = PublishSubject<Void>()
let loading = BehaviorRelay<Bool>(value: false)
let stories = BehaviorRelay<[Story]>(value: [])
var offset = 0
let error = PublishSubject<String>()
let selectedFeedType: BehaviorRelay<FeedType> = BehaviorRelay(value: .best)
override init() {
super.init()
let refreshRequest = loading.asObservable().sample(refreshTrigger).flatMap { loading -> Observable<[Story]> in
if loading {
return Observable.empty()
} else {
self.offset = 0
return self.fetchStories(type: self.selectedFeedType.value, offset: self.offset)
}
}
let loadMoreRequest = loading.asObservable().sample(loadMoreTrigger).flatMap { loading -> Observable<[Story]> in
if loading {
return Observable.empty()
} else {
self.offset += 10
return self.fetchStories(type: self.selectedFeedType.value, offset: self.offset)
}
}
let request = Observable.merge(refreshRequest, loadMoreRequest).share(replay: 1)
let response = request.flatMap { (stories) -> Observable<[Story]> in
request.do(onError: { error in
self.error.onNext(error.localizedDescription)
}).catchError { (error) -> Observable<[Story]> in
Observable.empty()
}
}.share(replay: 1)
Observable.combineLatest(request, response, stories.asObservable()) { request, response, stories in
return self.offset == 0 ? response : stories + response
}.sample(response).bind(to: stories).disposed(by: disposeBag)
Observable.merge(request.map{_ in true}, response.map{_ in false}, error.map{_ in false}).bind(to: loading).disposed(by: disposeBag)
}
Then when i checking loading observer i have false -> true, instead of true -> false. I just don't understand why it happening.
loading.subscribe {
print($0)
}.disposed(by: disposeBag)
In my viewController i call refreshTrigger on viewWillAppear using rx.sentMessage
Here is getFeed function:
func getFeed(type: FeedType, offset: Int) -> Observable<[Story]> {
return provider.rx.request(.getFeed(type: type, offset: offset)).asObservable().flatMap { (response) -> Observable<[Story]> in
do {
let feedResponse = try self.jsonDecoder.decode(BaseAPIResponse<[Story]>.self, from: response.data)
guard let stories = feedResponse.data else { return .error(APIError.requestFailed)}
return .just(stories)
} catch {
return .error(error)
}
}.catchError { (error) -> Observable<[Story]> in
return .error(error)
}
}
Your request and response observables are emitting values at the exact same time. Which one shows up in your subscribe first is undefined.
Specifically, request doesn't emit a value until after the fetch request completes. Try this instead:
Observable.merge(
loadMoreTrigger.map { true },
refreshTrigger.map { true },
response.map { _ in false },
error.map { _ in false }
)
.bind(to: loading)
.disposed(by: disposeBag)
There are lots of other problems in your code but the above answers this specific question.

Swift Alamofire + Promise catching

Folks, The following works except for the catch, xcode errors out with expected member name following '.'
Is this the proper way to promisify with PromiseKit?
All suggestions welcome! Thanks!
#IBAction func loginButtonTapped(sender: AnyObject) {
let email = userEmail.text!
let password = userPassword.text!
func onSuccess(success:Bool, message:String, token: String) -> Promise<Void> {
if success {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLoggedIn")
NSUserDefaults.standardUserDefaults().synchronize()
self.dismissViewControllerAnimated(true, completion: nil)
} else {
let myAlert = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Try Again", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
}
return Promise { resolve, reject in
return resolve()
}
}
func onFailure(error:NSError) -> Promise<Void> {
return Promise { resolve, reject in
return reject(error)
}
}
Login(email, password: password).then(onSuccess).catch(onFailure)
}
private func Login(email: String, password: String) -> Promise<(success:Bool, message:String, token: String)> {
let parameters: [String: String] = [
"username" : email,
"password" : password
];
let endpoint = "https://api.foo.bar/login"
return Promise { resolve, reject in
Alamofire.request(.POST, endpoint, parameters: parameters, encoding: .JSON)
.validate()
.responseJSON { (response) in
guard response.result.error == nil else {
logger.debug(response)
let result:(success:Bool, message:String, token: String) = (false, "Login Failed", "")
return resolve(result)
}
if let value = response.result.value {
let apiResponseJSONBody = JSON(value)
let result:(success:Bool, message:String, token: String) = (true, "", token: apiResponseJSONBody["token"].string!)
return resolve(result)
}
}
}
}

cannot convert type to expected argument type

let eventStore = EKEventStore()
// 2
switch EKEventStore.authorizationStatusForEntityType(EKEntityType.Event) {
case .Authorized:
insertEvent(eventStore)
case .Denied:
print("Access denied")
case .NotDetermined:
// 3
eventStore.requestAccessToEntityType(EKEntityType.Event, completion:
{[weak self] (granted: Bool, error: NSError!) -> Void in
if granted {
self!.insertEvent(eventStore)
}
else
{
print("Access denied")
}
})
default:
print("Case Default")
}
I am getting error: cannot convert value of type '(bool,nserror!) -->void' to expected argument type 'ekeventstorerequestaccescompletionhandler'
at this line:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion:
{[weak self] (granted: Bool, error: NSError!) -> Void in
Try to remove [weak self], in my case this one works:
eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
(accessGranted: Bool, error: NSError?) in
if accessGranted && (error == nil) {
dispatch_async(dispatch_get_main_queue(), { completion(true) })
} else {
dispatch_async(dispatch_get_main_queue(), { completion(false) })
}
})

Alamofire custom reponse migration from Alamofire v1.3 to 3.0 (and Swift 2 syntax)

I am converting an project from Swift 1.1 to Swift 2.0 that used Alamofire 1.3.
Because this version of Alamofire was not compatible with Swift 2.0, I switched to the very last version of Alamofire (3.1.x).
However this broke the code, I am now getting the error message
"Cannot call value of non-function type 'NSHTTPURLResponse?'"
which is due to my my extension to create a custom "responseShop" Alamofire.Request.
How can this Alamofire.Request extension correctly be converted to the Alamofire 3.x/Swift 2.0 syntax?
extension Alamofire.Request {
func responseShop(options: NSJSONReadingOptions = .AllowFragments, var errorHandler:ProtocolWebServiceErrorHandler?, completionHandler: (ShopCallResult?, WebServiceErrorCode) -> Void ) -> Self {
objc_sync_enter(communicationLockObj)
return response(serializer: Request.JSONResponseSerializer(options: options), completionHandler: {
(request, response, JSON, error) in
log.verbose("\(JSON)")
//network error?
if let error = error {
//is it cancelled?
if error.code == -999 {
dispatch_async(dispatch_get_main_queue()) {
//call handler with cancelled code
completionHandler(nil, WebServiceErrorCode.requestCancelled)
}
objc_sync_exit(communicationLockObj)
return
}
dispatch_async(dispatch_get_main_queue()) {
errorHandler?.handleWebServiceError(WebServiceErrorCode.connectError, errorText : error.localizedDescription, request: request, json: JSON)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.connectError)
}
objc_sync_exit(communicationLockObj)
return
}
if JSON == nil {
dispatch_async(dispatch_get_main_queue()) {
errorHandler?.handleWebServiceError(WebServiceErrorCode.jsonNil, errorText: nil, request: request, json: JSON)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.jsonNil)
}
objc_sync_exit(communicationLockObj)
return
}
//api return error?
let callResult = ShopCallResult(json: JSON!)
if callResult.statusCode.failed {
dispatch_async(dispatch_get_main_queue()) {
errorHandler?.handleWebServiceError(callResult.statusCode, errorText: callResult.statusCode.localizedText, request: request, json: JSON)
completionHandler(callResult, callResult.statusCode)
}
objc_sync_exit(communicationLockObj)
return
}
//no error
dispatch_async(dispatch_get_main_queue()) {
completionHandler(callResult, WebServiceErrorCode.OK)
}
objc_sync_exit(communicationLockObj)
})
return self
}
}
Based on the feedback of #ProblemSolver I managed to convert the code, now it looks like this:
extension Alamofire.Request {
func responseShop(queue: dispatch_queue_t? = nil, options: NSJSONReadingOptions = .AllowFragments, errorHandler:ProtocolWebServiceErrorHandler?, completionHandler: (ShopCallResult?, WebServiceErrorCode) -> Void ) -> Self {
//enter thread protected area...
objc_sync_enter(communicationLockObj)
return responseJSON() {
response in
switch response.result {
case .Success(let JSON):
//log json in verbose mode
log.verbose("\(JSON)")
//parse the returned json
let callResult = ShopCallResult(json: JSON)
//is it failed?
if callResult.statusCode.failed {
//call supplied error handler on the main thread
dispatch_async(dispatch_get_main_queue()) {
errorHandler?.handleWebServiceError(callResult.statusCode, errorText: callResult.statusCode.localizedText, request: self.request!, json: JSON)
completionHandler(callResult, callResult.statusCode)
}
//release the lock
objc_sync_exit(communicationLockObj)
//processing done!
return
}
//no error call handler on main thread
dispatch_async(dispatch_get_main_queue()) {
completionHandler(callResult, WebServiceErrorCode.OK)
}
//release the lock
objc_sync_exit(communicationLockObj)
case .Failure(let error):
//WARNING: cancelled is still error code 999?
//is it cancelled?
if error.code == -999 {
//just call the completion handler
dispatch_async(dispatch_get_main_queue()) {
//call handler with cancelled code
completionHandler(nil, WebServiceErrorCode.requestCancelled)
}
//release the lock
objc_sync_exit(communicationLockObj)
//stop furhter processing
return
}
//error with the json?
if error.code == Alamofire.Error.Code.JSONSerializationFailed .rawValue {
//call the error handler
dispatch_async(dispatch_get_main_queue()) {
errorHandler?.handleWebServiceError(WebServiceErrorCode.jsonNil, errorText: nil, request: self.request!, json: nil)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.jsonNil)
}
//release the lock
objc_sync_exit(communicationLockObj)
//stop further processing
return
}
//must be some other kind of network error
dispatch_async(dispatch_get_main_queue()) {
log.error("\(error)")
//so call the error handler
errorHandler?.handleWebServiceError(WebServiceErrorCode.connectError, errorText : error.localizedDescription, request: self.request!, json: nil)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.connectError)
}
//release the lock
objc_sync_exit(communicationLockObj)
}
}
}
}

NSURL error for broken links in Swift

I coded a function for OSX 10.10 that is willing to open a text file from an URL and display its content.
Everything is working but if the URL cannot be reach then the App will crash. How could I handle this type of Error?
I guess it comes from the completionHandler closure but I am not sure.
here is my code
#IBAction func checkAdminMessage(sender: NSMenuItem) {
let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt")
// The Network stuff will be handled in a background thread
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL!,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil)
// Check if text.txt has NULL as content
if urlContents! == "NULL" {
// Have to use Grand Central Dispatch to put NSAlert in the main thread
let noMessage = NSLocalizedString("Nothing there", comment: "Text to dislay when the file is empty" )
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: noMessage)
}
} else {
// If the file is not empty then we display the content of this file
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: urlContents!)
}
}
})
downloadTask.resume()
}
Thank you
EDIT: Here is the updated code but the App still crashed
#IBAction func checkAdminMessage(sender: NSMenuItem) {
if let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt") {
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil )
if urlContents == "NULL" {
println(urlContents)
// Have to use Grand Central Dispatch to put NSAlert in the main thread
let noMessage = NSLocalizedString("Nothing there", comment: "Text to dislay when the file is empty" )
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: noMessage)
}
}
else {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.displayAlertNotification(notification: urlContents!)
}
}
})
downloadTask.resume()
}
else {
println("Error")
}
}
NSURL(string: ...) returns an optional, so the result may be nil due to several reasons.
Wrap your code in a conditional unwrap:
if let messageURL = NSURL(string: "http://www.xxxxxx.com/text.txt") {
// success
...
}
else {
// error
}
I figured it out with the helps of the people that commented my question.
I was getting a nil from 'location' in downloadTaskWithUrl, then the var urlContents was receiving a nil as well.
The solution is to check if 'location' is nil :
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(messageURL,
completionHandler: {
(location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
**if (location != nil) {**
var urlContents = NSString(contentsOfURL: location, encoding: NSUTF8StringEncoding, error: nil ) ...

Resources