Parsing JSON file from folder - NSTemporaryDirectory - json

I have got a file downloaded from AWS S3 to my NSTemporaryDirectory using this code:
let downloadFilePath = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("FILENAME")
let downloadingFileURL = NSURL(fileURLWithPath:downloadFilePath)
let downloadRequest: AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest();
downloadRequest.bucket = "Bucketname";
downloadRequest.key = "FileName";
downloadRequest.downloadingFileURL = downloadingFileURL;
The file = .json file
the apps content is all saved on the JSON file, therefore i need to redirect the file from the NSTemporaryDirectory in order for the content to appear on the application.
Does anyone know the parse function in order to load the data from my JSON file into the application?
Thank you

You cannot modify the main bundle, so this isn't going to work.
There are a few directories under your control, for example the home directory, the application support directory, cache directories, or possibly the document directory.

As gnasher729 notes, you can't modify the main bundle itself, but there's no reason to here. You don't need to move the file in order to display it. You can read from your temporary directory. It's inside your application sandbox, and there's nothing special about it (it doesn't even get cleaned up for you either, so that's your responsibility if you need that).
The temp directory isn't backed up, so if you want that, you should move this to your documents directory. See NSFileManager moveItemAtPath:toPath:error: if you want to do that (or just download to your documents directory in the first place).

I figured it out.
So after downloading the File:
let downloadFilePath = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("FILENAME")
let downloadingFileURL = NSURL(fileURLWithPath:downloadFilePath)
let downloadRequest: AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest();
downloadRequest.bucket = "Bucketname";
downloadRequest.key = "FileName";
downloadRequest.downloadingFileURL = downloadingFileURL;
i have to submit the download request - as seen below:
// submit download request
let transferManager: AWSS3TransferManager = AWSS3TransferManager.defaultS3TransferManager();
print("Downloading started, please wait...");
transferManager.download(downloadRequest).continueWithExecutor(AWSExecutor.defaultExecutor(), block: { (task) -> AnyObject? in
print("TASK:::::: \(task)");
if (task.error != nil){
print("Error Downloading");
}else{
self.readFile()
print("Download complete");
}
return nil;
}, cancellationToken: nil)
}
create a function that will parse your JSON file through the temp directory, using AlamoFire and SwiftyJSON:
func readFile() {
// JSON parsing step (from temporary directory)
let path = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("FILENAME")
do {
let readFile:NSString? = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
let json = JSON.parse(readFile as String!)
for (_, subJson) in json["FILECONTENT"] {
let version = subJson["FILECONTENT"].string
let newsletter = Edition(Version: version!)
self.editions.append(ARRAYNAME!)
}
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
//print(readFile)
} catch {
}
}
this will showcase the text on your application when ran.
I am trying to get the images to do the something now.

Related

Problem loading JSON resource in SWIFT package

I am trying to load a JSON file that is bundled with a Swift package I am working on.
The JSON file is called config.json and it is located in my project under /Sources/<Target>/data/config.json
UPDATE: I have also added the resource to the target in the Package Description as follows:
...
.target(
name: "MyPackage",
resources: [
.process("data/config.json")
]
),
...
I am trying to load it using the following code:
guard let sourcesURL = Bundle.main.url(forResource: "config", withExtension: "json") else {
fatalError("Could not find config.json")
}
... but I keep getting nil. Has anyone had an issue like this? Any idea what I'm doing wrong?
You should use module
Bundle.module.url(forResource: "config", withExtension: "json")
And you need to make sure the file is included when building by adding below to your target in Package.swift
resources: [
.copy("data/config.json") //This could alo be .process
])
The above assumes that the resource is loaded from within the same package, if you want to load a resource from another package you can use the following general solution.
First define a constant in the package that holds the bundle identifier for the package, for instance in an extension to Bundle
extension Bundle {
public static let myPackageNameBundleIdentifier = Bundle.module.bundleIdentifier!
}
And then create an instance of that Bundle when loading the resource in another package or the app
if let bundle = Bundle(identifier: Bundle.myPackageNameBundleIdentifier) {
let url = bundle.url(forResource: "config", withExtension: "json")
// ...
}

"Fatal error: Unexpectedly found nil while unwrapping an Optional value" despite being in correct bundle and build phase [duplicate]

I've been trying to access a file in my command line tool Xcode project but program isn't able to find the file path. I'm assuming it's because the file isn't being copied to my project.
I've gone to build phases and added my file (graph2.net) but the program can't find the file.
func readGraph() {
if let path = Bundle.main.path(forResource: "graph2", ofType: "net") {
print(path)
} else {
print("Failed")
}
}
always returns failed. However in an iOS app, the option to copy bundle resources exists and I am able to find the file. How can I solve this issue?
A command-line-tool only consists of an executable. No bundle is created and what you are trying to do is not possible.
You’ll have to place the file in some other place and load it from there.
You can create a bundle and place it in same directory as your executable file.
import Foundation
private class BundleLocator {}
/// Category for easily retrieving the accompanying bundle.
extension Bundle {
/// Local bundle, assuming it resides in the main bundle.
static var resources: Bundle {
let executableBundle = Bundle(for: BundleLocator.self)
guard let bundlePath = executableBundle.path(forResource: "Resources", ofType: "bundle") else {
fatalError(
"Could not find Resources bundle. Make sure you copy the bundle to the same folder as the executable file."
)
}
guard let bundle = Bundle(path: bundlePath) else {
fatalError("Failed to create bundle from path: \(bundlePath)")
}
return bundle
}
}

