Swift 4.1 Encodable/Decodable Nested Array AND Dictionary - arrays

Need more help with json, any suggestions on how to lay this out?
Should players_loop be added in where I put it, etc... been going in circles for awhile.
struct:
struct LMSRequest: Decodable {
let id : Int
let method : String
let result : [String:Result]
let params : [Param]
}
struct players_loop: Decodable {
let uuid : String
let ip : String
let playerid : String
let connected : String
let firmware : String
let displaytype : String
let power : Int
let name : String
let playerindex : String
let canpoweroff : Int
let isplayer : Int
let seq_no : Int
let isplaying : Int
let modelname : String
let model : String
}
enum Result: CustomStringConvertible {
case string(String)
case int(Int)
case array([Result])
case players_loop([players_loop])
var description: String {
switch self {
case let .string(string): return string
case let .int(int): return "\(int)"
case let .players_loop(players_loop): return "\(players_loop)"
//case let .double(double): return "\(double)"
//case let .number(number): return "\(number)"
case let .array(array): return "\(array)"
}
}
}
extension Result: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode(String.self) {
self = .string(string)
} else if let int = try? container.decode(Int.self) {
self = .int(int)
//} else if let double = try? container.decode(Double.self) {
//self = .double(double)
} else {
self = .array(try container.decode([Result].self))
}
}
}
extension Result {
var stringValue: String? { if case let .string(value) = self { return value } else { return nil } }
var intValue: Int? { if case let .int(value) = self { return value } else { return nil } }
//var doubleValue: Double? { if case let .double(value) = self { return value } else { return nil } }
var arrayValue: [Result]? { if case let .array(value) = self { return value } else { return nil } }
subscript(_ index: Int) -> Result? {
return arrayValue?[index]
}
}
enum Param: CustomStringConvertible {
case string(String)
case int(Int)
case array([Param])
var description: String {
switch self {
case let .string(string): return string
case let .int(int): return "\(int)"
case let .array(array): return "\(array)"
}
}
}
extension Param: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode(String.self) {
self = .string(string)
} else if let int = try? container.decode(Int.self) {
self = .int(int)
} else {
self = .array(try container.decode([Param].self))
}
}
}
extension Param {
var stringValue: String? { if case let .string(value) = self { return value } else { return nil } }
var intValue: Int? { if case let .int(value) = self { return value } else { return nil } }
var arrayValue: [Param]? { if case let .array(value) = self { return value } else { return nil } }
subscript(_ index: Int) -> Param? {
return arrayValue?[index]
}
}
json:
let json = """
{
"id": 1,
"method": "slim.request",
"result": {
"mac": "B8:27:EB:7A:FA:4B",
"uuid": "e54389e6-7f63-4aac-aa83-a199226279f4",
"other player count": 0,
"info total artists": 6018,
"version": "7.9.1",
"info total albums": 6327,
"info total songs": 71808,
"lastscan": "1528917689",
"info total genres": 553,
"player count": 2,
"players_loop": [
{
"model": "squeezelite",
"modelname": "SqueezeLite",
"seq_no": 0,
"isplaying": 1,
"isplayer": 1,
"canpoweroff": 1,
"connected": 1,
"firmware": "v1.8.7-1052",
"playerindex": "-",
"displaytype": "none",
"power": 1,
"name": "piCorePlayer",
"playerid": "b8:27:eb:7d:09:80",
"uuid": null,
"ip": "10.2.2.21:47100"
}
]
},
"params": [
"b8:27:eb:db:6d:62",
[
"serverstatus",
"-",
1,
"tags:GPASIediqtymkovrfijnCYXRTIuwxNlasc"
]
]
}
""".data(using: .utf8)!
test:
do {
let decoder = JSONDecoder()
//decoder.keyDecodingStrategy = .convertFromSnakeCase
let lms = try decoder.decode(LMSRequest.self, from: json)
print(lms)
let inner = lms.params[1]
print(type(of: lms.params[1][0]))
print(inner[3] as Any)
} catch let jsonErr {
print("Failed to decode:", jsonErr)
}
Failed to decode: typeMismatch(Swift.Array,
Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue:
"result", intValue: nil), _DictionaryCodingKey(stringValue:
"players_loop", intValue: nil), _JSONKey(stringValue: "Index 0",
intValue: 0)], debugDescription: "Expected to decode Array but
found a dictionary instead.", underlyingError: nil))
Params section works great and is in the gist, answered here:
Swift 4.1 Codable/Decodable Nested Array
So I used Params as the starting point for "Results" --> but now trying to add in players_loop.
Thanks!!!
https://gist.github.com/sckramer/5b90d3b15eef2c19196abab2d7698e70

