我正在尝试附加 alamofire 循环并放入 sqlite db,但它给了我错误

Posted

技术标签:

【中文标题】我正在尝试附加 alamofire 循环并放入 sqlite db,但它给了我错误【英文标题】:I'm trying to append the alamofire loop and put in on sqlite db but it gives me error 【发布时间】:2019-02-28 07:44:39 【问题描述】:

致命错误超出范围这是日志文件

Alamofire URL 请求在循环中,系统的断点已经是 44,而不是在获取数组的第一个值后的第一个索引。

我尝试在循环之外打印数组,但它只是给了我一个空数组打印日志只是 []

let url = "http://localhost:8080/iostest/selectstudents.php"
    let parameters: Parameters=[
        "StatusCodeID":"2",
        "subjectCode":"ENG 099",
        "section":"BSIT 2-2BSIT-01"
    ]
    Alamofire.request(url, method: .post, parameters: parameters).responseJSON
        response in
        let json = response.data

        if let result = response.result.value 

            //converting it as NSDictionary
            let jsonData = result as! NSDictionary
            //displaying the message in label
            let x = jsonData.value(forKey: "Students") as! NSArray

            for dict in x 
                let dictone = dict as! NSDictionary

                ArrayStudentNumber.append(dictone["StudentNumber"]  as! String)
                ArraySection.append(dictone["Section"] as! String)
                ArraySemester.append(dictone["Semester"] as! String)
                ArraySubjectCode.append(dictone["SubjectCode"] as! String)
                ArraySchoolYear.append(dictone["SchoolYear"] as! String)
            


        

        let arraycount = ArrayStudentNumber.count
        var counter = 0
        while counter < arraycount
        print(counter)
        var currentindex = counter
        print (ArrayStudentNumber[counter])
        let url2 = "http://localhost:8080/iostest/selectstudentsinfo.php"
        var parameters2: Parameters=["studentNumber" : ArrayStudentNumber[currentindex]]

        Alamofire.request(url2, method: .post, parameters: parameters2).responseJSON
            response in
            let json = response.data
            if let result = response.result.value 
                print (response)
                //converting it as NSDictionary
                let jsonData = result as! NSDictionary
                //displaying the message in label
                let x = jsonData.value(forKey: "StudentsInfo") as! NSArray
                for dict in x 
                    let dictone = dict as! NSDictionary

                    ArrayFirstname.append(dictone["Firstname"]  as! String)
                    ArrayLastname.append(dictone["Lastname"]  as! String)
                    ArrayMiddlename.append(dictone["Middlename"]  as! String)
                    ArrayCollege.append(dictone["College"]  as! String)
                    ArrayCourse.append(dictone["Course"]  as! String)




                

            
        

            counter += 1
    

        var loopcounter = 0
        let thisarraycount = ArrayFirstname.count
        while loopcounter < thisarraycount
            var insertstatemanet: OpaquePointer? = nil
            var insertsql = "insert into tableStudentInfo(StudentNumber,Firstname,Lastname,Middlename,College,Course,SubjectCode,Section,Semester,Schoolyear) values ('\(ArrayStudentNumber[loopcounter])','\(ArrayFirstname[loopcounter])','\(ArrayLastname[loopcounter])','\(ArrayMiddlename[loopcounter])','\(ArrayCollege[loopcounter])','\(ArrayCourse[loopcounter])','\(ArraySubjectCode[loopcounter])','\(ArraySection[loopcounter])','\(ArraySemester[loopcounter])','\(ArraySchoolYear[loopcounter])';"


            //isolate sql query and validate statements
            sqlite3_prepare_v2(db, insertsql, -1, &insertstatemanet, nil)
            //
            if sqlite3_step(insertstatemanet) == SQLITE_DONE
                print("Inserted", "\(ArrayStudentNumber[counter])")
            
            sqlite3_finalize(insertstatemanet)
        
        loopcounter = loopcounter + 1


    




【问题讨论】:

您的代码没有明显缩进,所以我会说您缺少 Asynchrone 概念。另外,在 Swift3+ 中避免使用 NSDictionary、NSArray、NSStuff,更喜欢它的 Swift 等价物。 缩进是什么意思? 【参考方案1】:

