Migrating to Places 4.0 SDK, how to migrate place Bias? - ios

I am migrating to the new places SDK 4.0
The old func was:
findAutocompletePredictions(fromQuery: query,
bounds: bounds,
boundsMode: .bias,
filter: filter,
sessionToken: token) { (prediction, error) in
callback(prediction, error)
}
the new func as per docs is
findAutocompletePredictions(fromQuery: query,
filter: filter,
sessionToken: token) { (prediction, error) in
callback(prediction, error)
}
I see that bounds bias is now set on the GMSAutocompleteFilter filter
This has a locationBias property where i set some and it takes a parameter of <GMSPlaceLocationBias>
The issue i have is there is no info on what to provide here...GMSPlaceLocationBias is a protocol, and i have no idea what im meant to use object wise to provide the old bounds data.
Conforming to the protocol gives me a locationBiasURLQueryItem fun to populate, with no further documentation on what should go in this function
So im stuck and cant upgrade as there doesnt seem to be a clear way forward.
Anyone have any ideas? Docs are here: https://developers.google.com/places/ios-sdk/reference/interface_g_m_s_places_client#ab60773feec0e68751c5a7f1066b9d252)
My attempt to construct the filter is:
let filter = GMSAutocompleteFilter()
if case .location(let location) = _locationController.locationStatus {
filter.locationBias = .some(location)
}
But obviously my custom location model object doesnt confirm to GMSPlaceLocationBias and is a struct so cant be used and errors

I got totally lost on this as well, but just found an example buried in one of the guides here.
In short the implementation looks like this:
let filter = GMSAutocompleteFilter()
filter.locationBias = GMSPlaceRectangularLocationOption(bounds.northEast, bounds.southWest)
Here I'm using the same bounds I had previously been using in 3.x (in my case from the map currently being displayed) to get those northEast and southWest coordinates, but you can generate your own based on how where you are trying to bias results.
I wish they had just made ANY indication in their docs that this was the intended way to do it.

Related

Parse Platform on iOS: best way to replace changed local values with more-recently changed server values?

So imagine the following scenario, using the Parse platform on iOS:
I get a PFObject from the server, let's call it GlassChalice.
Someone else, let's say Bill Blofeld, changes GlassChalice from a different location.
Later, I make some changes to my local GlassChalice, but don't save them to the server.
Still later, I want to update GlassChalice, but I want to update it to the current server values, in other word Bill Blofeld's values. I do not want to replace the server values with my local values, and also do not want to reset my local values to the values GlassChalice was loaded with.
So if I use revert(), will I get what I want?
According to the Parse docs:
- revert Clears any changes to this object made since the last call to save and sets it back to the server state.
...but, as in my example, clearing "changes made since the last call to save" and setting it "back to the server state" aren't always the same thing.
So far this seems like the only way to guarantee the results I want, but it has one obvious problem:
public func updateObjectFromServer(_ objectToUpdate: PFObject, then doThis: (()->Void)? = nil) {
let query = PFObject.query()
query?.whereKey("objectId", equalTo: objectToUpdate.objectId!)
query?.getFirstObjectInBackground (block: {
(serverObject, error) in
if error.isNil() {
objectToUpdate["numberOfLimbs"] = serverObject?["numberOfLimbs"]
objectToUpdate["eyePlacement"] = serverObject?["eyePlacement"]
objectToUpdate["crossStitchingTalentRating"] = serverObject?["crossStitchingTalentRating"]
objectToUpdate["clamsEaten"] = serverObject?["clamsEaten"]
} else {
//handle error...
}
doThis?()
})
}
But the huge problem here is that I have to know all the key names, and type them in explicitly, for this to work.
Is there a better, more generic, way?

MapKit Define the desired type of search results (Country, city, region, etc)

