I'm coding an iOS app with a Mapbox MGLMapView displayed on my view controller, on this mapView I draw a route using a MGLShapeSource, MGLLineStyleLayer and MGLPolylineFeature objects.
Here is the code :
let newSource = MGLShapeSource(identifier: "polylineBlue", shape: self.polylines, options: nil)
mapView.style?.addSource(newSource)
let newStyle = MGLLineStyleLayer(identifier: "polylineBlueLayer", source: source)
...styling my layer...
mapView.style?.addLayer(newStyle)
source.shape = self.polylines // a MGLPolylineFeature object
Works great for the route but there is one issue : is appears on top of my annotations.
I add the annotation with regular mapView function :
mapView.addAnnotations([..my MGLPointAnnotation objects...])
I've tried searching here and other websites, I only found one topic and there is nothing helpful except someone saying that we can't set a z layer position on annotations so no fix for that.
Does someone know a workaround ? Do I have to use that : https://docs.mapbox.com/ios/maps/examples/add-marker-symbol/ ?
if so, do I need to create one MGLSymbolStyleLayer per annotation ?
Sounds like a painful solution for a so basic need...
Thanks !
In the code snippets that you provided, it appears that your annotations are MGLPointAnnotations. If this is the case, you would need to add your MGLPointAnnotations to an MGLShapeSource using MGLShapeSource(initWithIdentifier:shapes:) and then use this shape source to create your MGLSymbolStyleLayer.
To ensure that the annotations show on top of your route, you will need to verify when each layer is being added, as layers are “baked” into the map before rendering. If you add the MGLSymbolStyleLayer responsible for the annotations after the route is added to the map, they will appear on top. If you add them before the route loads, they will appear below the route line layer. Only one MGLSymbolStyleLayer is needed.
For additional information on markers and annotations, please take a look at Mapbox’s documentation here.
Related
I'm using OpenStreet map to with our own map server with iOS. for iOS I couldn't find any third party library (free or paid) which can use with our open StreetMap server. then I decided to go with MKMapView using MKTileOverlay like below :
added a MapKit outlet to my storyboard. made a outlet connection and set delegates to self using storyboard and then here is my viewdidload method.
let urltemplate = "http://tile.openstreetmap.org/17/94621/62995.png"
let overlay = MKTileOverlay(urlTemplate: urltemplate)
overlay.canReplaceMapContent = true
mapView.add(overlay)
then the output is like below :
Any idea of what is going on. when I scroll to right of left I can only see this image. please help me with this.
Because that's exactly what you specified in your URL template.
Instead of
http://tile.openstreetmap.org/17/94621/62995.png
use
http://tile.openstreetmap.org/{z}/{x}/{y}.png
in swift I'd like to programatically re-arranger the order
of my control
by example I have a textview that is on top of another one
and I'd like to change their orders in which they appear (send to back)ect
I looked hard online but can't find an answer to this
update:
I read the article linked but those solutions don't work in swift 4.0
You have following methods to manipulate which subview is above/behind other:
bringSubviewToFront(_:)
sendSubviewToBack(_:)
removeFromSuperview()
insertSubview(_:atIndex:)
insertSubview(_:aboveSubview:)
insertSubview(_:belowSubview:)
exchangeSubviewAtIndex(_:withSubviewAtIndex:)
If you need to know current index(z position) of subview, it corresponds to its index in superview.subviews array.
Not very well versed with iOS Development. I have a very stupid question to ask!! is there a difference between Placemarks and Annotations. Ive been through some Apple Developer documents. Somewhere it was mentioned Placemarks have areaOfInterest property. Im not sure if annotations have one too.
Apart from that how do Placemarks differ from Annotations??
Thanks in Advance!! Cheers
Annotations offer a way to highlight specific coordinates on the map and provide additional information about them. You can use annotations to call out specific addresses, points of interest, and other types of destinations. When displayed on a map, annotations typically have some sort of image to identify their location and may also have a callout bubble providing information and links to more content.
For Placemarks See This Link
http://ioscreator.com/display-placemarks-with-mapkit/
From the MKPlacemark class reference:
A placemark is also an annotation and conforms to the MKAnnotation protocol, whose properties and methods include the placemark coordinate and other information. Because they are annotations, you can add them directly to the map view.
MKPlacemark inherits from CLPlacemark, which has property areasOfInterest.
A look at the class references for both classes and the protocol should clear things up.
I've been doing some testing with a cool charts framework (http://www.shinobicontrols.com/shinobicharts/) and so far I got them working on my project. They look great!
Just as I do on any tests, I implement the examples as simple as I can and then, when it's working, I move on to improve things a bit in the code-organization department.
After I felt comfortable with what I had I started refactoring the code a bit. Now I can't get the charts to draw on my view. I've tested the calls to methods with NSLog and everything is being called as expected. It is the view handling what got me spinning here. Let me explain what I had (when it was working) and what I did (to broke it).
Working scenario:
ReportsViewController
1) Imported chartLibrary.h
2) Imported chartDatasource.h
3) Created view and added with [self.view addSubview:chart];
All in the same place. All good.
What I did to organize my code:
1) Created a new class "ChartReports" (first I thought it should be NSObject but then I couldn't work with views so I changed to UIViewController)
2) Moved all imports and drawing code to this new class. Create drawing methods for each type of chart.
3) Imported "ChartReports" into "ReportsViewController"
4) Created new object (of ChartReports type) and called the new method to "drawChartX" in the exact same place as I had the whole code before (inside "ReportsViewController")
It all went south :(
The thing is that the call is correct, the method "drawChartX" is called and I NSLog from beginning to end to make sure the code is executing, but nothing is draw in the screen.
I create it and call it like this:
ChartReports *chart = [[ChartReports alloc] init];
[chart drawChartX];
When I see the code I moved (from "ReportsViewController" to "ChartReports") I notice it still says "self.view" everywhere. I thinks this is the place where the drawing is breaking. "self" originally referred to "ReportsViewController" and now it means "ChartReports".
So, after all of that: How can I tell "ChartReports" to draw on "ReportsViewController".view and not on its own view?
I tried variables and properties with no luck. Should I maybe send the name of the view as a method parameter?
I'm sorry to post such a long explanation but I'm out of ideas to try. Any general tip would be more than helpful to get back on the right path.
Thanks as usual,
Your ChartReports object should not draw on your ReportsViewController, this would break basic MVC principles. Instead, you should organize your code so that the ChartReports object creates and returns a view (i.e. the chart) that your ReportsViewController will then add to its view using addSubview.
In this way you can still encapsulate the creation of the charts in a separate object (ChartReports) but you are leaving the work of displaying the chart to your view controller, which is its job.
note: This is an expansion (and clarification) of a question I asked yesterday.
I am conducting a research project where I want to record all of the user's touches in the iPhone app. After the experiment, I will be able to download the data and process it in either Excel or (more likely) Matlab and determine how many times they clicked on certain buttons, when they clicked certain buttons, etc. To do this, I would need to know:
a) When they touched
b) Where they touched
c) Which view they touched
The first two are easy, but the third I am having trouble with. I know I can do this to get the reference to the UIView that was touched:
CGPoint locationPoint = [[touches anyObject] locationInView:self];
UIView* viewYouWishToObtain = [self hitTest:locationPoint withEvent:event];
However, that will just give me a pointer to the view, not the name of the view that was touched. I could assign each view a tag, but then every time I create a new view I would need to remember to tag it (or, alternatively, log the address of each view when initialized and log it when the view is touched). Subclassing UIView and adding an automatic tag isn't really an option since I'm creating other UIButtons and UISliders and would need to subclass those also, which doesn't seem like a very good solution.
Does anyone know of a clean, easy way to do this?
For "Which view they touched", what information do you need?
Perhaps you could use a category to add a method to UIView. This method would generate a string containing information about the view. Such as:
its type e.g. UIButton etc.
its size and position
the title of the view, if it has one (e.g. the button title)
the parent view type and title
other stuff e.g. is the view enabled, what state it is in. anything you like.
For example: "Type:UIButton Title:"Back" Rect:{3,5,40,25}" or some such string.
This is very clean and gives you quite a lot of information to be going with.
You could add a category to UIView which would then be inherited by all UIView descended objects, although I'm not sure its any more efficient than tagging. Since a category can override methods then you could override init methods for automatic tagging I suppose.
http://macdevelopertips.com/objective-c/objective-c-categories.html
I'm not sure what you mean by the "name" of the view. If you mean the view name in Interface Builder, I don't believe it includes that in the instantiated objects. You could use the Tag attribute which is included, but that's just a number and not a name.