以下是我要做的事情:
var usernameCheckerResponse : String = ""
//This IBAction is a UITextfield that sends post request when editing is finshed.
@IBAction func usernameChecker(_ sender: Any) {
// perform post request with URLSession
// post request returns url response from URLSession
// the value of this response is either 'usernameExists' or 'usernameAvailable'
// usernameCheckerResponse = String(describing : response)
}
//use modified usernameCheckerResponse variable outside the IBAction function.
//For example like this:
func UsernameExists () -> Bool {
if(usernameCheckerResponse == "usernameExists"){
return true
} else { return false }
}
我知道IBAction只会返回一个空白,所以无论如何都会出现这个问题吗? 任何帮助和/或建议将不胜感激。
答案 0 :(得分:1)
绝对是的。这是一个例子,
var usernameCheckerResponse : String = ""
//This IBAction is a UITextfield that sends post request when editing is finshed.
@IBAction func usernameChecker(_ sender: Any) {
//post request
// post request returns url response
// usernameCheckerResponse = String(describing : response)
}
//use modified usernameCheckerResponse variable outside the IBAction function.
func accessVariable() {
print("\(usernameCheckerResponse")
}
请记住,这里的技巧是在变量发生变化时访问变量。要做到这一点,你需要选择某种方式来跟踪它。委派可能是最标准的方法。 See this.您必须更具体地了解为什么要更改变量,因为我需要知道使用它的是什么(委托要求您对参与者非常具体)。
我还想更具体地说明委托的工作方式。您可以指定' accessVariable()'函数在您想要修改变量的位置调用(这将始终位于两个不同的类或结构之间)。请记住,如果您只是尝试在同一个类中共享变量,则不需要使用委派。调用函数' accessVariable()'就足够了。但是,如果你希望在同一个类中发生某些事情,但你真的想控制函数完成的顺序,那么你需要使用回调。
BTW Leo,这样做会让应用程序崩溃......答案 1 :(得分:0)
通常,您应该将IBAction函数视为 按钮等控件的连接点 你永远不会自己打电话。 如果您需要这样做,请创建另一个功能 并使用IBAction函数调用。
因为您正在使用URLSession从外部获取数据 来源,你需要知道这不会同步发生。 将调用发送到您的API并调用完成处理程序 何时返回数据。
所有这些代码都会进入您的ViewController
// Set up a reusable session with appropriate timeouts
internal static var session: URLSession {
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 6.0
sessionConfig.timeoutIntervalForResource = 18.0
return URLSession( configuration: sessionConfig )
}
// Create an httpPost function with a completion handler
// Completion handler takes :
// success: Bool true/false if things worked or did not work
// value: String string value returned or "" for failures
// error: Error? the error object if there was one else nil
func httpPost(_ apiPath: String, params: [String: String], completion:@escaping (Bool, String, Error?) -> Void) {
// Create POST request
if let requestURL = URL( string: apiPath ) {
print("requestUrl \(apiPath)")
// Create POST request
var request = URLRequest( url: requestURL )
request.httpMethod = "POST"
var postVars : [String : String ] = params
var postString = postVars.toHttpArgString()
request.httpBody = postString.data( using: String.Encoding.utf8, allowLossyConversion: true )
let sendTask = ViewController.session.dataTask( with: request) {
(data, response, error) in
if let nserror = error as NSError? {
// There was an error
// Log it or whatever
completion(false, "", error)
return
}
// Here you handle getting data into a suitable format
let resultString = "whatever you got from api call"
// Send it back to the completion block
completion(true, resultString, nil)
}
sendTask.resume()
}
}
// I assume you have a text field with the user name you want to try
@IBOutlet weak var usernameToCheck : UITextField!
@IBAction func usernameChecker(_ sender: Any) {
guard let username = usernameToCheck.text else {
// This is unlikely to happen but just in case.
return
}
httpPost("https://someapicall", params: ["username" : username] ) {
(success, value, error) in
// This code gets called when the http request returns data.
// This does not happen on the main thread.
if success {
if value == "usernameExists" {
// User name already exists. Choose a different one.
DispatchQueue.main.async {
// put code here if you need to do anything to the UI, like alerts, screen transitions etc.
}
}
else if value == "usernameAvailable" {
// You can use this user name
DispatchQueue.main.async {
// put code here if you need to do anything to the UI, like alerts, screen transitions etc.
}
}
else {
// Unexpected response from server
}
}
else {
// Something did not work
// alert "Unable to connect to server"
}
}
}
要使此代码有效,您需要:
// Syntatic sugar to convert [String:String] to http arg string
protocol ArgType {}
extension String: ArgType {}
extension Dictionary where Key: ArgType, Value: ArgType {
// Implement using a loop
func toHttpArgString() -> String {
var r = String()
for (n, v) in self {
if !r.isEmpty { r += "&" }
r += "\(n)=\(v)"
}
return r
}
}