我需要从MYSQL获取JSON值并将其显示在表格视图中。我已经完成PHP部分以接收数据,但是我的XCODE错误。我的数据将存储温度,湿度和传感器的数字状态(开/关)。我有以下问题:
class DataManager {
var nodenameArray: [String] = []
var nodeidArray: [String] = []
var tempArray: [Float] = []
var humArray: [Float] = []
var pirArray: [Bool] = []
var lightArray: [Bool] = []
var relayArray: [Bool] = []
var hallArray: [Bool] = []
var smokeArray: [Bool] = []
@objc func taskdo() {
self.nodenameArray = []
self.nodeidArray = []
self.tempArray = []
self.humArray = []
self.pirArray = []
self.lightArray = []
self.relayArray = []
self.hallArray = []
self.smokeArray = []
if userlogin == true {
let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
request.httpMethod = "POST"
let postString = "username=\(username)&password=\(password)&authen=wdwfesf9329140dsvfxkciospdkm"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error!)")
return
} else {
do {
if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
print(respondString)
if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
for node in nodedata{
if let nodeDict = node as? NSDictionary {
if let nodeid = nodeDict.value(forKey: "node_id") {
self.nodeidArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "node_name") {
self.nodenameArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "temp") {
self.tempArray.insert(Float(nodeid as! String)!, at: 0)
}
if let nodeid = nodeDict.value(forKey: "hum") {
print(nodeid)
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
}
}
}
}
}
print(self.nodenameArray)
print(self.nodeidArray)
print(self.tempArray)
print(self.humArray)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "load"), object: nil)
}
catch let error as NSError {
print(error.debugDescription)
}
}
}
task.resume()
}
}
}
下面是响应:
{
nodedata = (
{
"hall_status" = "<null>";
hum = 111;
"light_status" = "<null>";
"node_id" = y2cfwecrw3hqznuxmfvf;
"node_name" = SVIN03;
"pir_status" = OFF;
"relay_status" = "<null>";
"smoke_status" = "<null>";
temp = 2132;
},
{
"node_name" = SVIN04;
nodeid = aj2w1aljw8nd65ax79dm;
},
{
"hall_status" = "<null>";
hum = 100;
"light_status" = "<null>";
"node_id" = mwmfl2og2l8888fjpj2d;
"node_name" = SVIN05;
"pir_status" = ON;
"relay_status" = "<null>";
"smoke_status" = "<null>";
temp = 45;
}
);
numberofnodeid = 3;
}
111 100
无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为'NSString'(0x10ca71568)。 2018-10-11 08:11:05.352491 + 0700 IOT 2 [1506:101847]无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为'NSString'(0x10ca71568)。
此行有错误:
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
答案 0 :(得分:0)
首先,您必须查看json_decode才能从php中的json读取数据
示例:
`$json = '{"foo-bar": 12345}';
$obj = json_decode($json);
print $obj->{'foo-bar'}; // this will print 12345`
如何获取ON / OFF JSON值并将其存储在Bool数组中? 基本上,您必须向onOff变量添加一个新值,例如
$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
$val = 0
} else {
$val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});
如何获取JSON值并将其存储在Float数组中? 基本上是同一件事,我已经有一段时间没有使用PHP了,只是声明您需要的值类型的数组。
如果JSON值为,我如何在XCODE中将值存储为0? 我猜你的意思是如果它为null,在这种情况下,你必须这样做
$onOff=array();
$val;
$obj = json_decode($json);
if (is_null($obj->{'name_of_the_alert'})) {
$val = 0
} else {
$val = $obj->{'name_of_the_alert'};
}
array_push($onOff,$obj->{'name_of_the_alert'});
考虑到我在这里可能会犯一些错误,因为我不熟悉较新的PHP版本。
祝你好运
答案 1 :(得分:0)
从您的问题来看,很清楚temp
和hum
是数字类型(双精度整数)。因此,使用NSNumber
而不是NSString
作为
self.humArray.insert(Float(Int(nodeid as! NSNumber)!), at: 0)
作为更快捷的方法,您可以将代码更新为:
if let nodeDict = node as? [String: Any] {
if let nodeid = nodeDict["node_id"] as? String {
self.nodeidArray.insert(nodeid, at: 0)
}
if let nodename = nodeDict["node_name"] as? String {
self.nodenameArray.insert(nodename, at: 0)
}
if let temp = nodeDict["temp"] as? Int {
self.tempArray.insert(Float(temp), at: 0)
}
if let hum = nodeDict["hum"] as? Int {
self.humArray.insert(Float(hum), at: 0)
}
}
答案 2 :(得分:0)
您的代码有很多问题:
首先,避免在等效的Swift3 +中使用NSStuff。
let request = NSMutableURLRequest(url: NSURL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")! as URL)
...
let task = URLSession.shared.dataTask(with: request as URLRequest) {
=>
let request = URLRequest(url: URL(string: http://talectric.com/wp-admin/a_p/iot/read_all.php")!)
...
let task = URLSession.shared.dataTask(with: request) {
瞧,您已经避免了所有as URL
,as URLRequest
。
避免强行展开:避免使用!
。
因为如果它为nil或使用as!
强制转换失败(然后为nil),则会导致崩溃。
使用if let
,guard let
。 Read this about Optional
作为示例,我会写:
guard let url = URL(string:http...) else {
print("invalid URL")
return
}
let request = URLRequest(url: url)
解析部分:
if let respondString = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
摆脱NSDictionary
,改用[String: Any]
,然后摆脱.allowFragments
,这很少有用(仅在某些情况下才有意义) data!
,并且不要命名变量respondString
因为这显然不是String
,而且显然具有误导性。
=>
guard let data = data else { return }
if let responseDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
现在:
if let nodedata = respondString.value(forKey: "nodedata") as? NSArray {
for node in nodedata{
if let nodeDict = node as? NSDictionary {
if let nodeid = nodeDict.value(forKey: "node_id") {
self.nodeidArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "node_name") {
self.nodenameArray.insert(nodeid as! String, at: 0)
}
if let nodeid = nodeDict.value(forKey: "temp") {
self.tempArray.insert(Float(nodeid as! String)!, at: 0)
}
if let nodeid = nodeDict.value(forKey: "hum") {
print(nodeid)
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
}
}
}
}
否,否NSArray
,否NSDictionary
,请避免使用value(forKey:)
,因为它会像您在NSDictionary
上所做的那样执行object(forKey:)
,或者只需下标(使用["someKey"]
),但是在Array
上,您会遇到一个问题,我想这是意外的结果。
不要命名您的所有变量nodeid
,在病房之后更难以调试,如果只是在此值之后进行强制解包,也不要进行软解包(if let
)。
if let nodedata = responseDict["nodedata"] as? [[String: Any]] {
for aNode in nodedata {
if let id = aNode["node_id"] as? String {
self.nodeidArray.insert(nodeId, at: 0)
}
if let name = aNode["node_name"] as? String {
self.nodenameArray.insert(name, at: 0)
}
if let temp = aNode["temp"] as? String, let tempFloat = Float(temp) {
self.tempArray.insert(tempFloat, at: 0)
}
if let hum = aNode["hum"] as? String, let humFloat = Float(hum) {
self.humArray.insert(humFloat, at: 0)
}
}
}
那更具可读性。
现在,使用insert(_:at:)
可能会更容易,而不是使用nodedata.inverted()
。
现在,让我们谈谈架构:
如果您在一次迭代中不通过if let hum = aNode["hum"] as? String, let humFloat = Float(hum) {
(假设第二次恰好是您所提供的样本中的情况,则没有temp
),那么您的情况将如何?其他?
这将发生什么:
self.nodeidArray[3]
和self.humArray[3]
将不正确,它们将被取消同步,对吗?
因为self.nodeidArray[2]
应该和self.humArray[1]
一起使用。
这些值是要同步的,因此请使用自定义的Struct / Class: 毕竟,Swift是一种OOP(面向对象编程)语言,因此请使用对象。
struct Node {
let id: String?
let name: String?
let humidity: Float?
let temperature: Float?
}
所以没有:
var nodenameArray: [String] = []
var nodeidArray: [String] = []
var tempArray: [Float] = []
var humArray: [Float] = []
只需:
var nodes: [Node] = []
在解析过程中,执行
let node = Node.init(withDict: aNode)
nodes.append(node) //or insert it at 0
您可以在Node中构造自己的方法init
,例如:
func init(withDict dict: [String: Any]) {
if let id = dict["node_id"] as? String {
self.id = id
}
etc.
}
简化此Node
类。但是使用Codable(在Swift 4中可用)可以避免使用JSONSerialization
并手动初始化所有值。
旁注:
此代码未经测试,可能存在一些故障,错别字等。让我们集中精力进行解释。
最后与该错误有关:
无法将类型'__NSCFNumber'(0x10db6f878)的值强制转换为 'NSString'(0x10ca71568)。 2018-10-11 08:11:05.352491 + 0700 IOT 2 [1506:101847]无法转换类型'__NSCFNumber'的值 (0x10db6f878)到'NSString'(0x10ca71568)。
此行有错误:
self.humArray.insert(Float(Int(nodeid as! String)!), at: 0)
该错误意味着您有时尝试在a as
上级联(使用(NS)String
),但实际上是NSNumber
(在Swift中,它很容易转换为{ {1}} / Int
等),因此失败。
因此失败的部分:Float
,因为nodeid as! String
不是nodeid