You have several issues. First of all, you need to be aware of the optional fields. From your attached JSON, it's clearly seen that uuid inside players_loop can be null. So this field should be optional as well in your model.
I purposefully changed the name of the struct to reflect Swift identifier convention (Type's name should start with UpperCase).
struct PlayersLoop: Decodable {
let uuid : String? // can take null
let ip : String
let playerid : String
let connected : Int
let firmware : String
let displaytype : String
let power : Int
let name : String
let playerindex : String
let canpoweroff : Int
let isplayer : Int
let seq_no : Int
let isplaying : Int
let modelname : String
let model : String
}
Then in the decodable requirement conformance of your Result enum you need to add another case for your PlayersLoop structure.
extension Result: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode(String.self) {
self = .string(string)
} else if let int = try? container.decode(Int.self) {
self = .int(int)
} else if let playersLoop = try? container.decode([PlayersLoop].self) {
self = .players_loop(playersLoop)
} else {
self = .array(try container.decode([Result].self))
}
}
}
Now, aside from your issues here, you should be more explicit when providing custom initializer for decodable requirement. As soon as you use try? you are saying to the compiler
"I don't care if this fails"
So you should be handling the error cases as well in the first place. If you did so, you wouldn't be in the position of posting this issue as a question at all.

Related

How to decode array of different data types?

I need to decode a JSON:
override func viewDidLoad() {
super.viewDidLoad()
foo()
}
struct MOCK: Codable {
var array = [AnyClass]()
enum CodingKeys: String, CodingKey {
case array = "arr"
}
}
func foo() {
let MOCK_JSON = """
{
"arr" : [
0,"my_str1",
90,"my_str2"
]
}
"""
do {
let data: Data = MOCK_JSON.data(using: .utf8)!
let manifest = try JSONDecoder.init().decode(MOCK.self, from: data)
print("\(manifest)")
} catch let error {
print("ERROR:", error)
}
}
Here I use a mock JSON, but a real structure I work with looks the same
The error I get is
Type 'ViewController.MOCK' does not conform to protocol 'Decodable'
How to decode the JSON correctly?
UPD
According to the #vadian comment I tried to use unKeyedContainer like this
struct MOCK: Decodable {
let array: [Any]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
array = try container.decode([Any].self)
}
}
But still I get an error in the last line
No exact matches in call to instance method 'decode'
Any is not supported in Codable, nor AnyObject nor AnyClass
A possible solution is an unkeyedContainer and an enum with associated values
let mockJSON =
"""
{
"arr" : [
0,"my_str1",
90,"my_str2"
]
}
"""
enum MockType {
case int(Int), string(String)
}
struct Mock: Decodable {
var values = [MockType]()
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
while !container.isAtEnd {
do {
let intValue = try container.decode(Int.self)
values.append(.int(intValue))
} catch DecodingError.typeMismatch {
let stringValue = try container.decode(String.self)
values.append(.string(stringValue))
}
}
}
}
let data = Data(mockJSON.utf8)
do {
let decoder = JSONDecoder()
let result = try decoder.decode([String:Mock].self, from: data)
print(result["arr"]!.values)
} catch {
print(error)
}

Is there any way we can debug to discover "Type of expression is ambiguous without more context" error?

