【问题标题】:Google Places API web service using swift returns error 303使用 swift 的 Google Places API Web 服务返回错误 303
【发布时间】:2016-10-20 14:29:12
【问题描述】:

我正在尝试通过 iOS 使用 Google Places Web 服务(使用 swift)。 我想这样做的原因 - 我想允许浏览地图上的地方,即使它们不在附近(使用 iOS 提供的库允许的唯一搜索)。 我还需要以编程方式进行(因为在一个用例中我希望允许浏览地图,而在另一个用例中 - 我希望位置保持不变,而不是根据地图相机而改变)。 我无法使用 iOS 地点选择器,因为我希望地图显示有关其位置的信息(并且在一个用例中不会更改)... (如果你对这个问题有更好的设计思路,请告诉我..)

调用 Google Places API 网络服务时出现错误 303。 在 Google API 网络服务上,它不计算调用,所以我认为它失败了,尽管应该重定向 303。

我构建了一个用于与 Web 服务通信的类(我将服务器地址保存在配置中)。 这个类的结构也可以立即提供结果(而不是在回调中)。

为什么我收到错误而不是重定向? 有什么办法可以处理吗? 有什么想法可以完全避免重定向吗?

谢谢!!

这是我的代码的(一个模板)——我减少了大部分逻辑并留下了对 Web 服务的调用(PlaceMarker 只是我返回的一个类,您可以将其修改为 String):

class GooglePlacesWS : NSObject, NSURLConnectionDelegate, NSURLConnectionDataDelegate , URLSessionDelegate{

var DataReady : Bool!;
var Data : Foundation.Data!;
var opQueue : OperationQueue!;
var _responseData : NSMutableData!;
var error = false;

func getPlacesNear(_ point : CLLocationCoordinate2D, _ radius: Double)->[PlaceMarker]!
{
    var retVal  = [PlaceMarker]();

    var locationJson = ["location": String(format:"%f, %f",point.latitude,point.longitude), "key": “MyKey”];

    if (radius > 0){
        locationJson["raidus"] = String(format:"%d",Int(radius));
    }

    // Fires the request to the server
    var reply : String = HtmlToText(FireRequest(locationJson));
    if reply == "" { return nil}

    return retVal;
}

//MARK: Connection

var session : URLSession? = nil;
var dataTasks : URLSessionTask? = nil;

func sendRequestNew(_ request : URLRequest)
{
    DataReady = false;
    Data = nil;

    let task = session!.dataTask(with: request, completionHandler: {data, response,error in

        if (error != nil){

            NSLog("Error reading data from web service: " + error!.localizedDescription);
            self.Data = nil;
            self.error = true;
            self.DataReady = true;
        }
        else{
            if (data != nil){
                self.Data = data;
                OSMemoryBarrier();
                self.DataReady = true;
            }
        }

    });
    task.resume();
    dataTasks = task;
}

// Changes a string to an HTML friendly tags (so the XML will transfer a string)
func textToHtml (_ htmlString : String) -> String
{
    var retHtml = htmlString;
    retHtml = retHtml.replacingOccurrences(of: "&",  with: "&");
    retHtml = retHtml.replacingOccurrences(of: "<",  with: "&lt;");
    retHtml = retHtml.replacingOccurrences(of: ">",  with: "&gt;");
    retHtml = retHtml.replacingOccurrences(of: "\"", with: "&quot;");
    retHtml = retHtml.replacingOccurrences(of: "'",  with: "&#039;");
    //retHtml = retHtml.stringByReplacingOccurrencesOfString("\n", withString: "<br>");
    return retHtml;
}

// Changes an HTML string to a regular xml (changes the & tags to actual signs)
func HtmlToText(_ textString : String)->String
{
    var retString: String = textString;
    retString = retString.replacingOccurrences(of: "&amp;",  with:"&");
    retString = retString.replacingOccurrences(of: "&lt;",  with:"<");
    retString = retString.replacingOccurrences(of: "&gt;",  with:">");
    retString = retString.replacingOccurrences(of: "&quot;", with:"\"");
    retString = retString.replacingOccurrences(of: "&#039;",  with:"'");
    retString = retString.replacingOccurrences(of: "<br>", with:"\n");
    return retString;
}


// Sends the request to the server
func FireRequest (_ query : [String:String]) ->String
{
    var retVal : String = "";

    do{
        // Builds the final URL request (adds the headers, and the WS addy)
        let config :UserDefaults = UserDefaults();
        //var myDict: NSDictionary?
        if let path : String = config.object(forKey: "googleServerAddy") as? String
        {
            let url = URL(string: path);
            //let theRequest = NSMutableURLRequest(url: url!);
            var request = URLRequest(url: url!);
            request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
            request.httpMethod = "GET";
            request.httpBody = try JSONSerialization.data(withJSONObject: query, options: []);


            sendRequestNew(request);

            while (DataReady == false)
            {
                Thread.sleep(forTimeInterval: 0.01);
            }

            if (!error)
            {
                let result : Foundation.Data = Data!;

                // Reads the response...
                retVal = NSString(data: result, encoding:String.Encoding.utf8.rawValue)! as String;
            }
            else
            {
                retVal = "";
            }
        }
    }
    catch{

    }

    return retVal;
}


//MARK: NSURLConnection delegates
func connection(_ connection: NSURLConnection, willSend request: URLRequest, redirectResponse response: URLResponse?) -> URLRequest? {

    return request;
}


override init() {
    super.init();

    opQueue = OperationQueue();

    session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: opQueue);
    }
}

