I am trying to read data from my API. I am not using JSON data because the API doesn't return an array, just a line of text. Anyways, I am using the following code to read the text from the API.
func contactVetApi(url:String){
let nsUrl = NSURL(string:url)
let task = NSURLSession.sharedSession().dataTaskWithURL(nsUrl!){
(data, response, error) in
print(data)
}
task.resume()
}
I am calling this function in the ViewDidLoad function of my ViewController file. As you can see, it takes a parameter that is a string. The parameter is the URL to read. It then translates the string into a NSUrl so it can be used with the sharedSession. I then initialize the shared session and create a data task with that url. I then print out the data it returns. The only issue is that the output isn't what I am expecting. What I am expecting is for it to say, "Future home of something quite cool." Although, this is what I am getting.
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
Optional(<46757475 72652068 6f6d6520 6f662073 6f6d6574 68696e67 20717569 74652063 6f6f6c>)
I need help figuring out why it is printing that out instead of what I am expecting. In case it is needed, the api url is http://apis.wilsonfamily5.org/vet/about.php. Before anybody asks though, I did add into the info.plist file the disabling of the iOS 9 app transport security. If you need any extra information to help me solve this problem, I would be more then happy to give it to you. I want to thank you in advance.
You currently are printing a NSData object, which will always look like that jibberish. What you actually want however is to convert the NSData to a NSString or String to create a human readable form:
var dataAsString = NSString(data: data, encoding: NSUTF8StringEncoding)
Taken from this answer.
Related
I am learning how to write JSON format data to an iPhone. So with one button clicked, I want to save those data to the iPhone. I looked a simple look on how to write some simple text and saved it to the iPhone file and it worked. However, I tried to apply the same idea to JSON data but still haven't figure out. I tried:
Rather than having contents equal to some written text, I tried to put it as my data (jsondata).
But it does not seem working with
try jsondata.write(to: fileURL, atomically: false, encoding: .utf8)
#IBAction func writeFiles(_ sender: Any) {
let file = "\(UUID().uuidString).txt"
let contents = "Testing"
let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = dir.appendingPathComponent(file)
do {
try contents.write(to: fileURL, atomically: false, encoding: .utf8)
}
catch {
print("Error: \(error)")
}
}
Sorry I am a bit new and learning Swift at the moment
Thanks!
Here is a simple project for you to clone or browse the source files
https://github.com/eSpecialized/WriteJsonToFiles
The View Controller contains the example;
https://github.com/eSpecialized/WriteJsonToFiles/blob/master/WriteToFiles/ViewController.swift
Basically you need to do a few steps for writing;
Assemble your objects (Strings etc).
Convert to JSONEncoded Data using the JSONEncoder.
The actual 'Data' Object can write it's binary content to storage.
To read the data;
You need a JSONDecoder.
You need the FileContents in memory using Data(contents:...)
Decode the in-memory data back into the object like it was stored.
A more complicated example of reading and writing JSON to a Web Service API is on Medium here > https://medium.com/better-programming/json-parsing-in-swift-2498099b78f
The concepts are the same, the destination changes from a file in the users document folder to a web service API. I feel that it is adequate to get you started with reading and writing JSON.
The Medium article goes a step further with introducing you to Data Models and reading and writing those Data Model Structs using the Codable protocol.
Enjoy! :)
I use gzip library to convert data to gzip data
If I want to get string from data I do String(data: data, encoding: .utf8) . But if I do the same for gzip data I get nil string, because as far as I understand it's impossible to convert gzip data to string with .utf8 encoding.
I need that because I want to compare data with a server developer (because he sometimes he says that my data is incorrect format, but sometimes it's ok, and that's strange because I use the same library, and I have thoughts that may be the problem is on server side).
Is there any way to convert gzip data to any string to compare it then later?
If this is just for debug purpose, then I think the quickest way is:
let myGZipNSData = myGZipData as! NSData //I wrote a "!" just for the sample)
print("myGZipNSData: \(myGZipNSData)")
It should output:
myGZipNSData: <5b226d79 41727261 7956616c 75653022 2c226d79 41727261 7956616c 75653122 5d>
This relies on -description method of NSData which print "<hexValue>".
Do not rely on it on release version, almost never rely on -description (yes, Apple could change the behavior of -description in next release. It happened on a different class).
Other way (safer) to get almost the same result, you can check this question: How to convert Data to hex string in swift which you get you the same result (almost, less space, and no </>) as the previous one.
Other way: Base 64
Use base64EncodedString() method of Data:
let base64Str = myGZipData?.base64EncodedString()
print("base64Str: \(base64Str!)")
Output:
base64Str: WyJteUFycmF5VmFsdWUwIiwibXlBcnJheVZhbHVlMSJd
Now, there should be other way:
Have a array representation with Int values (between 0/255 instead of hex), but it seems to be for debug purpose so check if you can "reproduce the current solutions" (working/fast implementation) I gave you, and check with the server developer what he/she can do on his/her side too to compare.
Note:
For the purpose of this sample, myGZipData is constructed this way:
let array = ["myArrayValue0", "myArrayValue1"]
let myGZipData = try? JSONSerialization.data(withJSONObject: array, options:[])
It's not really a GZipData, but the goal was to quickly have a Data object "big enough".
I am converting a [NSDictionary] to NSString like so :
do{
let newDict = try NSJSONSerialization.dataWithJSONObject(objectDictionaries, options: NSJSONWritingOptions.PrettyPrinted)
if let json = NSString(data: newDict, encoding: NSUTF8StringEncoding) {
print(json)
}
When the json prints out I get this:
How do I convert this NSString to JSON without changing the format as this photo shows?
The I want to send this json to a API and the format I want is the only one the API will be able to encode,
Remove the option NSJSONWritingOptions.PrettyPrinted in the call to dataWithJSONObject. That is what is forcing the outputted string to be formatted like that.
The output of NSJSONSerialization.dataWithJSONObject is valid JSON, and that's what you should send to an API. Conversion to a string is pointless unless you want to view the output for debugging purposes.
NSJSONWritingOptions.PrettyPrinted is useful if you want to view the output for debugging purposes, but otherwise it's just a waste of time and makes the JSON a few percent bigger which takes memory, time to send to the API, time to process in the API.
PS. If "Pretty printed" or not makes any difference to your API, then your API is pretty badly broken.
Whenever I try to create an NSURL from it, I always receive nil back. How do I make it work?
Small example:
let str = "https://montr\\U00e9al.ca".stringByRemovingPercentEncoding!
NSURL(string: str)
Which always gives me nil back. Even if I replace the \u00e9 with é it still returns nil.
How should I be doing this?
You should make unicode in braces and add percent for it like this:
let str = "https://www.montr\u{00e9}al.ca".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
First, if you have any control over the server, you should fix the server to provide proper URLs. If you don't have control over it, but can choose a different service, do so. There's no guarantee that improperly encoded URLs will be the only problem coming from that server.
If you can't switch servers, you may need to do something like this:
let percentEncodedURLString = NSURL(dataRepresentation: str.dataUsingEncoding(NSUTF8StringEncoding)!, relativeToURL: nil).relativeString
This is the Swift version of what Apple recommends in the Foundation release notes. I strongly recommend that you read that section to understand the issues with other approaches.
I am putting together a program that reads the sensors within a cell phone and saves the sensor data to a core-data SQLite model, with each set of readings pertaining to a particular session
The program provides the user with the option to email a .csv file of a particular session.
Having never done this before, I approached the issue by initializing a delegate and context, and searching the core data for entities that pertain to a specified session. The entities that satisfy the session attribute then have their data fields (gps, mag, accel, gyro) read and put into a string. Then the string is appended to an array. All done in swift.
After the entities are searched and the array is created, I attempt to create a csv file for attachment to an email. The file is attached successfully, but my encoding technique is presenting additional data prepended and appended to the file.
I want to save a file on the phone and email a copy to the user.
Here is what I have to change the Array to NSArray before converting again to NSData:
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
let path = paths[0].stringByAppendingPathComponent("SessionData.csv")
if !NSFileManager.defaultManager().fileExistsAtPath(path)
{
NSFileManager.defaultManager().createFileAtPath(path, contents: nil, attributes: nil)
}
else
{
NSFileManager.defaultManager().createFileAtPath(path, contents: nil, attributes: nil)
}
var handle: NSFileHandle = NSFileHandle(forWritingAtPath: path)
handle.truncateFileAtOffset(handle.seekToEndOfFile())
var arrayToWriteNS = (arrayToWrite as NSArray)
var dataNS: NSData = NSKeyedArchiver.archivedDataWithRootObject(arrayToWrite as NSArray)
handle.writeData(dataNS)
mc.setSubject(emailTitle)
mc.addAttachmentData(dataNS, mimeType: "text/csv", fileName: "SessionData.csv")
Here is the prepended and appended data:
bplist00‘()T$topX$objectsX$versionY$archiver—TrootĨ
!U$null“
V$classZNS.objectsÄ©ÄÄÄÄÄÄÄÄ Ä
"My Data"
“"#$'X$classesZ$classname¢%&WNSArrayXNSObjectWNSArray܆_NSKeyedArchiver(25:<IOT[fhrtvxz|~ÄÇÑ·Ø}KÁµÉQV_jmu~Üã*ù
In a large data session with 28,000 entities there may be ~750 lines of prepended data.
Any help that you can provide would be appreciated.
I'm new to iOS, Obj-C, and swift, thus I'm positive there is a better way to do this, I just haven't discovered a better method yet.
Thank you.
UPDATE: Ended up just using the NSString data encoding and writing to my file in increments:
handle.truncateFileAtOffset(handle.seekToEndOfFile())
var stringToWriteNS = (stringToWrite as NSString).dataUsingEncoding(NSUTF8StringEncoding)
handle.writeData(stringToWriteNS!)
You do not want NSKeyedArchiver, it is for archiving and restoring classes.
You need to go through the array and create a text representation of each item in a format you what to present to the user.
A quick search of CocoaPods reveals several projects that may fit you needs to generate csv format data.
This one might be what you need.
csv is fairly simple so it would be reasonable to format your data to csv by writing your own code.