I got a problem with OpenTok, I got a session of OTSession and I want to call the method signalWithType so I can send a chat message.
In the start I have
var session : OTSession?
And then in my method where I want to send chat message from textField I get the error 'Could not find memember 'signalWithType'
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
let message = sendMessageField.text
sendMessageField.text = ""
var type = ""
var maybeError : OTError?
session?.signalWithType(type, string: message, connection: nil, error: maybeError)
if let error = maybeError {
println(error)
} else {
println("besked blev sendt")
}
return false
}
I can't find out why it says it as I pretty sure I got the right types and that.
I have not have other problems with calling methods from session..
Related
I am attempting to implement Square Connect iOS SDK, and after implementing and clicking the pay button it opens up the Square Payment app and redirects to a blank page .. have you guys had the same issues ?
My App delegate has the proper section:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
guard let sourceApplication = options[.sourceApplication] as? String,
sourceApplication.hasPrefix("com.squareup.square") else {
return false
}
do {
let response = try SCCAPIResponse(responseURL: url)
if let error = response.error {
// Handle a failed request.
print(error.localizedDescription)
} else {
// Handle a successful request.
}
} catch let error as NSError {
// Handle unexpected errors.
print(error.localizedDescription)
}
return true
}
I have created a proper URL scheme inside the Square portal. Also my view controller has the correct code:
func charge()
{
// connect v1
if let callbackURL = URL(string: "myscheme://")
{
do
{
SCCAPIRequest.setClientID("xxxxxxxxxxx")
let amount = try SCCMoney(amountCents: 100, currencyCode: "USD")
let request = try SCCAPIRequest(
callbackURL: callbackURL,
amount: amount,
userInfoString: nil,
locationID: nil,
notes: "Purchase for cleaning",
customerID: nil, supportedTenderTypes: .all,
clearsDefaultFees: true,
returnAutomaticallyAfterPayment: true)
try SCCAPIConnection.perform(request)
}
catch let error as NSError {
print(error.localizedDescription)
}
}
}
https://snag.gy/R4A30L.jpg
Andrei
You need to make sure you delete all apps from the phone with having duplicate bundle ids. This way you will make sure you go back to the original app which triggered the payment.
I'm practicing making a URLProtocol subclass. I'm using URLSessionStreamTask to do the reading & writing. When trying out the subclass, I got a time-out. I thought I messed up my reading routine, but adding logging showed I didn't get past the initial write!
Here's a shortened version of my subclass:
import Foundation
import LoggerAPI
class GopherUrlProtocol: URLProtocol {
enum Constants {
static let schemeName = "gopher"
static let defaultPort = 70
}
var innerSession: URLSession?
var innerTask: URLSessionStreamTask?
override class func canInit(with request: URLRequest) -> Bool { /*...*/ }
override class func canonicalRequest(for request: URLRequest) -> URLRequest { /*...*/ }
override func startLoading() {
Log.entry("Starting up a download")
defer { Log.exit("Started a download") }
precondition(innerSession == nil)
precondition(innerTask == nil)
innerSession = URLSession(configuration: .ephemeral, delegate: self, delegateQueue: .current)
innerTask = innerSession?.streamTask(withHostName: (request.url?.host)!, port: request.url?.port ?? Constants.defaultPort)
innerTask!.resume()
downloadGopher()
}
override func stopLoading() {
Log.entry("Stopping a download")
defer { Log.exit("Stopped a download") }
innerTask?.cancel()
innerTask = nil
innerSession = nil
}
}
extension GopherUrlProtocol {
func downloadGopher() {
Log.entry("Doing a gopher download")
defer { Log.exit("Did a gopher download") }
guard let task = innerTask, let url = request.url, let path = URLComponents(url: url, resolvingAgainstBaseURL: false)?.path else { return }
let downloadAsText = determineTextDownload(path)
task.write(determineRetrievalKey(path).data(using: .isoLatin1)!, timeout: innerSession?.configuration.timeoutIntervalForRequest ?? 60) {
Log.entry("Responding to a write with error '\(String(describing: $0))'")
defer { Log.exit("Responded to a write") }
Log.info("Hi")
if let error = $0 {
self.client?.urlProtocol(self, didFailWithError: error)
return
}
var hasSentClientData = false
var endReadLoop = false
let aMinute: TimeInterval = 60
let bufferSize = 1024
let noData = Data()
var result = noData
while !endReadLoop {
task.readData(ofMinLength: 1, maxLength: bufferSize, timeout: self.innerSession?.configuration.timeoutIntervalForRequest ?? aMinute) { data, atEOF, error in
Log.entry("Responding to a read with data '\(String(describing: data))', at-EOF '\(atEOF)', and error '\(String(describing: error))'")
defer { Log.exit("Responded to a read") }
Log.info("Hello")
if let error = error {
self.client?.urlProtocol(self, didFailWithError: error)
endReadLoop = true
return
}
endReadLoop = atEOF
result.append(data ?? noData)
hasSentClientData = hasSentClientData || data != nil
}
}
if hasSentClientData {
self.client?.urlProtocol(self, didReceive: URLResponse(url: url, mimeType: downloadAsText ? "text/plain" : "application/octet-stream", expectedContentLength: result.count, textEncodingName: nil), cacheStoragePolicy: .notAllowed) // To-do: Update cache policy
self.client?.urlProtocol(self, didLoad: result)
}
}
}
}
extension GopherUrlProtocol: URLSessionStreamDelegate {}
And the log:
[2017-08-28T00:52:33.861-04:00] [ENTRY] [GopherUrlProtocol.swift:39 canInit(with:)] GopherUrlProtocol checks if it can 'init' gopher://gopher.floodgap.com/
[2017-08-28T00:52:33.863-04:00] [EXIT] [GopherUrlProtocol.swift:41 canInit(with:)] Returning true
[2017-08-28T00:52:33.863-04:00] [ENTRY] [GopherUrlProtocol.swift:39 canInit(with:)] GopherUrlProtocol checks if it can 'init' gopher://gopher.floodgap.com/
[2017-08-28T00:52:33.863-04:00] [EXIT] [GopherUrlProtocol.swift:41 canInit(with:)] Returning true
[2017-08-28T00:52:33.864-04:00] [ENTRY] [GopherUrlProtocol.swift:54 canonicalRequest(for:)] GopherUrlProtocol canonizes gopher://gopher.floodgap.com/
[2017-08-28T00:52:33.864-04:00] [EXIT] [GopherUrlProtocol.swift:56 canonicalRequest(for:)] Returning gopher://gopher.floodgap.com
[2017-08-28T00:52:33.867-04:00] [ENTRY] [GopherUrlProtocol.swift:82 startLoading()] Starting up a download
[2017-08-28T00:52:33.868-04:00] [ENTRY] [GopherUrlProtocol.swift:112 downloadGopher()] Doing a gopher download
[2017-08-28T00:52:33.868-04:00] [EXIT] [GopherUrlProtocol.swift:113 downloadGopher()] Did a gopher download
[2017-08-28T00:52:33.868-04:00] [EXIT] [GopherUrlProtocol.swift:83 startLoading()] Started a download
[2017-08-28T00:53:33.871-04:00] [ENTRY] [GopherUrlProtocol.swift:132 downloadGopher()] Responding to a write with error 'Optional(Error Domain=NSPOSIXErrorDomain Code=60 "Operation timed out" UserInfo={_kCFStreamErrorCodeKey=60, _kCFStreamErrorDomainKey=1})'
[2017-08-28T00:53:33.871-04:00] [INFO] [GopherUrlProtocol.swift:134 downloadGopher()] Hi
[2017-08-28T00:53:33.872-04:00] [EXIT] [GopherUrlProtocol.swift:133 downloadGopher()] Responded to a write
[2017-08-28T00:53:33.876-04:00] [ENTRY] [GopherUrlProtocol.swift:95 stopLoading()] Stopping a download
[2017-08-28T00:53:33.876-04:00] [ERROR] [main.swift:42 cget] Retrieval Error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x100e01470 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=gopher://gopher.floodgap.com, NSErrorFailingURLKey=gopher://gopher.floodgap.com, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}
[2017-08-28T00:53:33.876-04:00] [EXIT] [GopherUrlProtocol.swift:96 stopLoading()] Stopped a download
Program ended with exit code: 11
Strangely, the logging for the writing closure appears only sometimes. Maybe it's some kind of threading/timing issue. (Here, I ran the program twice.)
Am I using URLSessionStreamTask wrong? Or URLProtocol wrong? Or, although it's not HTTP, am I triggering ATS?
It looks like you're queueing up an insane number of read callbacks in a while loop and blocking the thread where the callback will actually run by never returning from the while loop.
That read call is asynchronous, which means that the callback inside will run later—probably much later. Thus, your "while not EOF" thing will block the calling thread, ensuring that it never returns to the top of the run loop to allow the callback to run, thus ensuring that the callback will never be able to set the eof flag to terminate the while loop. Essentially, you deadlocked the thread.
You should almost never call asynchronous methods in any sort of loop. Instead:
create a method whose sole purpose is to return that block/closure (perhaps getReadHandlerBlock).
Call the read method, passing the block returned from a call to getReadHandlerBlock.
Then, the bottom of the read handler block:
Check to see if you need to read more.
If so, call getReadHandlerBlock on a weak reference to self to obtain a reference to a read handler block.
Call the read method.
Hope that helps. (Note that I'm not saying that this is the only problem with the code; I haven't looked at it in too much detail. It was just the first thing that I noticed.)
I was about to ask this query on a different forum. In my steps, I mentioned that I send out the request line...
Line? With... endings?
[Look up RFC 1436, Section 2]
Oh, I calculate and send the retrieval string from the URL, but I forgot to cap off the request with a CR-LF. That gets the request through.
But now I'm getting a time-out on the read-back....
Trying to poll the content of a website, no matter if JSON or REST API, I cannot seem to make it work. The same code works for iOS App, but will not get the content when being used within a Swift macOS Terminal application. What's the main reason?
The project does not have an Info.plist file.
Here's a code example that works within an iOS application, but not within the macOS Terminal application. I call the function with a simple jsonParser(), which initiates the NSURLSession and prints the JSON when it's arrived.
enum JSONError: String, ErrorType {
case NoData = "ERROR: no data"
case ConversionFailed = "ERROR: conversion from JSON failed"
}
func jsonParser() {
let urlPath = "https://api.coindesk.com/v1/bpi/currentprice.json"
guard let endpoint = NSURL(string: urlPath) else {
print("Error creating endpoint")
return
}
let request = NSMutableURLRequest(URL:endpoint)
NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
do {
guard let data = data else {
throw JSONError.NoData
}
guard let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary else {
throw JSONError.ConversionFailed
}
print(json)
} catch let error as JSONError {
print(error.rawValue)
} catch let error as NSError {
print(error.debugDescription)
}
}.resume()
}
I was able to solve my problem by adding
dispatch_main()
at the end of my main program code. Listed above was the function to request the web data. Thanks to Martin and Eric for pointing it out.
I want to convert the friend list ids that I am getting from facebook as an array to save in parse. My code is as below but I am getting a "unexpectedly found nil while unwrapping an Optional value" error. What should I do to save the result to parse and retrieve it as array when required?
let fbRequest = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil);
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
print("Friends are : \(result)")
if let dict = result as? Dictionary<String, AnyObject>{
let profileName:NSArray = dict["name"] as AnyObject? as! NSArray
let facebookID:NSArray = dict["id"] as AnyObject? as! NSArray
print(profileName)
print(facebookID)
}
}
else {
print("Error Getting Friends \(error)");
}
}
When I use the code below in print() I get the result below:
Friends are : {
data = (
{
id = 138495819828848;
name = "Michael";
},
{
id = 1105101471218892;
name = "Johnny";
}
);
The issue is that you are trying to access the name and id elements from the top-level dictionary, where you need to be accessing data.
When you call the FB Graph API for friends it will return an array of dictionaries (one per friend).
Try this:
let fbRequest = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil)
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
print("Friends are : \(result)")
if let friendObjects = result["data"] as? [NSDictionary] {
for friendObject in friendObjects {
println(friendObject["id"] as NSString)
println(friendObject["name"] as NSString)
}
}
} else {
print("Error Getting Friends \(error)");
}
}
You should also check out this SO post with more information on the FB Graph API. Here's a brief snippet.
In v2.0 of the Graph API, calling /me/friends returns the person's
friends who also use the app.
In addition, in v2.0, you must request the user_friends permission
from each user. user_friends is no longer included by default in every
login. Each user must grant the user_friends permission in order to
appear in the response to /me/friends. See the Facebook upgrade guide
for more detailed information, or review the summary below.
I'm trying to make a messaging app in Parse, but I get this error when trying to upload a PFObject.
The error says:
2014-11-22 14:43:21.154 Parse demo[688:27950] Warning: A long-running operation is being executed on the main thread.
Break on warnBlockingOperationOnMainThread() to debug.
and my code is for the sender-button is:
#IBAction func sendButton(sender: AnyObject) {
var message = PFObject(className:"message")
message["message"] = send.text
message.save()
where send.text is just a text-box.
Any recommendations or ways to proceed would be highly appreciated.
Try this instead. then you save in a background blok
#IBAction func sendButton(sender: AnyObject) {
var message = PFObject(className:"message")
message["message"] = send.text
message.saveInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if (error != nil) {
println("Save : \(error)")
}
else{
println("Success! with save")
}
}
}
This is not exactly an error, but more a hint, that it'll block the app because you are making a synchronous save call. Use one of the saveInBackground* methods instead and the save will take place asynchronously on a background job.