I'm trying to code in a basic ArcGIS workflow into my iOS project. I am new to this platform and can use some pointers. My workflow is as follows.
1.) Create mapView displaying satellite (world style) map.
2.) Add a public webMap from my user account on ArcGIS Online as an overlay/layer on the satellite map.
What I've tried
//.h
#import <ArcGIS/ArcGIS.h>
#interface ViewController : UIViewController <AGSWebMapDelegate>
#property (strong, nonatomic) IBOutlet AGSMapView *mapView;
//.m
// Add basemap
NSURL* url = [NSURL URLWithString:#"http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"];
AGSTiledMapServiceLayer *tiledLayer = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:url];
[self.mapView addMapLayer:tiledLayer withName:#"Basemap Tiled Layer"];
//If I run this part alone, I'll get the satellite map.
AGSWebMap* webmap = [[AGSWebMap alloc] initWithItemId:#"bb9b8c172e8142f995526bf658078f54" credential:nil];
webmap.delegate = self;
[webmap openIntoMapView:self.mapView];
//When I add this webMap code and run the project, I get a blank white screen.
//.m cont.
- (void)mapViewDidLoad:(AGSMapView *) mapView {
NSLog(#"mapView didLoad");
}
- (void) webMapDidLoad:(AGSWebMap*) webMap {
NSLog(#"webmap added successfully");
}
//Neither of these logs get called.
Questions.
1.) Is it right to use AGSTiledMapServiceLayer as my basemap? Also, is it right to use AGSWebMap for my ArcGIS Online map?
2.) My goal is to be able to add and remove multiple layers to and from a satellite basemap, one at a time. Am I on the right track?
I'm currently using MapBox to achieve this but I'm starting to experiment with ArcGIS SDK and it's features.
Thanks in advance.
You are almost there. Make sure all 3 of these items are in the proper pace.
From the discussion from https://developers.arcgis.com/ios/objective-c/guide/viewing-web-map.htm.
Make these calls where you made them before (presumably viewDidLoad)
instantiate an AGSWebMap object // 1
An instance of your class must then be set as the web map's delegate // 2
// 1
AGSWebMap* webmap = [[AGSWebMap alloc] initWithItemId:#"bb9b8c172e8142f995526bf658078f54" credential:nil];
// 2
webmap.delegate = self;
Then update the handler webMapDidLoad() // 3
// open the web map into a map view in the delegate handler
- (void) webMapDidLoad:(AGSWebMap*) webMap {
// 3
[webmap openIntoMapView:self.mapView];
NSLog(#"webmap added successfully");
}
Related
I am working on google map iOS sdk. Here I create multiple markers in separate location co-ordinates.
Now I need to add identifier such like TAG for all markers to perform action for particular marker.
If TAG or some other identifier option is not available in google map iOS sdk, please suggest me how to archive it.
Thanks in Advance.
What I do is that I simply inherit the GMSMarker and add whatever data I need to it like this, I guess this is the best and easiest option you have.
#interface ATGoogleMapsSelectiveMarker : GMSMarker
#property (nonatomic) int markerID;
#property (nonatomic) int order;
#property (strong, nonatomic) NSObject* referenceObject;
#property (nonatomic) BOOL selected;
#end
EDIT:
I thought it is clear but I'll continue on how to get the data... When you create your markers and add them to the map, you create ATGoogleMapsSelectiveMarker and add it to the map after you fill it with everything you need, then you register any class you want as a delegate which implements GMSMapViewDelegate and you implement this method
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
// Here you are sure that your marker object is of type ATGoogleMapsSelectiveMarker but it won't harm to double check
if ([marker isKindOfClass:[ATGoogleMapsSelectiveMarker class]]) {
ATGoogleMapsSelectiveMarker* parsedMarker = (ATGoogleMapsSelectiveMarker*)marker;
NSLog(#"%d", parsedMarker.markerId);
}
return YES;
}
Swift solution :
You can add identifier or any thing to a marker by setting a value for a key for the marker:
marker.setValue("20", forKey: "id")
and you can get it later using :
marker.value(forKey: "id")
Or
My way to do it is by create an extension for the GMSMarker and using the userData property to make the GMSMarker fits my need, for me I want to add each marker with instance of Branch class (map with markers for branches of some company) and this is the way that I did:
extension GMSMarker {
var branch: Branch {
set(branch) {
self.userData = branch
}
get {
return self.userData as! Branch
}
}
}
so when I set the marker property I set it like this:
marker.branch = someBranch
Isn't that clearer and more readable than marker.userData = someBranch ??
I am working on an app using RTMP/RTSP links to broadcast/play live audio/video.As iOS devices support HTTP , but my requirement is to play RTMP/RTSP Links.
I want to create my custom player using FFMpeg framework.I have searched over internet , ried many solutions but did not find any solution.
there's a Xcode project based on ffmpeg. It's possible to play RTSP links. Have a look at it:
https://github.com/durfu/DFURTSPPlayer
If you want to know more about RTSP, I can highly recommend you the following link:
https://www.rfc-editor.org/rfc/rfc2326
Here is an overview of current solutions for rtsp on iOS:
https://gist.github.com/oc2pcoj/e55795550984d205d109
I use ijkplayer at current project for playing video stream from IP-cam. It works fine.
To play an rtsp stream on iOS using ffmpeg I recommend https://github.com/teocci/RTSP-Client-iOS
For reference, here is an Objective-C interface to RTSP-Client-iOS/FFMpegDecoder/RTSPPlayer.m based on RTSP-Client-iOS/RtspClient/ViewController.swift;
//
// ViewController.h
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageViewInstance1;
#end
//
// ViewController.m
//
#import "ViewController.h"
#import "RTSPPlayer.h"
RTSPPlayer *rtspPlayer;
int frameIndex;
NSTimer *timerRefresh;
#define CAMERA_RTSP_ADDRESS "rtsp://..."
#define CAMERA_FPS (30.0)
#define TIMER_INTERVAL_SECONDS (1.0/CAMERA_FPS)
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString* address = #CAMERA_RTSP_ADDRESS;
rtspPlayer = [[RTSPPlayer alloc] initWithVideo:address usesTcp:false];
rtspPlayer.outputWidth = 640;
rtspPlayer.outputHeight = 480;
[rtspPlayer seekTime:0.0];
timerRefresh = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL_SECONDS target:self selector:#selector(run:) userInfo:nil repeats:YES];
}
-(void) run:(NSTimer *) timer
{
if(![rtspPlayer stepFrame])
{
[timerRefresh invalidate];
[rtspPlayer closeAudio];
}
UIImage* uiImage = rtspPlayer.currentImage;
_imageViewInstance1.image = uiImage;
frameIndex++;
}
#end
To create an ImageView object in the user interface (_imageViewInstance1);
Project Navigator (left pane) - [INSERTAPPLICATIONNAME]
Open Main.storyboard
Select View Controller Scene - View Controller - View
Select the Library button (top right: circle with inside square)
Search for 'Image View'
Drag and drop a new View Image Object into View Controller Scene - View Controller - View (adjacent 'Safe Area')
Create an outlet connection for the new Image View object
Select the Assistant Editor button (top right: two intersecting circles)
Select file ViewController.h in the Project Navigator
If necessary hide the left and right panes to create more space (top right: blue box with left vertical bar, blue box with right vertical bar)
hold the Ctrl key and drag the new image view object to the ViewController.h file (immediately below #interface ViewController: UIViewController) - name the object reference as imageViewInstance1
I have two scenes that I made in SpriteBuilder, one is Shop and the other is UpgradesNew. Shop is a CCNode layer and UpgradesNew is a CCNode layer. I have two CCScrollViews in the MainScene that load Shop and UpgradesNew respectively.
When one button in Shop is tapped, the label in UpgradesNew should change colors. I have been trying to implement this using delegates but it's not working.
Here's what I did...
In shop.h I set the protocol:
#protocol changeColorProtocol <NSObject>
#required
-(void)changeColor;
#end
Then I set the id
#property (nonatomic, retain) id <changeColorProtocol> delegate;
Here is the button that when clicked, should use changeColor. This is in shop.m
-(void) buyDiggerShibe {
[self.delegate changeColor];
[self didLoadFromCCB];
}
Now in UpgradesNew.h I made it adopt the protocol like this
#interface UpgradesNew : CCNode <changeColorProtocol>
And in UpgradesNew.m
I set delegate to self in ViewDidLoad.
Shop *shop = [[Shop alloc]init];
shop.delegate = self;
.
-(void)changeColor {
if (hasDigger == YES) {
shovelRequires.color = [CCColor greenColor];
NSLog(#"HEY HEY HEY");
}
}
I probably have parts of the delegate placed in the wrong area because I was trying to switch them around when it wasn't working, I'm not sure where they are supposed to go. I've watched multiple delegate tutorials and it just seems overly complicated, at least with what I am trying to do.
Any ideas?
EDIT:
Tried this.
I created a property in UpgradesNew
#property (strong, nonatomic) Shop *shop;
Then I synthesized it in the implementation and allocated it like this in didLoadFromCCB, instead of creating a new object:
self.shop = [[Shop alloc]init];
shop.delegate = self;
EDIT: This is how I am creating objects.
Drag a label into a layer. Identify it then define it in header as CCLabelTTF *label; That's it, thats all I do to create any object on the layer.
To create a layer like Shop or UpgradesNew, I hit New -> File -> Layer. That creates a new CCNode. Then I set the class of the CCNode, as shown in the picture the CCNode that is highlighted has a class of MainScene. If I want to establish a #property to that CCNode I just type the name in the box right below custom class and set it as doc root var, and then put it in the header as CCNode *MainScene. I don't do anything other than that.
I don't know anything about SpriteBuilder, so it's a bit hard to address your question. You might want to add SpriteBuilder to the title of your post so people who use that framework are likely to read it.
You need to explain how the 2 "CCNode layer"s are created, and how you link them together. In order for one object to have another object as a delegate, the delegate property has to be set somewhere. Where is that setup being done? Have you set a breakpoint at the line
[self.delegate changeColor];
To make sure that self.delegate is not nil?
Have you set a breakpoint in your changeColor method, or added a log statement, to see if it's being called? My guess is that self.delegate is nil, so the messages is being dropped on the floor (it's legal to send messages to nil in Objective-C. It just doesn't do anything.)
I want to add Google Maps in a UIView that I added in MainStoryboard (Because I want to control maps place and size).
The map shows correctly but does not listen to the events. I have added <GMSMapViewDelegate> protocol in ViewController.h and also the methods in ViewController.m and when i set the UIViewController view as the map view (Googles example self.view = GMSMapView) everything works fine.
Thanks in Advance!
You have to set your ViewController as a GMSMapView delegate.
in viewDidLoad:
mapView.delegate = self;
I know it's easy in the java version of Google Maps but I can't figure out how to get the info window to close in the objective C version of the SDK.
I'm using this method:
-(void) mapView:(GMSMapView *)mapView
didTapInfoWindowOfMarker:(id<GMSMarker>)marker {
sharedGlobal.shouldShowPlayer = YES;
/* adds the path to the map by decoding google's encoded string */
[self addPath: sharedGlobal.encodedPathString];
}
And want to add a line to close the infowindow associated with marker.
I think you can use this:
mapView.selectedMarker = nil;
The comments on the selectedMarker property in GMSMapView.h say this:
/**
* The marker that is selected. Setting this property selects a particular
* marker, showing an info window on it. If this property is non-nil, setting
* it to nil deselects the marker, hiding the info window. This property is
* observable using KVO.
*/
#property (nonatomic, strong) id<GMSMarker> selectedMarker;
SWIFT
mapView.selectedMarker?.title = nil