For an app i'm building, I want to implement a feature that allows users to specify the geographical origin of wines (country (e.g. France), region (e.g. Bordeaux), subregion (e.g. Paullac)).
I want to make sure that I don't have to add all available countries myself, and that all information that comes into the database is valid. Therefore, I decided to do it as follows:
User adds a new wine and types the name of the country it comes from
While typing, the app searches in the apple maps database
The results from this search get displayed as suggestions, and when the user taps a suggestion, the app creates a Country object with all relevant information. The wine van only be saved when such an object is present
This works fine, except one thing: Apple maps returns anything, like restaurants, shops, etcetera, from anywhere.
My question: How can I specify WHAT I am looking for? I can only specify the region I'm searching in, which is irrelevant in my case. I would like to be able to tell apple maps to ONLY look for countries, regions, cities, whatever. Is this possible in a way? I have exhausted google for this and found no way thus far.
Going off what #Trevor said, I found rejecting results where either the title or subtitle have numbers yields pretty good results if you only want cities and towns.
Swift 4.1 code:
// Store this as a property if you're searching a lot.
let digitsCharacterSet = NSCharacterSet.decimalDigits
let filteredResults = completer.results.filter { result in
if result.title.rangeOfCharacter(from: digitsCharacterSet) != nil {
return false
}
if result.subtitle.rangeOfCharacter(from: digitsCharacterSet) != nil {
return false
}
return true
}
or more compactly:
let filteredResults = completer.results.filter({ $0.title.rangeOfCharacter(from: digitsCharacterSet) == nil && $0.subtitle.rangeOfCharacter(from: digitsCharacterSet) == nil })
The best solution we found was to filter our results using a comma in the result's title. This mostly returned only results that matched a city's format, e.g Detroit, MI, United States. We added this filter to the ones suggested by #Ben Stahl. Ben's solution filtered out edge cases where a comma formed part of the business' name.
This usually returns the correct result within three characters. To answer the OP's question, you could then parse this string by city, state or country to get the desired result.
For better results you could use the Google Places API.
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
self.searchResults = completer.results.filter { result in
if !result.title.contains(",") {
return false
}
if result.title.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
if result.subtitle.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil {
return false
}
return true
}
self.searchResultsCollectionView.reloadData()
}
I have worked with MapKit and don't believe you can do autocomplete assistance on user entries as they type the best solution I found is Google Place API autocomplete
iOS right now provides receiving geo-coordinates when sending a well-formatted address , or you can receive an address when sending a pair of coordinates. Or points of interest for locations names or coordinates.
There was a class added to MapKit in iOS 9.3 called MKLocalSearchCompleter which helps with autocompletion. You can filter what is returned by using 'MKSearchCompletionFilterType' but that isn't the most extensive and might not fully help with your situation. It does return cities and countries as results but it also returns businesses when I've used it.
One possible option is to filter the returned results again on the app side and exclude all results that have a numeric character in them.
func setupCompleter() {
self.searchCompleter = MKLocalSearchCompleter()
self.searchCompleter?.delegate = self
self.searchCompleter?.filterType = .locationsOnly
self.searchCompleter?.queryFragment = "Bordeaux"
}
func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
print("Results \(completer.results)")
// Do additional filtering on results here
}
In addition to Allan's answer, I've found that if you filter by the subtitle property of a MkLocalSearchCompletion object, you can remove the business entries.

How can I visualise tweets on a map in Processing?

I'm trying to use the twitter API to search for a keyword and get the location of that particular tweet to then visualise onto a map.
I've successfully created my map using unfolding maps and tilemill, I'm just struggling with the twitter part. Using the twitter 4J library, I've tried the following code but I'm not able to get the location as coordinates. Also, once I've got the coordinates I dont know how to go about visualising them on my map.
import twitter4j.*;
import twitter4j.api.*;
import twitter4j.auth.*;
import twitter4j.conf.*;
import twitter4j.json.*;
import twitter4j.management.*;
import twitter4j.util.*;
import twitter4j.util.function.*;
ConfigurationBuilder cb = new ConfigurationBuilder();
Twitter twitterInstance;
Query queryForTwitter;
void setup() {
cb.setOAuthConsumerKey("**********");
cb.setOAuthConsumerSecret("*******");
cb.setOAuthAccessToken("*********");
cb.setOAuthAccessTokenSecret("*********");
twitterInstance = new TwitterFactory( cb.build()).getInstance();
queryForTwitter = new Query("#nature");
size(640, 440);
background(0);
FetchAndDrawTweets();
}
void FetchAndDrawTweets() {
try {
QueryResult result = twitterInstance.search(queryForTwitter);
ArrayList tweets = (ArrayList) result.getTweets();
for (int i=0; i<tweets.size(); i++) {
Status t = (Status) tweets.get(i);
String user = (t.getUser()).getLocation();
text(user + ":" , 20,15+i*15);
}
}
catch(TwitterException te) {
println("Couldn't connect:" + te);
}
}here
I'm quite new to processing, so please be patient with me as I don't even know if I'm going about this the right way.
Any help would be gratefully appreciated!!
Nice work on separating your problem into smaller sub-problems. It's a good idea to separate the "get tweets and locations" step from the "show stuff on map" step. Good work.
As for getting the location of a tweet, there are two places you should look:
The Twitter4J JavaDocs: This is a list of every class, function, and variable available to you from the Twitter4J library. This should be your first stop. Do you see anything that looks useful in here? Specifically, the Status class has a getGeoLocation() function that looks pretty promising.
The Twitter API: this is the underlying JavaScript API that the Twitter4J library is built on. Check out this documentation for more details on what's going on underneath the Twitter4J library. Specifically, this page says the the geo object is deprecated and that you should use the coordinates field instead.
So the first thing I would try is the getGeoLocation() function. But note that not every tweet will have a location, since users can disable location tracking. Also note that if the underlying JavaScript library no longer provides the geo object, and if the Twitter4J library is using that to populate its getGeoLocation() function, then you won't be able to get at the location through Twitter4J. I haven't tested that at all though.

