Reputation: 1
I'm having troubles with this error.
Would you tell me how to fix this code to workout?
Any help will be appreciated.
//This is JSON data.
{
"boxOfficeResult":{
"boxofficeType":"일별 박스오피스",
"showRange":"20161020~20161020",
"dailyBoxOfficeList":[
{
"rnum":"1",
"rank":"1",
"rankInten":"0",
"rankOldAndNew":"OLD",
"movieCd":"20153444",
"movieNm":"럭키",
"openDt":"2016-10-13",
"salesAmt":"1452501900",
"salesShare":"60.2",
"salesInten":"-85908900",
"salesChange":"-10",
"salesAcc":"23329189948",
"audiCnt":"193801",
"audiInten":"-11203",
"audiChange":"-10",
"audiAcc":"2879481",
"scrnCnt":"968",
"showCnt":"4961"
}, ...
//This is code.
var list = Array<MovieVO>()
override func viewDidLoad() {
let apiURI = NSURL(string: "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=a7497a5e700fdff2f3fd468b604d9d18&targetDt=20161020")
let apidata : NSData? = NSData(contentsOf: apiURI! as URL)
NSLog("result = %@", NSString(data: apidata! as Data, encoding: String.Encoding.utf8.rawValue)!)
do {
let apiDictionary = try JSONSerialization.jsonObject(with: apidata! as Data, options: []) as! NSDictionary
let boxOfficeResult = apiDictionary["boxOfficeResult"] as! NSDictionary
let dailyBoxOfficeList = boxOfficeResult["dailyBoxOfficeList"] as! NSArray
var mvo : MovieVO
for row in dailyBoxOfficeList {
mvo = MovieVO()
mvo.rank = row["rank"] as? String // error occur
mvo.movieNm = row["movieNm"] as? String
mvo.openDt = row["openDt"] as? String
mvo.audiCnt = row["audiCnt"] as? String
self.list.append(mvo)
}
} catch {
}
}
Upvotes: 0
Views: 266
Reputation: 47906
The shortest quick fix would be changing this line:
let dailyBoxOfficeList = boxOfficeResult["dailyBoxOfficeList"] as! NSArray
to something like this:
let dailyBoxOfficeList = boxOfficeResult["dailyBoxOfficeList"] as! [[String: Any]]
In Swift 3, the Element type of NSArray
has become Any
, and you cannot apply any methods (including subscript) to Any
. In your code, row
's type is inferred as Any
and you cannot apply subscript to row
.
A little more ahead to make your code more Swifty and safer:
enum MyError: Error {
case badURL
case notDictionary
case invalidBoxOfficeResult
case invalidDailyBoxOfficeList
}
override func viewDidLoad() {
do {
//Use `URL` rather than `NSURL`
guard let apiURI = URL(string: "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=a7497a5e700fdff2f3fd468b604d9d18&targetDt=20161020") else {
throw MyError.badURL
}
//Use `Data` rather than `NSData`
//Avoid using forced unwrapping
let apidata = try Data(contentsOf: apiURI)
//Use `String` rather than `NSString`
NSLog("result = %@", String(data: apidata, encoding: .utf8)!)
//Cast the resutl of type `Any` as soon as possible
guard let apiDictionary = try JSONSerialization.jsonObject(with: apidata) as? [String: Any] else {
throw MyError.notDictionary
}
//Cast the resutl of type `Any` as soon as possible
guard let boxOfficeResult = apiDictionary["boxOfficeResult"] as? [String: Any] else {
throw MyError.invalidBoxOfficeResult
}
//Cast the resutl of type `Any` as soon as possible
guard let dailyBoxOfficeList = boxOfficeResult["dailyBoxOfficeList"] as? [[String: String]] else {
throw MyError.invalidDailyBoxOfficeList
}
for row in dailyBoxOfficeList {
var mvo = MovieVO() //<- Assuming `MovieVO` is a struct, use `let` if it is a class
mvo.rank = row["rank"]
mvo.movieNm = row["movieNm"]
mvo.openDt = row["openDt"]
mvo.audiCnt = row["audiCnt"]
self.list.append(mvo)
}
} catch {
print(error) //<- You should not ignore errors
}
}
And a little more...
Data(contentsOf:)
(or NSData(contentsOf:)
) may consume indefinite time and blocks the main thread until the whole data is received. If you are writing an app for App Store, such an app has risk to be rejected. Try loading the contents in a background thread.
Upvotes: 1