Building a JSONDecoder to get weather data to use in a widget, I'm facing this issue (Type of expression is ambiguous without more context) which looks impossible to find on Xcode. Looking into the code below, can you see what could possibly be wrong ? I already take a look into the web but this error is general and can appear on many situations without detail. I'm now using JSONDecoder instead of serialization as suggested into the comments but same issue. Any help will be really appreciated.
import Foundation
import WidgetKit
import SwiftUI
var locationManager = LocationManager()
var userLatitude: String {
return "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
}
var userLongitude: String {
return "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
}
// MARK: - WidgetData
struct WidgetData {
let temperature: Double
let feels: Double
let humidity: Int
let uvi: Double
let conditionId: Int
var conditionName: String {
switch conditionId {
case 200...232:
return "cloud.bolt.rain"
case 300...321:
return "cloud.drizzle"
case 500...531:
return "cloud.rain"
case 600...622:
return "cloud.snow"
case 701...780:
return "cloud.fog"
case 781:
return "tornado"
case 800:
return "sun.max"
case 801...804:
return "cloud"
default:
return "cloud"
}
}
}
// MARK: - WeatherData
struct WeatherData: Decodable {
let current: Current
}
// MARK: - Current
struct Current: Decodable {
let temp, feels_like: Double
let humidity, uvi: Double
let weather: [Weather]
}
// MARK: - Weather
struct Weather: Decodable {
let id: Int
}
struct WeatherLoader {
func performRequest(with urlString: String) {
if let url = URL(string: "https://api.openweathermap.org/data/2.5/onecall?exclude=minutely,hourly&units=metric&lat=\(userLatitude)&lon=\(userLongitude)") {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (weatherData, response, error) in
if error != nil {
print(error!)
return
}
}
task.resume()
}
}
func parseJSON(_ weatherData: Data) -> WeatherData? {
let decoder = JSONDecoder()
do {
let decodedData = try? decoder.decode(WeatherData.self, from: weatherData)
//Current Weather
let temp = decodedData?.current.temp
let feels_like = decodedData?.current.feels_like
let humidity = decodedData?.current.humidity
let uvi = decodedData?.current.uvi
let id = decodedData?.current.weather[0].id
let widgetData = WidgetData(temp: temp, feels_like: feels_like, humidity: humidity, uvi: uvi, conditionId: id)
return widgetData
} catch {
print(error)
return nil
}
}
}
The error points to the "W" into WidgetData(temp: ...

How can I remove whole dictionary in nested array at specific index after filter some specific value

I have API response with nested array . But I can't understand how can I remove whole Dict by filtering the value .
This is the response screenshot
https://imgur.com/XIDyfYX
here is the json Resonse :- https://del.dog/lofavofogo.json
I have tried this but I don't know how to get filter nested value and remove whole dict at specific index
How to remove pairs from dictionary at specific index - Swift?
I want to remove the dict where section name are "NA"
Here is the code :-
Model Class For API Response :-
class filterclass: NSObject {
var classesID : String?
var classname : String?
var section = [filterSections]()
init(json: [String: Any]) {
if let classname = json["class"] as? String {
self.classname = classname
}
if let classesID = json["classesID"] as? String {
self.classesID = classesID
}
print("classname",classname)
if let evUserGoing = json["classsection"] as? [[String: Any]] {
if self.section.count > 0
{
self.section.removeAll()
}
for evUser in evUserGoing {
// print("evUser",evUser)
let userGoing = filterSections(json: evUser)
self.section.append(userGoing)
}
for sec in section {
let section = sec.secctionname
let setionID = sec.sectionID
}
}
}
}
class filterSections: NSObject {
var sectionID : String?
var secctionname : String?
var isSelctedSection : Bool = false
init(json: [String: Any]) {
if let sectionID = json["sectionID"] as? String {
self.sectionID = sectionID
}
if let secctionname = json["section"] as? String {
self.secctionname = secctionname
}
print("sectioname",secctionname)
}
}
API POST Method TO hit API :-
func getClassSectionAPI() {
if ReusableClass.sharedInstance.isNetworkAvailable() == true
{
ReusableClass.sharedInstance.showActivityIndicator()
let UUid = LoginUserInfo.sharedInstance.uuid!
let dictionary = ["uuid":UUid,"device_id":devicetoken,"school_id":LoginUserInfo.sharedInstance.schoolId!, "user_type":LoginUserInfo.sharedInstance.usertype!]
print(dictionary)
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dictionary) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
// print(jsonString)
let cipher:String = CryptoHelper.encrypt(input:jsonString)!;
let NewEncryption = "data=\(cipher)"
print(NewEncryption)
let hmac_md5 = cipher.hmac(algorithm: .sha512, key: kHMACKey)
print("hmac",hmac_md5)
UserDefaults.standard.set(hmac_md5, forKey: Headerkey)
Singleton.sharedInstance.getWebservicesverify(params: NewEncryption, Methodname: KFilterClassSection, data: Stringnil)
{ (result) in
DispatchQueue.main.async {
ReusableClass.sharedInstance.hideActivityIndicator()
}
if result != nil
{
do {
let jsonData = try JSONSerialization.data(withJSONObject: result)
if let json = String(data: jsonData, encoding: .utf8) {
let Dict = function.convertToDictionary(text: json)! as NSDictionary
guard let data = Dict[KData] as? String
else
{
return
}
self.baseDict = data
}
}
catch {
}
guard let output = CryptoHelper.decrypt(input:self.baseDict)
else
{
return
}
print(output)
let mainDict = function.convertToDictionary(text: output)! as NSDictionary
let status = mainDict[KStatus] as! NSInteger
if(status == 1)
{
DispatchQueue.main.async {
print("Main dict",mainDict)
guard let messageArray = mainDict["data"] as? [[String: Any]] else{
return
}
if self.arrayClasSection.count > 0
{
self.arrayClasSection.removeAll()
}
print("Main dict",messageArray)
for arr in messageArray {
let obj = filterclass.init(json: arr)
if let index = self.arryFilterTemperary.index(where: { $0.classname == obj.classname }) {
// let filtered = self.arryFilterTemperary.filter { $0.classname == "NA" }
obj.section = self.arryFilterTemperary[index].section
self.arrayClasSection.append(obj)
for sec in self.arryFilterTemperary[index].section {
let section = sec.sectionID
let sectionName = sec.secctionname
self.NASection = sec.secctionname!
print(self.NASection)
self.selectedNASectionID = sec.sectionID!
// let test = self.arryFilterTemperary[index].section.filter { !$0.value.contains("") }
// print(test)
}
}
else
{
self.arrayClasSection.append(obj)
}
}
ReusableClass.sharedInstance.hideActivityIndicator()
self.tableFilter.reloadData()
}
}
I want to append the data to array but before appending I want to
filter that "NA" value dict from the array
Since this is your first question I go to some greater length in answering it than usual. Playgrounds are an exceptional way to demonstrate your problem, so you should always try to compose your questions in a form of one. I will post my answer directly from the Playground I have done.
With that out of the way lets get to the question. Your main problem seems to be that you tried an ill fated JSONSerialization "shortcutt" route. This looks cheap from the outside, but working with the unavoidable optionality of a [String:Any] comes at a high cost in a language like Swift. The way to go is the brilliant Codable protocol, at least in my opinion. Once you define your data structure properly Xcode has so much more possibilities to guide you through the APIs that writing your filter code becomes a piece of cake.
Enough of the ranting, let's get to the pizza.
import UIKit
let dataStr = """
{
"status":1,
"message":"Class and sections list",
"data":[
{
"classsection":[
{
"section":"A",
"sectionID":"1",
"classesID":"1"
},
{
"section":"B",
"sectionID":"3",
"classesID":"1"
}
],
"class":"First",
"classesID":"1"
},
{
"classsection":[
{
"section":"A",
"sectionID":"2",
"classesID":"2"
},
{
"section":"B",
"sectionID":"7",
"classesID":"2"
}
],
"class":"Second",
"classesID":"2"
},
{
"classsection":[
{
"section":"A",
"sectionID":"20",
"classesID":"15"
}
],
"class":"Third",
"classesID":"15"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"33",
"classesID":"22"
}
],
"class":"Pre Nursery",
"classesID":"22"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"34",
"classesID":"23"
},
{
"section":"A",
"sectionID":"35",
"classesID":"23"
},
{
"section":"B",
"sectionID":"36",
"classesID":"23"
},
{
"section":"C",
"sectionID":"37",
"classesID":"23"
}
],
"class":"Fourth four",
"classesID":"23"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"38",
"classesID":"24"
}
],
"class":"Fifth",
"classesID":"24"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"39",
"classesID":"25"
}
],
"class":"sixth 6th",
"classesID":"25"
}
]
}
"""
struct Section: Codable {
let section, sectionId, classesId: String
enum CodingKeys: String, CodingKey {
case sectionId = "sectionID"
case classesId = "classesID"
case section
}
}
struct Class1: Codable {
let classsection: [Section]
let clazz, classesId: String
private enum CodingKeys: String, CodingKey {
case classsection
case clazz = "class"
case classesId = "classesID"
}
}
struct Response: Codable {
let status: Int
let message: String
let data: [Class1]
func filterSections(notMatching filterVal: String) -> Response {
let filteredData = data.map { (clazz) -> Class1 in
let filteredSections = clazz.classsection.filter { (sect) -> Bool in
sect.section != filterVal
}
return Class1(classsection: filteredSections, clazz: clazz.clazz, classesId: clazz.classesId)
}
return Response(status: status, message: message, data: filteredData)
}
}
let jsonData = dataStr.data(using:.utf8)!
do {
let res = try JSONDecoder().decode(Response.self, from: jsonData)
let filteredResponse = res.filterSections(notMatching: "NA")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
print(String(data:try encoder.encode(filteredResponse), encoding: .utf8)!)
} catch {
print(error)
}
As you can see your data structure is easily defined and the filtering code is really easy to understand once you wrap your head around the lambdas (which you should). The playground will output nicely formatted JSON as an answer, this way it is easy to check that your code does the right thing without all the messy parts of asynchronous communication (which are still nicely done in Swift).
Here's my last tipp of the day: Always try to isolate your problem as much as possible if you post a question on StackOverflow. I think your question carried too much legacy, you should whittle it down for the next one. This will improve your chances for a quick answer.

How can I convert Json into 2D array?

If I got a Json like this:
{ "i": [ "0", [123]] }
Is there any possible way can decode the 2D array above?
class ModelA: Codable{
var i: [String]?
var temp: [Any] = []
enum CodingKeys: String, CodingKey {
case i = "i"
}
required init(from decoder: Decoder) throws {
let value = try decoder.container(keyedBy: CodingKeys.self)
temp = try value.decode([Any].self, forKey: .i)
}
}
Usage:
public func printJsonData(){
let jsonData: Data = """
{
"i": [ "0", [123]]
}
""".data(using: .utf8)!
if let model = try? JSONDecoder().decode(ModelA.self, from: jsonData){
print(model.temp)
}else{
print("no data")
}
}
I have tried that an array [Any] works successfully here,
but can't find any method to convert in 2D array.
If someone knows how to solve this problem, or knows this is impossible in Swift4.2, please tell me. Thanks!
If you know the possible data types for the array value, perhaps you can try using the possible value (in this case String and [Int]) represented by enum instead of Any.
e.g:
enum ArrayIntOrString: Decodable {
case string(String)
case arrayOfInt([Int])
init(from decoder: Decoder) throws {
if let string = try? decoder.singleValueContainer().decode(String.self) {
self = .string(string)
return
}
if let arrayOfInt = try? decoder.singleValueContainer().decode([Int].self) {
self = .arrayOfInt(arrayOfInt)
return
}
throw ArrayIntOrStringError.arrayIntOrStringNotFound
}
enum ArrayIntOrStringError: Error {
case arrayIntOrStringNotFound
}
}
And declare it in your model:
class ModelA: Decodable {
var i: [ArrayIntOrString]?
enum CodingKeys: String, CodingKey {
case i = "i"
}
}
usage
public func printJsonData() {
let jsonData: Data = """
{
"i": [ "0", [123]]
}
""".data(using: .utf8)!
do {
let model = try JSONDecoder().decode(ModelA.self, from: jsonData)
print(model.i)
} catch let err {
print("no data \(err)")
}
}

Swift - json nested array not returning value

I am trying to grab the array from "imports" from the JSON file but the array is returning encoded.
[ServerName.JSONNodeValue, ServerName.JSONNodeValue, ServerName.JSONNodeValue, ServerName.JSONNodeValue, ServerName.JSONNodeValue, ServerName.JSONNodeValue]
I know the data can be seen as if I print the value of the data in the JSONNode file, it comes up as
https://servername.com/storage/sessions/00167/imports
(
"movie1.mov",
"movie3.mov",
"movie2.mov",
"._movie1.mov",
"._movie2.mov",
"._movie3.mov"
)
This isn't my code and the reason why I am struggling as I am still pretty new at swift.
My JSON file looks similar to this.
{
"id": 135
"name": Test
"angles" [
{
"id": 35,
"name": "test",
"mp4": "http:/0.0.0:3000/storage/seesion/00138/url.mp4"
}
]
"imports" [
movie1.mp4,
movie2.mp4,
movie3.mp4
]
}
Swift Code - Session File
struct Session {
var id: Int
var name: String
var angles: [Angle] = []
var imports: [Any]
extension Session {
init(fromDict dict: [String: AnyObject]){
let node = JSONNodeValue(dict)
let sessionId = node["id"].int ?? 0
self.id = sessionId
self.name = node["name"].string ?? "???"
print(name)
self.imports = node["imports"].arrayOrEmpty
self.angles = node["angles"].arrayOrEmpty.map { angleDict in
Angle(fromDict: angleDict.object!)
}
JSONnode file that handles the JSON
protocol JSONNode {
subscript(key: String) -> JSONNode { get }
var int: Int? { get }
var double: Double? { get }
var string: String? { get }
var bool: Bool? { get }
var date: Date? { get }
var array: [JSONNode]? { get }
var arrayOrEmpty: [JSONNode] { get }
var object: [String: Any]? { get }
var objectOrEmpty: [String: Any] { get }
}
class JSONNodeValue : JSONNode {
static func parse (_ data: Data) -> JSONNode {
if let root = try? JSONSerialization.jsonObject(with: data) {
return JSONNodeValue(root)
} else {
return JSONNodeNone.instance
}
}
var value: Any
init(_ value: Any) {
self.value = value
print(value) // SHOWS THE DATA I NEED
}
subscript(key: String) -> JSONNode {
if let object = value as? [String: Any], let subvalue = object[key] {
return JSONNodeValue(subvalue)
} else {
return JSONNodeNone.instance
}
}
var int: Int? {
return value as? Int
}
var double: Double? {
return value as? Double
}
var string: String? {
return value as? String
}
var bool: Bool? {
return value as? Bool
}
var date: Date? {
if let formatted = string {
return Date.fromIso8601(formatted)
} else {
return nil
}
}
var array: [JSONNode]? {
if let array = value as? [Any] {
return array.map { JSONNodeValue($0) }
} else {
return nil
}
}
var arrayOrEmpty: [JSONNode] {
return array ?? []
}
var object: [String: Any]? {
return value as? [String: Any]
}
var objectOrEmpty: [String : Any] {
return object ?? [:]
}
}
Could someone point me in the right direction or to other answered questions that could help me solve this? Thanks
The struct looks good, but remove the = [] after [Angle], but you should use Codable protocol to parse the JSON like so:
struct Session: Codable {
var id: Int
var name: String
var angles: [Angle]
var imports_dir_contents: [Any]
then create another struct to get the Angle
struct Angle: Codable
let id: Int
let name: String
let mp4: String
Then you want to parse using the Codable protocol method by passing in the data retrieved from the networking call.
do {
let newJSONDecoder = JSONDecoder()
let session = try newJSONDecoder.decode(Session.self, from:data)
let anglesArray = session.angles // or use whatever array property you want
} catch {
print("error while parsing:\(error)")
}
I solved what I was trying to achieve by adding a new a variable in the JSNODE file which then gave me ["movie1.mov", "movie3.mov", "movie2.mov", "._movie1.mov", "._movie2.mov", "._movie3.mov"]
var arrayList: [String]? {
return value as? [String]
}
Thanks for the help though.

Resources