我所说的坏缩进的意思是,你不难阅读不同的范围,标签做得很奇怪。

你的代码有什么问题:

这是你正在做的主要逻辑:

//0
Alamofire.request(url, method: .post, parameters: parameters).responseJSON  response in
    if let result = response.result.value  //1
        //Populate arrays
    

    whileLoop  //2
        Alamofire.request(url2, method: .post, parameters: parameters2).responseJSON  
            if let result = response.result.value  //2.n
                //Populate arrays
            
        
    
    whileLoop  //3
        //Populate SQL according to populated arrays
    

//4

第一个大问题是您错过了 Alamofire 请求是异步的这一事实。这意味着,我在我放置 //number 的地方添加了 print,控制台中的 print 可能不是你所期望的。 目前应该是:“0, 4, 1, 2, 3, 2.3, 2.5, 2.2, 2.1, 2.4 etc.”,而不是“0, 1, 2, 2.1, 2.2..., 3, 4” .更糟糕的是,因为 2.n 甚至可能不在顺序中。 很明显,当您执行第三个操作(SQL 的 while 循环)时,您没有自己的价值观。

Asynchrone 概念是一个重要的概念,您需要理解和掌握它,因为它非常基础和常见。

见: Returning data from async call in Swift function Using a value from Alamofire request outside the function 等等

我想这就是为什么您将第二批 (//2) 请求的 while 循环放在第一个请求中的原因。

您需要做的是使用DispatchGroup,与enter()leave()notify()

Swift / How to use dispatch_group with multiple called web service? How do I use DispatchGroup / GCD to execute functions sequentially in swift? Waiting until the task finishes Swift closure async order of execution Wait until swift for loop with asynchronous network requests finishes executing 等等

有了要查找的关键字和链接,您应该能够找到可行的解决方案。

现在,在 Swift 3+ 中,避免使用 NSStuff,如 NSDictionary、NSArray,如果可用,则更喜欢 Swift 版本。

例子:

let jsonData = result as! NSDictionary

=>

let jsonData = result as! [String: Any]

避免使用value(forKey:),它的结果有一天可能会让你大吃一惊。为此需要了解 KVC。每件事都在适当的时候,但当你似乎开始时,避免使用它。首选object(forKey:),或直接下标:myDict["myKey"]

避免强制转换(使用!)。为什么?这告诉编译器:别担心,我知道我在做什么(通常情况并非如此,让我们明确一点)。如果我错了,就崩溃。因此,让您的应用程序崩溃是一场赌博,因为在某种情况下,您无法投射它,或者做出了错误的投射,不是吗? 首选if letguard let

最后:

ArrayStudentNumber.append(dictone["StudentNumber"])
ArraySection.append(dictone["Section"])
ArraySemester.append(dictone["Semester"])
ArraySubjectCode.append(dictone["SubjectCode"])
ArraySchoolYear.append(dictone["SchoolYear"])

没有。只是不要。不要为此使用多个数组。只用一个。为什么?如果要删除第一个会发生什么,您将删除每个数组上的第一个?如果您想重新排序一个(因为您现在发现学生按 id/学生编号而不是他们的姓名排序更好)怎么办?你也会对其他 4 个数组进行排序吗?这些信息只有放在一起才有意义。

使用字典数组、自定义对象数组来保存它们的值等。

另外,由于您将了解异步的内容,您会在其他 for 循环中看到(因为您也这样做)ArrayFirstname.first 可能不适用于 ArrayStudentNumber.first(请记住 2.1、2.2 顺序 I告诉过你吗?)

【讨论】:

以上是关于我正在尝试附加 alamofire 循环并放入 sqlite db,但它给了我错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AlamoFire 和 Swift 将 JSON 数据放入 UILabel

在for循环中将Dataframes附加在一起

将 [UInt8] 作为数据附加到 alamofire

使用 alamofire 在 Swift 上解析 Json

使用 Alamofire 4 下载 MP4 文件,同时附加自定义标题

无法在 Alamofire 4.0 中使用类型为“(String,withName:String)”的参数列表调用“附加”