Fatal error: Session manager did not return a task: file - vimeo-ios

I am currently playing around with the Vimeo API and following the setup process and the guided readme found here:
(https://github.com/vimeo/VimeoNetworking)
All I am doing is pulling down publicly available videos from Vimeo except I have been receiving
Fatal error: Session manager did not return a task: file
everything else works and I am able to use my own token for authentication.
Here is the code I have right now that throws this error:
What am I doing wrong or missing?
let queryURL = URL(string: "/channels/staffpicks/videos")
let videoRequest = Request<[VIMVideo]>(path: queryURL!.absoluteString)
guard let sessionClient = _client else {
return []
}
let _ = sessionClient.request(videoRequest, completion: {
results in
switch results {
case .success(let response):
let videos: [VIMVideo] = response.model
for video in videos
{
print("retrieved video: \(video)")
}
vVideo = videos
break
case .failure(let error):
print(error.localizedDescription)
break
}
})

Sorry I am late but this worked for me (using Swift 4.2):
let appConfiguration = AppConfiguration(
clientIdentifier: Constants.VIMEO_CLIENT_IDENTIFIER,
clientSecret: Constants.VIMEO_CLIENT_SECRET,
scopes: [.Public], keychainService: "")
let vimeoSessionManager = VimeoSessionManager.defaultSessionManager(
baseUrl: VimeoBaseURL,
accessToken: Constants.VIMEO_ACCESS_TOKEN,
apiVersion: "3.4")
let vimeoClient = VimeoClient(
appConfiguration: appConfiguration,
sessionManager: vimeoSessionManager)
let videoRequest = Request<[VIMVideo]>(path: "/videos?query=dragon+ball")
vimeoClient.request(videoRequest) {
result in
switch result {
case .success(let response):
let videos: [VIMVideo] = response.model
print("\n\n retrieved videos: \(videos) \n\n")
case .failure(let error):
print("\n\n error retrieving videos: \(error) \n\n")
}
}
I'am almost sure you needed to add a session manager, but not 100% because haven't seen how you initialize the client and the other variables, so I am just adding this example.
Remember to get clientIndentifier, clientSecret and accessToken in [https://developer.vimeo.com/apps][1] (after you've created your app).
This is using a public accessToken, if you need authenticated access just add the .Private and .Interact scopes to the scopes array in appConfiguration, and to get an 'Authenticated' accessToken.
Also, please notice that I am using "/videos?query=dragon+ball" as an example.

Related

One request - Two responses. Which end is creating the problem (Front / Back)

Problem:
When I call a request from iOS swift based app, then the server is responding two responses.
Inputs:
In my request, am sending some user values including one base64 image string. I already ensure that my app is calling request only one time.
Outputs:
When we opened the server log, it printed two set of request and response. But, difference that the first one is not having base64 image string and second one is having it. Thats why am receiving two different responses.
Questions:
What end is causing this problem - Front / back end?
Note:
I given front code below but I can’t provide back end code.
let task = urlSession.dataTask(with: urlRequest, completionHandler: {
(data, response, error) in
if error != nil
{
print("Error ==",error!.localizedDescription);
onFailure(error!.localizedDescription)
}
else
{
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
// For some critical cases:
//print("Status code: ", statusCode)
//print("http Response: ", httpResponse)
// JSON serialize
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print("Server Response == ",jsonResponse)
onSuccess(statusCode, jsonResponse)
}
catch
{
onFailure("JSON Parser Error")
}
}
})`

swift 3 urlRequest session.dataTask not firing

I am trying to get stock quotes from Yahoo using Swift 3. Although there are some decent tutorials on Swift 2, none of them seem to translate well to Swift 3.
The issue I have at the moment is that in the code below, the session.dataTask is never called. The print statement never fires and the rest of the code that is in there does not work.
I have checked that the request variable looks good, and the url has been tested on the yahoo developer site.
So I'm thinking I must have the syntax of the dataTask wrong or has an error so is skipping completely.
Any thoughts?
urlString = "http://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.quotes where symbol IN ('APL')"
//let urlNSS : NSString = urlString as NSString
let urlStr : String = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url : URL = URL(string: urlStr as String)!
let request = URLRequest(url: url)
let session = URLSession.shared
let config = URLSessionConfiguration.default
let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
print("in the task")
..
..
)}
task.resume()
If I inspect task I see the following
You must resume the task (task.resume()) that you have created. By default, a task is in suspended state.
I have created a Playground file with a different Yahoo RSS Feed URL. https://drive.google.com/file/d/0B5nqEBSJjCriWl9UTWcxSE42Yk0/view?usp=sharing
The URL you have in your question is not giving any data.
<error xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:lang="en-US">
<description>No definition found for Table yahoo.finance.quotes</description>
</error>
Code as Below:
//: Playground - noun: a place where people can play
import UIKit
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
var str = "Hello, playground"
let yahooURLString = "https://feeds.finance.yahoo.com/rss/2.0/headline?s=yhoo&region=US&lang=en-US"
let yahooRSSURL: URL = URL(string: yahooURLString)!
var request = URLRequest(url: yahooRSSURL)
request.httpMethod = "GET"
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let task = session.dataTask(with: request) {data, response, err in
print("Entered the completionHandler")
print("Response JSON:\n\(String(data: data!, encoding: String.Encoding.utf8)!)")
}
task.resume()
Hope this helps.
Edit: Attaching a screenshot of print statements appearing in the console of playgorund.

AWS Cognito integration swift3 Refresh provides ResourceNotFoundException

Following the answer here:
https://github.com/aws/aws-sdk-ios/issues/357
At the very bottom there is a mini guide on getting swift and cognito working.
I've made a AWSCustomIdentityProvider as such:
import Foundation
import AWSCognitoIdentityProvider
import AWSCognito
class AWSCustomIdentityProvider: NSObject, AWSIdentityProviderManager
{
private var dict = NSDictionary()
func addToken(value:NSString)
{
dict = ["graph.facebook.com":value]
}
public func logins() -> AWSTask<NSDictionary>
{
return AWSTask(result: dict)
}
}
And I have a login method from facebook:
public func loginButtonDidCompleteLogin(_ loginButton: FacebookLogin.LoginButton, result: FacebookLogin.LoginResult){
switch result {
case .failed(let error):
print("FACEBOOK LOGIN FAILED: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
let customIdentity = AWSCustomIdentityProvider()
let token = accessToken.authenticationToken
customIdentity.addToken(value: token as NSString)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: REGIONTYPE, identityPoolId: "XXXXXXXXXXXXXXXXXXXXXXX", identityProviderManager:customIdentity)
credentialsProvider.clearKeychain()
credentialsProvider.clearCredentials()
let serviceConfiguration = AWSServiceConfiguration(region: REDIONTYPE, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration;
credentialsProvider.getIdentityId().continue( { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("Error: " + (task.error?.localizedDescription)!)// gets called
}
else {
print(task.result)//identityid
}
return nil
})
}
}
However I get the error:
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={__type=NotAuthorizedException, message=Logins don't match. Please include at least one valid login for this identity or identity pool.}
Please let me know if you have any idea on how to resolve my issue. I've tried also following the docs and setting the logins directly "credentialsProvider.logins = {"graph.facebook.com": mytoken}
and that produces a different exception upon invoking a lambda method but DOES retrieve the identityID properly. However doing it according to the docs makes a warning that the method I'm using is deprecated.
The error I get:
UserInfo={NSLocalizedDescription=serialized object is neither a valid json Object nor NSData object: }
However that only happens sometimes. If I retry then i can potentially get the identity id but upon invoking a lambda method, I get the same error. I'm assuming it is a cognito issue.
UPDATE
If I use AWSCognitoLoginProviderKey.facebook.rawValue instead of graph.facebook.com in the first part, then it gives me the cognito ID and then I invoke the lambda method. I'll include the lambda method just incase that's the part I'm getting wrong but I'm decently sure that it's cognito that is preventing me from calling the lambda method:
import AWSLambda
import Foundation
struct AWSHelper{
let lambda = AWSLambda.default()
let APPLICATION_NAME = "MYAPPLICATION"
init(){
}
func getFunctionName(funcName: String) -> String{
return "\(funcName)_\(APPLICATION_NAME)"
}
func login(facebookID: String, cognitoID:String, callback:#escaping (Bool) -> Void){
let req = AWSLambdaInvocationRequest();
req?.invocationType = AWSLambdaInvocationType.requestResponse
req?.payload = ["cognitoID" : cognitoID, "facebookID" : facebookID]
req?.functionName = getFunctionName(funcName: "MYFUNCNAME")
lambda.invoke(req!) { (response: AWSLambdaInvocationResponse?,error: Error?) in
print(error)
let payload = response?.payload
print(payload)
callback(true)
}
}
}
Update 2
I have found out that calling a refresh method like this:
credentialsProvider.credentials().continue({ (task: AWSTask!) -> Any? in
print(task.result)
})
Causes an error like this:
AWSiOSSDK v2.4.10 [Error] AWSCredentialsProvider.m line:577 | __44-[AWSCognitoCredentialsProvider credentials]_block_invoke.352 | Unable to refresh. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=Identity 'us-east-1:0db18266-1baa-4c59-9110-f9041dc92ead' not found.}]
I believe the big string that looks like an identitypoolID is actually the identityID for the given user that I have, so cognito has distributed an ID but is not able to query it?
the error:
Logins don't match. Please include at least one valid login for this identity or identity pool
Can also occur because you attempt to log in as another user without logging out, so the token in the logins dictionary is compared to the identityId for a different identity (and doesn't match). In this case the SDK usually recovers by retrying, clearing and reestablishing the identityId, and then it works.
But in your case since you are constructing your own logins dictionary, the issue is more likely that you have constructed a token that does not match. You can inspect tokens using https://jwt.io. (though I admit it works for google and cognito user pools, but not on facebook tokens (I don't know why this is)),
I think doesn't match means that the identityId records a different unique user than is specified in the token.
Are you sure the token is constructed correctly?
As you mentioned... the documentation.. well .. I find the documentation is not worth looking at, So I set up my projects so I can review working code and set breakpoints.
Here is a snippet of the code from Mobile Hub Helper's Facebook AWSSignInProvider, which shows what they use to get the token (token.tokenstring).
- (AWSTask<NSString *> *)token {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
NSDate *idTokenExpirationDate = token.expirationDate;
if (tokenString
// If the cached token expires within 10 min, tries refreshing a token.
&& [idTokenExpirationDate compare:[NSDate dateWithTimeIntervalSinceNow:AWSFacebookSignInProviderTokenRefreshBuffer]] == NSOrderedDescending) {
return [AWSTask taskWithResult:tokenString];
}
AWSTaskCompletionSource *taskCompletionSource = [AWSTaskCompletionSource taskCompletionSource];
[FBSDKLoginManager renewSystemCredentials:^(ACAccountCredentialRenewResult result, NSError *error) {
if (result == ACAccountCredentialRenewResultRenewed) {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
taskCompletionSource.result = tokenString;
} else {
taskCompletionSource.error = error;
}
}];
return taskCompletionSource.task;
}
Also... It bears mentioning. The AWSIdentityManager, and it's associated AWSSignInProviders is a nice architecture for getting signed in with Facebook and Google. Even if you don't use the rest of Mobile Hub Helper. Why re-invent the wheel, they did a very good job on the Identity portion of aws-mobilehub-helper-ios
I have a version of that library posted on github that adds an AWSSignInProvider for Cognito User Pools as well. SignIn-awsmhh it requires some fixes in the aws-mobilehub-helper-ios to use cognito user pools they are here aws-mobilehub-helper-ios (so if you clone do a clone --recursive and you will be set up for debugging using breakpoints in the library).
Few things that made it work I think.
I made the correct move by making my own identityprovidermanager and I think the main thing that was blocking me from executing a lambda method was actually the fact that I was using AWSLambda instead of AWSLambdaInvoker. After I switched it started making errors that made sense.

How to make synchronous url requests with swift 3

I know the question has been asked before and I agree with most answers that claim it is better to follow the way requests are made async with URLSession in Swift 3. I haver the following scenario, where async request cannot be used.
With Swift 3 and the ability to run swift on servers I have the following problem.
Server Receives a request from a client
To process the request the server has to send a url request and wait for the response to arrive.
Once response arrives, process it and reply to the client
The problem arrises in step 2, where URLSession gives us the ability to initiate an async data task only. Most (if not all) server side swift web frameworks do not support async responses. When a request arrives to the server everything has to be done in a synchronous matter and at the end send the response.
The only solution I have found so far is using DispatchSemaphore (see example at the end) and I am not sure whether that will work in a scaled environment.
Any help or thoughts would be appreciated.
extension URLSession {
func synchronousDataTaskWithURL(_ url: URL) -> (Data?, URLResponse?, Error?) {
var data: Data?
var response: URLResponse?
var error: Error?
let sem = DispatchSemaphore(value: 0)
let task = self.dataTask(with: url as URL, completionHandler: {
data = $0
response = $1
error = $2 as Error?
sem.signal()
})
task.resume()
let result = sem.wait(timeout: DispatchTime.distantFuture)
switch result {
case .success:
return (data, response, error)
case .timedOut:
let error = URLSessionError(kind: URLSessionError.ErrorKind.timeout)
return (data, response, error)
}
}
}
I only have experience with kitura web framework and this is where i faced the problem. I suppose that similar problems exist in all other swift web frameworks.
In Vapor, you can use the Droplet's client to make synchronous requests.
let res = try drop.client.get("https://httpbin.org")
print(res)
Additionally, you can use the Portal class to make asynchronous tasks synchronous.
let res = try Portal.open { portal in
asyncClient.get("https://httpbin.org") { res in
portal.close(with: res)
}
}
Your three-step problem can be solved via the use of a completion handler, i.e., a callback handler a la Node.js convention:
import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
let session = URLSession(configuration: URLSessionConfiguration.default)
Log.logger = HeliumLogger()
let router = Router()
router.get("/test") { req, res, next in
let datatask = session.dataTask(with: URL(string: "http://www.example.com")!) { data, urlResponse, error in
try! res.send(data: data!).end()
}
datatask.resume()
}
Kitura.addHTTPServer(onPort: 3000, with: router)
Kitura.run()
This is a quick demo of a solution to your problem, and it is by no means following best Swift/Kitura practices. But, with the use of a completion handler, I am able to have my Kitura app make an HTTP call to fetch the resource at http://www.example.com, wait for the response, and then send the result back to my app's client.
Link to the relevant API: https://developer.apple.com/reference/foundation/urlsession/1410330-datatask

Get facebook user's uploaded photos in swift/xcode 6

I've been able to login and get the first name, last name, email, and profile picture url in Xcode 6.1.1 with swift. I haven't been able to figure out how to get the urls or pull the images from a user, even though I have the user_photos Permission. Any help would be greatly appreciated.
You need to make request to graph api that will return you JSON in response to your request. For example if you want to get name, profile picture (it will give you url for profile picture) and id you can make request in your viewDidLoad() as follows
FBRequestConnection.startWithGraphPath("me?fields=id,name,picture", completionHandler: {(connection: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if (result? != nil) {
NSLog("error = \(error)")
println(result)
}
} as FBRequestHandler)
to set a label text to facebook name you can use
var resultdict = result as? NSDictionary
if let name = resultdict?["name"] as? String {
self.YOUR_LABEL.text = name //name is response object in "result" dictionary
}
Cheers!!!