#ios #mysql #json #swift #xcode
#iOS #mysql #json #swift #xcode
Вопрос:
Я новичок в разработке Swift и iOS, но я пытаюсь загрузить и проанализировать данные, которые хранятся в базе данных MySQL.
Я продолжаю получать ошибку:
Domain = NSCocoaErrorDomain Code = 3840 «Нет значения». userInfo={NSDebugDescription= Нет значения.}
Я опубликовал свой код ниже, но я не думаю, что проблема заключается в функции parseJSON, а в фактической загрузке данных, поскольку, когда я печатаю «данные», они возвращают «<>».
Вот мой код:
//properties
weak var delegate: HomeModelProtocal!
var data : NSMutableData = NSMutableData()
let urlPath: String = "http://localhost/service.php" //this will be changed to the path where service.php lives
// Function to download the incoming JSON data
func downloadItems(){
let url: URL = URL(string: urlPath)!
var session: URLSession!
let configuration = URLSessionConfiguration.default
session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url)
task.resume()
}
func urlSession(_ session: URLSession, task: URLSessionDataTask, didCompleteWithError error: Error?) {
self.data.append(data as Data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if error != nil{
print("Failed to download data")
}else{
print("Data downloaded")
print(data)
self.parseJSON()
}
}
func parseJSON(){
var jsonResult: NSMutableArray = NSMutableArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSMutableArray
} catch let error as NSError {
print("**** sake its happened again (error)")
}
var jsonElement: NSDictionary = NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 0 ..< jsonResult.count{
jsonElement = jsonResult[i] as! NSDictionary
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let exerciseName = jsonElement["stationName"] as? String,
let bodyPart = jsonElement["buildYear"] as? String
{
print(exerciseName, bodyPart)
location.exerciseName = exerciseName
location.bodyPart = bodyPart
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
self.delegate.itemsDownloaded(items:locations)
})
}
Комментарии:
1. Возможно, ответ пустой? Что вы
print(data)
показываете?2. попробуйте сделать это в postman или где-нибудь еще и проверьте, действительно ли там что-то есть
3. Я попытался распечатать данные, и они возвращают <> Когда я просматриваю URL-адрес, который я использую, я получаю следующее: ‘[ { «Exercise_Id»: «1», «Exercise_Name»: «Скручивание штанги», «Body_Part»: «Руки» }, ‘
Ответ №1:
Особенно плохо в вашем коде:
//This method is not being called...
func urlSession(_ session: URLSession, task: URLSessionDataTask, didCompleteWithError error: Error?) {
self.data.append(data as Data) //<-This line adding self.data to self.data
}
Не существует urlSession(_:task:didCompleteWithError:)
метода, который принимает URLSessionDataTask
в качестве второго параметра. Таким образом, этот метод никогда не будет вызван.
И внутри метода self.data
добавляется self.data
, поэтому, даже если метод вызывается, self.data
он все равно остается пустым…
Вместо этого вам нужно реализовать этот метод:
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.data.append(data)
}
Но если вы не хотите ничего делать, кроме накопления полученных данных, вам не нужно использовать делегатов.
И вы используете принудительное приведение в своем parseJSON()
методе:
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options: []) as! NSMutableArray
без указания .mutableContainers
опции. Это также приведет к сбою вашего приложения.
И ваш код использует слишком много NSSomethings
.
Исправив все подобные вещи, вы можете получить что-то вроде этого:
//properties
weak var delegate: HomeModelProtocal!
let urlPath: String = "http://localhost/service.php" //this will be changed to the path where service.php lives
// Function to download the incoming JSON data
func downloadItems() {
let url: URL = URL(string: urlPath)!
let session = URLSession.shared
let task = session.dataTask(with: url) {data, response, error in
if let error = error {
print("Failed to download data: (error)")
} else if let data = data {
print("Data downloaded")
print(data as NSData)
//print(String(data: data, encoding: .utf8))
self.parseJSON(data: data)
} else {
print("Something is wrong...")
}
}
task.resume()
}
func parseJSON(data: Data){
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data) as? [[String: AnyObject]] {
var locations: [LocationModel] = []
for jsonElement in jsonResult {
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let exerciseName = jsonElement["stationName"] as? String,
let bodyPart = jsonElement["buildYear"] as? String
{
print(exerciseName, bodyPart)
location.exerciseName = exerciseName
location.bodyPart = bodyPart
}
locations.append(location)
DispatchQueue.main.async {
self.delegate.itemsDownloaded(items: locations)
}
}
} else {
print("bad JSON")
}
} catch let error as NSError {
print("**** sake its happened again (error)")
}
}
Комментарии:
1. Большое вам спасибо за помощь в решении моей проблемы, это исправило ее отлично!