0

My app uses data from 11 JSON files (size between 70 kb and 200 kb each). During the same user session, the user might access to data from any of the 11 files, at different times. So obviously I want to download these files only once and I want to be able to access their content anytime during the same session. When the app launches I download the files immediately, then allow the user to navigate anywhere (see code below for 1 file but it would be the same for the others) At the moment, I am storing the content of each file in a static array of Strings, so that it is accessible from any other class.

Questions: 1. is it dangerous for performance memory wise ? 2. can the array variable be emptied or destroyed or lost in any way during a user session (for example if the user presses the Home button and does activities requiring lots of memory with his phone, then go back to my app)? 3. is there a better practice for my need (singleton for example?) I want to avoid storing the files with NSUserDefaults

What I am doing at the moment (with Alamofire and SwiftyJSON)

class MyClass: UIViewController {

let username = "..."
let password = "..."
let url = "..."

static var staticArrayOfJS: [String] = []
var arrayOfJS: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()        
    fetchJS()
}

func fetchJS() { //this is intended to be executed only once
    let credentialData = "\(username):\(password)".data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
    let base64Credentials = credentialData.base64EncodedString()
    let headers = [
        "Authorization": "Basic \(base64Credentials)",
        "Accept": "application/json",
        "Content-Type": "application/json" ]

    Alamofire.request(url, method: .get, parameters: nil,encoding: URLEncoding.default, headers: headers) .responseJSON { response in
        guard let data = response.data else {
            print("no data returned")
            return
        }

        do {
            let json = try JSON(data: data)
            let indexOfLastItem = json.array?.count
            for i in 0..<indexOfLastItem! {
                self.arrayOfJS.append(json[i]["message"].string!)
            }
            MyClass.staticArrayOfJS = self.arrayOfJS
        }
        catch {
            print("error parsing json data")
        }
    }
}

static func getJSMessage(id: Int) -> String { // this is intended to be accessed from external classes, several times within the same user session
    return staticArrayOfJS[id]
}
}

Example of a JSON file content

[{"id":0,"message":"my message 0"}, {"id":1,"message":"my message 1"}, ...
Don
  • 977
  • 3
  • 10
  • 28
  • You should simply download these files and store them, as files. At every launch you can override the previously downloaded files with the new ones. – AnthoPak Aug 01 '18 at 07:53

2 Answers2

1

I don't think it's a heavy operation to have 11 * 200KB nearly 2MB , in memory shared as a singleton array

regarding sending app to background , the content won't reset if the app is left working by IOS , but if closed you will get a new launch when you open it again with array content is initiated from the begining

regarding the download every launch , i recommend having expire or new data flag , you should store them in a file/coreData or any other alternative and , it's best to implement Codable , to read them as Data to objects and vice versa when saving

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • Hi, thanks for your answer. When the app closes, could you confirm that the data from the files' content will be erased from the cache? Or is it kept somewhere? If it is not completely deleted, can a user find it on his device somehow? – Don Aug 01 '18 at 08:57
  • When the data is downloaded store it anywhere you want , then it will be erased only if the app is deleted from the device – Shehata Gamal Aug 01 '18 at 09:10
  • Sorry if I was not clear, I meant in the case the data is stored in a static array, I understand it is kept as long as the app is open, even in the background, but is it completely erased when the app closes or does it stay in cache somewhere in the device? – Don Aug 01 '18 at 09:15
  • @Don it doesn't cache it anywhere – AnthoPak Aug 01 '18 at 10:51
  • @Don There is no cache for variables or any app open state , once the app is terminated/closed everything is cleared except things you save ( that you'll load again when you open it ) – Shehata Gamal Aug 01 '18 at 10:55
  • 1
    Thank you @Sh_Khan – Don Aug 01 '18 at 11:59
0

The best way I can think of is simply downloading and storing the json as files in the app. Then, if the content may have been updated, you should override the previously downloaded files with the new ones, at app launch.

Here is sample code taken from this question to store and retrieve json files locally :

-(void)saveJsonWithData:(NSData *)data{
     NSString *jsonPath=[[NSSearchPathForDirectoriesInDomains(NSUserDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingFormat:@"/data.json"];
     [data writeToFile:jsonPath atomically:YES];
}

-(NSData *)getSavedJsonData{
    NSString *jsonPath=[[NSSearchPathForDirectoriesInDomains(NSUserDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingFormat:@"/data.json"];
    return [NSData dataWithContentsOfFile:jsonPath]
}

Please tell me if you need help for Swift translation :)

AnthoPak
  • 4,191
  • 3
  • 23
  • 41
  • Thanks for your answer. As stated in my OP, I would rather not store the content in a file – Don Aug 01 '18 at 08:57
  • @Don You stated "I want to avoid storing the files with NSUserDefaults" and my solution isn't storing the files in `NSUserDefaults` which is not made to store files. The solution I've provided hasn't got any drawbacks on memory – AnthoPak Aug 01 '18 at 09:01