How do I get feature data from a feature layer using the ArcGIS iOS SDK?

3848
13
Jump to solution
12-31-2017 12:24 PM
TrevorPostma
New Contributor II

Hi everyone,

I'm building an AR app using ARKit and the ArcGIS iOS SDK. I'm trying to access the data of a Feature Layer which I'm hosting on ArcGIS Online. The Feature Layer consists of images which have been submitted by participants through a Crowdsource Story Map. Specially, I'm trying to get the location and URL of each image in the Feature Layer, using the ArcGIS iOS SDK, so that I can then place/display them in the AR app based on that information.

I've been working on this problem for a few days now and have been unable to come up with a solution. I'll share what I have so far, below. Any help would be greatly appreciated!

// Connect to the ArcGIS Online portal
let portal = AGSPortal(url: URL(string: "https://organizationName.maps.arcgis.com")!, loginRequired: false)

// Provide credentials
portal.credential = AGSCredential(user: "username", password: "password")

// Get the portal item
let portalItem = AGSPortalItem(portal: portal, itemID: "xxxx836axxxx4781xxxxe4d58bcxxxx")

// Next I load the portal item
portalItem.load { [weak self] (error) -> Void in

    if let error = error {
        print("Could not load portal item due to error : \(error)")
        return
    }

    // Printing the portal item to the console produces the result I'm looking for. I'm getting the correct portal item.
    print("portal item is loaded \(portalItem)")

   // The above print statements outputs the following:
   // portal item is loaded xxxx836axxxx4781xxxxe4d58bcxxxx, Feature Service, featureLayerName, organizationName, https://organizationName.maps.arcgis.com/sharing/rest/content/items/xxxx836axxxx4781xxxxe4d58bcxxxx/...
}

// Then I try to fetch the data of the portal item. This is where I get stuck. I would have thought this grabs the data of the feature layer, which would then let me get the data for each specific feature but it doesn't fetch any data (print statement outputs "0 bytes")

portalItem.fetchData { [weak self](data, error) -> Void in


    if let error = error {
        print("Could not fetch data due to error: \(error.localizedDescription)")
        return
    }

    // Print statement is reached but output is "0 bytes"
    if let data = data {
        print(data)
    }
}

I apologize if there is a better way to post code on this forum. Again, any help would be awesome!

Trevor

0 Kudos
13 Replies
TrevorPostma
New Contributor II

Done!

TrevorPostma
New Contributor II

Hey Nick.

I have a follow-up question for you. Sorry if I should be opening a new question for this.

I'm able to access all the data I need, except I'm looking for a way to query a specific portal item to determine how many layers it has.

For example, I'm doing this: 

let table = AGSServiceFeatureTable(item: contoursItem, layerID: layerID)

Most of the portal items I'm working with have a single layer so using 0 as the layerID works in those cases. However, I have one particular portal item where I need to iterate over a number of layers and the number of layers could change in the future. I'm getting the portal item as below. Do you know how I can get all the layerIDs for that portal item?

portalItem = AGSPortalItem(portal: portal, itemID: "xxxxxItemIdxxxxx")

I was hoping I would be able to load that portal item and there would be a layersCount option but there doesn't seem to be anything like that.

Thanks again for your help.

Trevor

0 Kudos
Nicholas-Furness
Esri Regular Contributor

No problem Trevor.

The AGSPortalItem is very generic (it could be a map, or a CSV file, or even an Excel spreadsheet) so it doesn't expose type-specific info (think of it as a Content Management System item where ArcGIS Online or your own portal is the CMS but with geo-capabilities). The "type" property will tell you what it represents. In your case you happen to know it's a FeatureService, which is great.

To find out what the sublayers are, it's a bit opaque but can be done. Take the Feature Service URL (that should be accessible via portalItem.serviceURL if the portal item has loaded) and instantiate yourself an instance of AGSGeodatabaseSyncTask. Then call loadWithCompletion() on it. In the completion handler, you'll be able to read the featureServiceInfo property, which gives rich information about the FeatureService itself. Probably more than you wanted to learn about

I feel we could expose this a little better, but it's low priority as AGSGeodatabaseSyncTask is very lightweight, does the job, and most use-cases don't need it.

Let me know how that goes.

TrevorPostma
New Contributor II

That works great. Thanks again Nick!

0 Kudos