0

I'm saving images into Parse Data as an array of NSURL's. Once I have them back into my app I would like to convert them to [String] so my app can temporarily store them. Any ideas?

Here is my code....

// Saving like This....

vc.videoImageArry = defaults.setObjectForKey("vidImages)

//Retrieving like This....

vc.vidImageArray = defaults.objectForKey("vidImages") as! [NSURL]
Charles Jr
  • 8,333
  • 15
  • 53
  • 74

2 Answers2

2

Using NSData

You can convert each NSURL to NSData in order to save it

func save(urls: [NSURL]) {
    let urlsData = urls.map { $0.dataRepresentation }
    NSUserDefaults.standardUserDefaults().setObject(urlsData, forKey: "urlsData")
}

Later on you can retrieve the NSData array and convert it back to [NSURL]

func load() -> [NSURL]? {
    let retrievedData = NSUserDefaults.standardUserDefaults().arrayForKey("urlsData") as? [NSData]
    return retrievedData?.map { NSURL(dataRepresentation: $0, relativeToURL: nil) }
}

Using String

Alternatively you can save the urls as String(s)

func save(urls: [NSURL]) {
    let urlsData = urls.map { $0.absoluteString }
    NSUserDefaults.standardUserDefaults().setObject(urlsData, forKey: "urlsData")
}

func load() -> [NSURL?]? {
    let retrievedData = NSUserDefaults.standardUserDefaults().arrayForKey("urlsData") as? [String]
    return retrievedData?.map { NSURL(string: $0) }
}

As discussed in the comments below, if data is written to NSUserDefaults exclusively with the save function, we know that every element of the array is a String representing a valid NSURL.

So we can change the return type of load from [NSURL?]? to [NSURL]? using this alternate version of load.

func load() -> [NSURL]? {
    let retrievedData = NSUserDefaults.standardUserDefaults().arrayForKey("urlsData") as? [String]
    return retrievedData?.flatMap { NSURL(string: $0) }
}
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • 1
    Arguably, it should probably be `[NSURL?]?` since that's what the `NSURL(string:)` initializer returns. – nhgrif Dec 08 '15 at 00:00
  • Hmm, actually, thinking about it, the original answer was probably fine... I forgot what `flatMap` does... which makes it non-optional (stripping out any `nil` values). In theory, since we're also saving by passing in an array of valid `NSURL` objects, the `flatMap` should never remove anything... just unwrap them all... – nhgrif Dec 08 '15 at 00:03
  • Well yes, if data is written exclusively with the `save` function every element of `urlsData` should contain a `String` representing a valid `NSURL`. Should I put back the previous version? – Luca Angeletti Dec 08 '15 at 00:06
  • 1
    I think so, yes. Or maybe update your answer to include both options and a comment explaining the difference. I've upvoted this answer either way. – nhgrif Dec 08 '15 at 00:08
0

To convert from NSURL to String:

String(url)

To convert from String to NSURL:

NSURL(string: string)

Here's a fully working example that converts an array both ways:

import Cocoa
let urls = [NSURL(string: "http://www.swift.org/")!, NSURL(string: "http://www.apple.com/")!]
let strings = urls.map { String($0) }
let backToUrls = strings.map { NSURL(string: $0)! }

I believe that the above answers your specific question.

Having said that, the line for saving doesn't look right to me. You may want to look further into NSUserDefaults or ask a separate question if you're having difficulty with that line. You would need to paste some more context like lines above and below and exact error messages you're getting if any.

hashemi
  • 2,608
  • 1
  • 25
  • 31
  • I will try this. I'm saving all my strings and ints correctly. I'm not as familiar with mapping and the $ designation. Between you and appzYourLife I think I got it. If you know off any good resources for mapping that would be great. – Charles Jr Dec 08 '15 at 00:05