Possible to make a composite symbol?

When editing a vertex I would like to substitute the vertex symbol with SimpleMarkerSymbol and a TextSymbol but that appears to be impossible. Any suggestions on how I could do this? I want the appearance of dragging something like this (text + circle):
After taking some time to look at the API I've come to the conclusion it is impossible. Here is my workaround:
editor.on("vertex-move", args => {
let map = this.options.map;
let g = <Graphic>args.vertexinfo.graphic;
let startPoint = <Point>g.geometry;
let tx = args.transform;
let endPoint = map.toMap(map.toScreen(startPoint).offset(tx.dx, tx.dy));
// draw a 'cursor' as a hack to render text over the active vertex
if (!cursor) {
cursor = new Graphic(endPoint, new TextSymbol({text: "foo"}));
this.layer.add(cursor);
} else {
cursor.setGeometry(endPoint);
cursor.draw();
}
})
You could use a TextSymbol to create a point with font type having numbers inside the circle. Here is one place where you can find such font. http://www.fontspace.com/the-fontsite/combinumerals
Wont be exactly as shown in the image but close enough. Also some limitation it wont work with IE9 or lower (this is as per esri documentation, as I am using halo to get the white border).
Here is the working Jsbin : http://jsbin.com/hayirebiga/edit?html,output use point of multipoint
PS: I have converted the ttf to otf and then added the font as base64, which is optional. I did it as I could not add the ttf or otf to jsbin.
Well, Achieve this seems impossible so far however ArcGIS JS API provides a new Application/platform where you can generate single symbol online for your applications.
We can simply create all kind of symbols(Provide by ESRI) online and it gives you on the fly code which you just need to paste in your application.
This will help us to try different type of suitable symbols for the applications.
Application URL: https://developers.arcgis.com/javascript/3/samples/playground/index.html
Hoping this will help you :)

How to receive updates to the Twitter social graph?

I just got some crazy ideas for analyzing the Twitter social graph (i.e., representing follow-relations as the edges of a graph). Interestingly, the Twitter API provides methods for creating the graph. It is possible to read out a static snapshot of the social graph, whereas Twitter is a very dynamic network. It would be great if one could dynamically update the graph. So my question is: Is there any way to get notified by Twitter when anyone starts or stops to follow anyone?
I believe that the documentation you linked to would definitely mention that.
I'm quite certain that you need to do your own follower-list checking, and compare results on a regular basis.
I do this if someone follows me or not and how many followers they have and i generate this chart
public function existsFriendship($username,$friend)
{
try
{
if ($this->twitter->existsFriendship($username, $friend))
return true;
}
catch(Exception $e)
{
$this->debug($e->getMessage());
}
}
for the chart generation i use pchart.
in smarty template the code looks like this;
include("pChart/pData.class");
include("pChart/pChart.class"); ![alt text][1]
// Initialise the graph
$Test = new pChart(700,230);
$Test->setFontProperties("Fonts/tahoma.ttf",13);
$Test->setGraphArea(40,30,680,200);
$Test->drawGraphArea(252,252,252,TRUE);
$Test->drawScale($DataSet->GetData(),$DataSet->GetDataDescription(),SCALE_NORMAL,150,150,150,TRUE,0,2);
$Test->drawGrid(4,TRUE,230,230,230,70);
// Draw the line graph
$Test->drawLineGraph($DataSet->GetData(),$DataSet->GetDataDescription());
$Test->drawPlotGraph($DataSet->GetData(),$DataSet->GetDataDescription(),3,2,255,255,255);
// Finish the graph
$Test->setFontProperties("Fonts/tahoma.ttf",12);
$Test->drawLegend(45,35,$DataSet->GetDataDescription(),255,255,255);
$Test->setFontProperties("Fonts/tahoma.ttf",12);
$Test->drawTitle(60,22,"Twitter Graph",50,50,50,585);
$example = $Test->Render("templates/example1.png");
$smarty->assign("example",$example);
$smarty->display('index.tpl');
finaly the result
alt text http://img691.imageshack.us/img691/6749/example1k.png

Resources