菜鸟教程小白 发表于 2022-12-11 17:54:47

iOS api 调用本地 RESTful Django 失败


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

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

<p>我的 Django view.py 和 url.py 文件</p>

<pre><code>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):
    &#34;&#34;&#34;
    List all snippets, or create a new snippet.
    &#34;&#34;&#34;
    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):
    &#34;&#34;&#34;
    Retrieve, update or delete a snippet instance.
    &#34;&#34;&#34;
    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)
</code></pre>

<p>我的 iOS API 文件</p>

<pre><code>import Foundation
import SwiftyJSON

typealias ServiceResponse = (JSON, NSError?) -&gt; Void

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

let baseURL = &#34;http://127.0.0.1:8000/snippets/?format=json&#34;

func getRandomUser(onCompletion: (JSON) -&gt; 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 -&gt; Void in
      print(data)
      print(response)
      print(error)
      print(&#34;list&#34;)
      let json:JSON = JSON(data: data!)
      onCompletion(json, error)
    })
    task.resume()
}
</code></pre>

<p>动态添加表格行的我的 ViewController </p>

<pre><code>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(&#34;Add new Dummy&#34;, forState: UIControlState.Normal)
    btn.addTarget(self, action: #selector(TableMenu.addDummyData), forControlEvents: UIControlEvents.TouchUpInside)
    self.view.addSubview(btn)
    }




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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -&gt; UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier(&#34;CELL&#34;) as UITableViewCell!

    if cell == nil {
      cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: &#34;CELL&#34;)
    }

    let user:JSON =JSON(self.items)

    print(user)
    //let picURL = user[&#34;picture&#34;][&#34;medium&#34;].string
    //print(picURL)
    //let url = NSURL(string: picURL!)
    //let data = NSData(contentsOfURL: url!)
    //print(user)
    cell!.textLabel?.text = user.string //user[&#34;username&#34;].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[&#34;id&#34;].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.
   }
   */

}
</code></pre>

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

<pre><code>Optional(Error Domain=NSURLErrorDomain Code=-1004 &#34;Could not connect to the server.&#34; UserInfo={NSUnderlyingError=0x12dd99a50 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 &#34;(null)&#34; 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.})
</code></pre>

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

<p>感谢您的宝贵时间。</p>

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

<p>祝大家好运</p>

<p>编辑我的 info.plist 如下所示
<a href="/image/CNDJ2.png" rel="noreferrer noopener nofollow">info.plist</a> </p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>作为应用传输安全性的一部分,Apple 已禁用来自 iOS 应用的所有不安全 HTTP 流量。这有助于实现安全最佳实践。</p>

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

<p><strong>解决方案:-</strong></p>

<p>打开 Info.plist,并添加以下行:</p>

<pre><code>&lt;key&gt;NSAppTransportSecurity&lt;/key&gt;
&lt;dict&gt;
    &lt;key&gt;NSAllowsArbitraryLoads&lt;/key&gt;
    &lt;true/&gt;
&lt;/dict&gt;
</code></pre>

<p><strong>注意:-</strong></p>

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

<p>有关更多信息,请参阅此链接:
<a href="http://www.neglectedpotential.com/2015/06/working-with-apples-application-transport-security/" rel="noreferrer noopener nofollow">http://www.neglectedpotential.com/2015/06/working-with-apples-application-transport-security/</a> </p></p>
                                   
                                                <p style="font-size: 20px;">关于iOS api 调用本地 RESTful Django 失败,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/40195403/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/40195403/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: iOS api 调用本地 RESTful Django 失败