iOS api调用本地RESTful Django失败

时间:2016-10-22 18:08:46

标签: ios django swift django-rest-framework swifty-json

大家好,第一次发帖提问。很长一段时间内收获其他问题的好处所以我想在此之前向所有回答问题的人表示感谢。

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

我的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控制器动态添加表行

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.})

我在这里找了一段时间来回答这个问题,但是一切都是关于身份验证的,我认为在我向用户提供需要验证访问的特定数据库之前,先让两个人进行通信

感谢您的时间。

请批评我的堆叠溢出礼仪,以便积极收到我未来的问题。

欢呼你们

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

2 个答案:

答案 0 :(得分:0)

作为App Transport Security的一部分,Apple已禁用iOS应用中的所有不安全HTTP流量。这有助于实施安全最佳实践。

如果您尝试在启用ATS的情况下发出HTTP请求(使用NSURLSession或像AFNetworking这样的库),那么您将收到错误。

<强>解决方案: -

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

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

<强>注意: -

请记住,上述解决方案应该是您的最后手段。理想情况下,您希望在服务上启用HTTPS,或者在您希望使用HTTP的白名单域中启用HTTPS,如果不可能,则使用此方法

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

答案 1 :(得分:0)

Gy指出我应该使用我的电脑IP地址。在阅读了本地服务器之后,我发现当我在我的Mac上运行django服务器时,无法从我的iPad上访问它。

因此,要让我开始工作,我需要将ipad链接到我的mac,方法是在同一个网络上并将IP地址放在URL中。

我还没有开始工作,但我现在需要专注于前端开发,但对于任何旅行者来说,这个链接应该有所帮助。

Access localhost on Mac from XCode? Phonegap communicating with Ajax to a local Rails app

我希望将来能够使用它并更新这个答案。

干杯