7 Answers
7

First of all never load data synchronously from a remote URL, use always asynchronous methods like URLSession.

'Any' has no subscript members

occurs because the compiler has no idea of what type the intermediate objects are (for example currently in ["currently"]!["temperature"]) and since you are using Foundation collection types like NSDictionary the compiler has no idea at all about the type.

Additionally in Swift 3 it's required to inform the compiler about the type of all subscripted objects.

You have to cast the result of the JSON serialization to the actual type.

Many (it seems all) tutorials suggest .mutableContainers or .mutableLeaves options which is completely nonsense in Swift. The two options are legacy Objective-C options to assign the result to NSMutable... objects. In Swift any variable is mutable by default and passing any of those options and assigning the result to a let constant has no effect at all. Further most of the implementations are never mutating the deserialized JSON anyway.

The only (rare) option which is useful in Swift is .allowFragments which is required if if the JSON root object could be a value type(String, Number, Bool or null) rather than one of the collection types (array or dictionary). But normally omit the options parameter which means No options.

In the rare case that the JSON is simply one of the value types – rather than a collection type – you have to pass the .allowFragments option and cast the result to the appropriate value type for example

This is very helpful. I'm just curious why the above code does not show visible output when it's run in a playground.
– user2563039Sep 10 '16 at 8:37

As mentioned above you need to cast the ambiguous result of dict!["currently"]! to a dictionary that the compiler can safely infer the subsequent key subscription.
– vadianSep 10 '16 at 9:18

1

The Apple article is pretty cool, but I couldn't get it to run with swift 3 for some reason. It complains about Type [String : Any]? has no subscript members. There was some other issues with it too, but I was able to get around it. Anyone has an example of their code that actually runs?
– ShadesNov 23 '16 at 0:00

A big change that happened with Xcode 8 Beta 6 for Swift 3 was that id now imports as Any rather than AnyObject.

This means that parsedData is returned as a dictionary of most likely with the type [Any:Any]. Without using a debugger I could not tell you exactly what your cast to NSDictionary will do but the error you are seeing is because dict!["currently"]! has type Any

So, how do you solve this? From the way you've referenced it, I assume dict!["currently"]! is a dictionary and so you have many options:

It also generates dependency-free marshaling code to coax the return value of JSONSerialization.jsonObject into a Forecast, including a convenience constructor that takes a JSON string so you can quickly parse a strongly typed Forecast value and access its fields:

Marco, what would be best way to add this function in project? in any contorller or model?
– KamalPanhwarJan 24 '17 at 19:38

hey, you just add the first method func loadingJSON(...) in an extra swift file or class. After that you are able to call this from every controller in your project
– Marco WeberFeb 7 '17 at 11:32

i did try it , but i love the idea of demonstrating a full solution and also how to use it including the helper method isConnectedToNetwork() it me the idea of how to implement it probably in good code
– Amr AngryFeb 16 '17 at 7:51

so i just used a new swift-file (left klick on your project tree, new file ..., swift file) and called it jsonhelper.swift. in this file you place the first code, loadingJSON() and isConnectedToNetwork(). after that you can use this two functions in every part of your project. for example in a loginVC, as an action of the login button you're able to use the second code, obviously you have to change the domain, the post string and the paseJson values (parseJSON["loginSuccessfull"]) so they match to your php file
– Marco WeberFeb 17 '17 at 9:26

The Problem is with the API interaction method.The JSON parsing is changed only in Syntax. The main problem is with the way of fetching data. What you are using is a synchronous way of getting data. This doesn't work in every case. What you should be using is an asynchronous way to Fetch data. In this way, you have to request data through the API and wait for it to respond with data. You can achieve this with URL session and third-party libraries like Alamofire. Below is the Code for URL Session method.

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).