OGeek|极客世界-中国程序员成长平台

标题: iOS api 调用本地 RESTful Django 失败 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 17:54
标题: iOS api 调用本地 RESTful Django 失败

大家好,第一次发帖。很长一段时间以来都从其他问题中受益,所以我想在此开头感谢所有在这里回答问题的人。

关于我的问题。所以我设置了一个本地 Django 服务器,可以正确地将 JSON 对象返回到我的浏览器。我还在 IOS 中使用 swift 设置了一个 API 查询方案,可以与教程 HTTP 服务器一起正常工作。但是,当我尝试调用自己的本地服务器时,我的数据和响应对象为零

我的 Django view.py 和 url.py 文件

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from snippets.models import Snippet
from django.http import Http404
from snippets.serializers import SnippetSerializer

class SnippetList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class SnippetDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

我的 iOS API 文件

import Foundation
import SwiftyJSON

typealias ServiceResponse = (JSON, NSError?) -> Void

class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()

let baseURL = "http://127.0.0.1:8000/snippets/?format=json"

func getRandomUser(onCompletion: (JSON) -> Void) {
    let route = baseURL
    makeHTTPGetRequest(route, onCompletion: { json, err in
        onCompletion(json as JSON)
    })
}

func makeHTTPGetRequest(path: String, onCompletion: ServiceResponse) {
    let request = NSMutableURLRequest(URL: NSURL(string: path)!)

    let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        print(data)
        print(response)
        print(error)
        print("list")
        let json:JSON = JSON(data: data!)
        onCompletion(json, error)
    })
    task.resume()
}

动态添加表格行的我的 View Controller

import UIKit
import MapKit
import CoreLocation
import SwiftyJSON

class TableMenu: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var tableView:UITableView?
    var items = NSMutableArray()

    override func viewWillAppear(animated: Bool) {
    let frame:CGRect = CGRect(x: 0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
    self.tableView = UITableView(frame: frame)
    self.tableView?.dataSource = self
    self.tableView?.delegate = self
    self.view.addSubview(self.tableView!)

    let btn = UIButton(frame: CGRect(x: 0, y: 25, width: self.view.frame.width, height: 50))
    btn.backgroundColor = UIColor.cyanColor()
    btn.setTitle("Add new Dummy", forState: UIControlState.Normal)
    btn.addTarget(self, action: #selector(TableMenu.addDummyData), forControlEvents: UIControlEvents.TouchUpInside)
    self.view.addSubview(btn)
    }




func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.items.count;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as UITableViewCell!

    if cell == nil {
        cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "CELL")
    }

    let user:JSON =  JSON(self.items[indexPath.row])

    print(user)
    //let picURL = user["picture"]["medium"].string
    //print(picURL)
    //let url = NSURL(string: picURL!)
    //let data = NSData(contentsOfURL: url!)
    //print(user)
    cell!.textLabel?.text = user.string //user["username"].string
   // cell?.imageView?.image = UIImage(data: data!)

    return cell!
}
func addDummyData() {
    RestApiManager.sharedInstance.getRandomUser { json in
        let results = json.array
       for Json: JSON in results! {
        let user: AnyObject = Json["id"].string!
            print(user)
            self.items.addObject(user)
            dispatch_async(dispatch_get_main_queue(),{
                self.tableView?.reloadData()
            })
        }
    }
}
    /*
     // MARK: - Navigation

     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */

}

当我从我得到的 dataTaskWithRequest 方法中打印出错误对象时得到的错误

Optional(Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo={NSUnderlyingError=0x12dd99a50 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 "(null)" UserInfo={_kCFStreamErrorCodeKey=61, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=http://127.0.0.1:8000/snippets/?format=json, NSErrorFailingURLKey=http://127.0.0.1:8000/snippets/?format=json, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=61, NSLocalizedDescription=Could not connect to the server.})

我在这里看了一段时间来寻找答案,但一切都是关于身份验证的,我认为 id 首先让两者进行通信,然后再为用户提供需要身份验证才能访问的特定数据库

感谢您的宝贵时间。

请批评我的 stack-overflow 礼仪,以便我 future 的问题得到肯定。

祝大家好运

编辑我的 info.plist 如下所示 info.plist



Best Answer-推荐答案


作为应用传输安全性的一部分,Apple 已禁用来自 iOS 应用的所有不安全 HTTP 流量。这有助于实现安全最佳实践。

如果您尝试在启用 ATS 的情况下发出 HTTP 请求(使用 NSURLSession 或 AFNetworking 之类的库),您将遇到错误。

解决方案:-

打开 Info.plist,并添加以下行:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

注意:-

请记住,上述解决方案应该是您最后的手段。理想情况下,您希望在您的服务上启用 HTTPS,或者接下来,将您希望使用 HTTP 的域列入白名单,如果这些都不可行,请使用此方法

有关更多信息,请参阅此链接: http://www.neglectedpotential.com/2015/06/working-with-apples-application-transport-security/

关于iOS api 调用本地 RESTful Django 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40195403/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4