Swift HTTP Post Request dataUsingEncoding使字符串变形

时间:2016-02-04 15:09:40

标签: php ios json swift

所以首先:嘿伙计们。我目前正在与提出这个问题的家伙一起开发一个应用程序:Post request always wrapped by optional text 他正在编写iOS部分,我正在编写Android部分,我完全不知道整个Swift的东西是什么让iOS中的编码变得有点困难,因为他几乎没有编程经验。

现在问题: 我们正在向我编写的php脚本发送POST请求,该脚本获取发布的用户名和密码,并再次向应用程序发送json响应。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Windows.Forms;

namespace WebApplication7
{
public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void calculateButton_Click(object sender, EventArgs e)
    {
            double test1;
            double test2;
            double test3;
            double average;

            test1 = double.Parse(t1TextBox.Value);
            test2 = double.Parse(t2TextBox.Value);
            test3 = double.Parse(t3TextBox.Value);

            average = (test1 + test2 + test3) / 3.0;

            avgOutputLabel.InnerText = average.ToString("N2");

    }


}
}

例如,如果用户名或密码为空,我们应该收到此回复:

$username = $_POST['username'];
$password = $_POST['password'];
if (!empty($username) && !empty($password)) {
    $encrypted_password = md5($password);
    $user -> login($username,$encrypted_password);
} else {
    $json['error'] = 'You must fill all fields!';
    echo json_encode($json);
    mysqli_close($this->connection);
}

对于Android,这非常有效,我们可以使用响应。

但是在iOS中我们对String进行编码时,它将我们发送到php脚本的整个字符串转换为:

{"error":"You must fill all fields!"}

因为php脚本需要这样的数据:

Optional(<75736572 6e616d65 3d612670 61737377 6f72643d 61>)

它当然不起作用。

那么我们如何才能将这个糟糕的十六进制代码转换为我们想要的内容,或者我们如何才能防止这种错误。

提前致谢:D

修改

夫特码:

username=xyz&password=xyz

错误-消息:

let username = UsernameTextField.text ?? ""
        let password = PasswordTextField.text ?? ""

        if(username.isEmpty || password.isEmpty) {return; }



        let request = NSMutableURLRequest (URL: NSURL(string: "http://myip/loginregister.php")!)
        request.HTTPMethod = "POST"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
        let postString = "username=\(username)&password=\(password)"
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
            guard error == nil && data != nil else {
                // check for fundamental networking error
                print("error=\(error)")
                return
            }

            let data = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!


            do {
                if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
                    let success = json["success"] as? Int                                 
                    print("Success: \(success)")
                } else {
                    let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)   
                    print("Error could not parse JSON: \(jsonStr)")
                }
            } catch let parseError {
                print(parseError)                                                      `JSONObjectWithData`
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                print("Error could not parse JSON: '\(jsonStr)'")
            }
        }

        task.resume()

4 个答案:

答案 0 :(得分:0)

a)你丢弃了服务器的答案......

b)熟悉调试器并检查postString的内容;它永远不会是有效的JSON,因此您无法期望转换成功。

c)不要混合发送和接收部分,但要解决一个接一个的问题。

d)当您将结果作为评论在线发布时,回答起来要容易得多。

答案 1 :(得分:0)

用这一行:

let data = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

您正在使用发布请求的参数覆盖在完成处理程序中返回的数据变量。只需删除此行即可。然后你还必须在下面几行打开数据参数,只需插入'!'数据之后。 (更好的代码风格是在闭包开始时使用可选绑定,但'!'只是让它工作;)

答案 2 :(得分:0)

您的参数编码不正确。

为了设置包含POST请求参数的内容类型application/x-www-form-urlencoded,您应该使用帮助程序类NSURLComponents

首先,创建一个NSURLQueryItems数组,例如:

        var queryItems = [NSURLQueryItem]()
        self.parameters.forEach { (name, value) in
            queryItems.append(NSURLQueryItem(name: name, value: value))
        }

其中parameter是元组数组或参数字典,其元素(namevalue)是字符串。

然后将此数组设置为NSURLComponents实例:

        let urlQueryComponent = NSURLComponents()
        urlQueryComponent.queryItems = queryItems

可以获得编码的“查询”字符串,如下所示:

        let queryString = urlQueryComponent.percentEncodedQuery!

然后作为NSData表示:

        let data = queryString.dataUsingEncoding(NSUTF8StringEncoding)!

答案 3 :(得分:0)

好问题。好消息是,这似乎是一个常见且简单的错误。 在request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)行中,该编码的结果是可选的,而不是必须发送的JSON或Data对象。这意味着该对象在那里,但是它包裹在一个属性中,该属性允许将编码结果设为nil

首先,您需要删除以下行:

let data = postString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

因为您实际上是在覆盖返回的数据。

好,要解决可选问题,有一些替代方法:

首先也是最推荐的方法是解开该值并将其设置为httpbody:

if let unWrappedValue = postString.dataUsingEncoding(NSUTF8StringEncoding) {
 request.HTTPBody = unWrappedValue
}
else {
 //if the encoding fails, treat the error here before sending any value as the body
}

第二,您可以直接构造JSON并对其进行编码(尽管我不确定这是否是服务器期望的格式):

let jsonDic: [String: Any] = ["username": username, "password": password]

do {
 let jsonData = try JSONSerialization.data(withJSONObject: json)
catch {
 //treat the error here
}

request.HTTPBody = jsonData

在生产中建议的第三点(绝不是建议)(仅用于测试)是用“!”强制解开该值。像这样:

request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)!