Saving a file with a variable of datatype 'Data" in Swift

I'm new to programming and I'm trying to write a function in Swift to download a JSON and parse it.
However, the JSON is very complicated and I have a daily limit on number of requests of data from the server.
Is there a way to download the data and save it to a file as 'data' so I can run all tests on this data in the file and not have to get it from the server everytime? Once I'm ready, I can start getting data from the server again.
Basically I could initialize a data variable with the contents of the file so I can use it on my tests.
Thank you
Determine where you want to store it and what it should be named. For example, for files that can be re-retrieved from the network, we’d use the cachesDirectory:
let folder = try! FileManager.default
.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("downloads")
Or, you can use the applicationSupportDirectory (if re-retrieving it is impractical) or .documentsDirectory (if you want to potentially expose the file to the end user). But the idea is the same.
Create that folder if you haven’t already:
try? FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
Create URL for the file within that folder:
let fileURL = folder.appendingPathComponent("sample.json")
Save that Data to that fileURL:
do {
try data.write(to: fileURL)
} catch {
print(error)
}

Retrieving binary file from post request

Sending a POST request (Apache httpclient, here Kotlin source code):
val httpPost = HttpPost("http://localhost:8000")
val builder = MultipartEntityBuilder.create()
builder.addBinaryBody("file", File("testFile.zip"),
ContentType.APPLICATION_OCTET_STREAM, "file.ext")
val multipart = builder.build()
httpPost.entity = multipart
val r = httpClient.execute(httpPost)
r.close()
I receive the request in my post handler as a via spark-java Request-object. How do I retrieve the original file (plus the file name as a bonus) from the post request? The request.bodyAsBytes() method seems to add some bytes because the body is larger than the original file.
Thanks, Jörg
Near the bottom of Spark's Documentation page there is a section "Examples and FAQ". The first example is "How do I upload something?".
From there, it links further to an example on GitHub.
In short:
post("/yourUploadPath", (request, response) -> {
request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
try (InputStream is = request.raw().getPart("file").getInputStream()) {
// Use the input stream to create a file
}
return "File uploaded";
});
To access the original file name:
request.raw().getPart("file").getSubmittedFileName()
To handle multiple files or parts, I usually have code similar to the following (assuming only files are included in the multi-part encoded upload):
for (Part part : req.raw().getParts()) {
try (InputStream stream = part.getInputStream()) {
String filename = part.getSubmittedFileName();
// save the input stream to the filesystem, and the filename to a database
}
}

Why do I unwrap nil in my Swift file?

I have an app (the same one from my previous post about unwrapping nil. I really hate nil now.) that searches the iTunes store and returns data in JSON. I have it working, it gets the song name, artist name, everything! I created an #IBAction button for playing the song's preview. The JSON has a property that is the url to the song preview. When I click the button, it does the following:
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(url, ofType: "m4a")!)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
The url is this: http://a1993.phobos.apple.com/us/r1000/101/Music/b7/b3/e0/mzm.ooahqslp.aac.p.m4a. I know my setup for playing an audio file works; I have another app I am building that uses the exact same setup. Why does it tell me that I unwrap nil here: http://a1993.phobos.apple.com/us/r1000/101/Music/b7/b3/e0/mzm.ooahqslp.aac.p.m4a? The url is valid and the file plays.
Examine this line of code.
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(url, ofType: "m4a")!)
fileUrlWithPath is asking for a local path, that is one on your device.
NSBundle.mainBundle().pathForResource(url.....
This method returns the local path for the resource you send to it. You are sending it a web url, which is not in the mainBundle unless you've explicitly put it there. So the path that it returns is nil, because there is no local path that satisfies the arguments you are passing to it.
If you have a local resource you should use a method called URLForResource
This line makes no sense. You should always prefer working with urls and extract the path from it if needed.
Replace this line:
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("fileName", ofType: "m4a")!) // this would crash if not found (nil)
with this block of code
if let alertSoundUrl = NSBundle.mainBundle().URLForResource("fileName", withExtension: "m4a") {
println(true)
} else {
println(false)
}
If it is a web link you need to use NSURL(string:). fileUrlWithPath it is only for local resources.
if let checkedUrl = NSURL(string: "http://a1993.phobos.apple.com/us/r1000/101/Music/b7/b3/e0/mzm.ooahqslp.aac.p.m4‌​") {
println(true)
} else {
println(false)
}