【问题讨论】:

    标签: swift google-api google-places-api nsurlsession nsurlrequest


    【解决方案1】:

    你可以使用Alamofire,工作正常。用于谷歌街景图片

    import Foundation
    import Alamofire
    import AlamofireImage
    
    
    class GoogleData {
    
        static let dataService = GoogleData()
    
        func getGoogleImages(_ latitude: Double, longitude: Double, heading: Double, id: String, key: Int){
    
            let url = "https://maps.googleapis.com/maps/api/streetview?size=400x300&location=" + String(latitude) + "," + String(longitude) +  "&heading=" + String(heading) +  "&fov=120&&pitch=-0.76&key=" + GOOGLE_API_KEY
    
                Alamofire.request(url).responseImage { (response) -> Void in
    
                print(response)
                guard let image = response.result.value else { return }
    
                print("alamo \(url) ")
                let returnObj = [image]
    
                ImageUtils.saveGoogleImageToFile(image , key: key, id: id)
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: googleGetImagesNotificationKey), object: returnObj)
            }
        }
    }
    

    叫它:

    GoogleData.dataService.getGoogleImages(yourlatitude, longitude: your.longitude, heading: someHeading, id: someId, key: someKey )
    

    【讨论】:

    • 我喜欢它的优雅,但现在为我的项目添加这个库为时已晚。我弄清楚了问题所在 - 请参阅我对这个问题的其他答案...谢谢你。我可能会在我的下一个项目中尝试这个库。
    【解决方案2】:

    所以我遇到的问题来源于这里:

    let url = URL(string: path);
    var request = URLRequest(url: url!);
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "GET";
    request.httpBody = try JSONSerialization.data(withJSONObject: query, options: []);
    

    看来 - 此解决方案强制重定向。 我不知道函数addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) 所以我想使用httpBody 来传输GET 数据,这显然是错误的......

    将代码更改为:

    let actPath = path + "?" + query;
    let url = URL(string: actPath);
    var request = URLRequest(url: url!);
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "GET";
    

    为我解决了这个问题。 注意query 是获取字符串的查询——类似于

    location=1.1, 2.2&radius=5&key=MY_KEY

    【讨论】:

      猜你喜欢
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多