I have a problem that I can't successfully convert NSData to NSString
I use google drive sdks to get content of my google doc using
var fetcher:GTMHTTPFetcher = service.fetcherService.fetcherWithURLString(downloadurl as! String)
fetcher.beginFetchWithCompletionHandler({(olddata:NSData!, error:NSError!) in
if(error == nil) {
print(olddata)
}
else {
print("error is \(error)")
}
})
olddata was a NSData (with no optional)
And I want to convert to NSString
but it always return nil when using basic conversion
let myStringFromData = NSString(data: olddata, encoding: NSUTF8StringEncoding)
how can i fix this
import Foundation
let string = "what i would like to send to server as utf8 text"
var utf8text = string.utf8.map { $0 }
utf8text.append(0)
let data = NSData(bytes: &utf8text, length: utf8text.count)
// ..... upload, download, data is now received NSData from server
let p = UnsafePointer<Int8>(data.bytes)
if let received = String.fromCString(p) {
print(received) // what i would like to send to server as utf8 text
}else {
print("error by reconstructing string from data")
}
or
let string = "what i would like to send to server as utf8 text"
var buffer = string.nulTerminatedUTF8.map{ $0 }
let data = NSData(bytes: &buffer, length: buffer.count)
// ..... upload, download, data is now received NSData from server
let p = UnsafePointer<Int8>(data.bytes)
if let received = String.fromCString(p) {
print(received) // what i would like to send to server as utf8 text
}else {
print("error by reconstructing string from data")
}
or
let buffer = "what i would like to send to server as utf8 text".nulTerminatedUTF8
let data = buffer.withUnsafeBufferPointer {
NSData(bytes: $0.baseAddress, length: $0.count)
}
Related
I currently have a function that allows me to upload an image to Firebase Storage. But how in the world can I achieve the same, with a video instead of an image?
I suspect I have to change UIImage and .jpg to something else. But what is the type of a video?
#State var pickedImages: [UIImage] = []
#State var retrievedImages = [UIImage]()
This is my function:
func uploadImage() {
// Create storage reference
let storageRef = Storage.storage().reference()
// Turn our image into data
let selectedImage = pickedImages[0]
let imageData = selectedImage.jpegData(compressionQuality: 0.8)
guard imageData != nil else {
let er = "THIS: Error while converting to data"
return print(er)
}
// Specifie filepath and name
let path = "images/\(UUID().uuidString).jpg"
let fileRef = storageRef.child(path)
// Upload that data
let uploadTask = fileRef.putData(imageData!, metadata: nil) {metaData, error in
print("THIS: from uploadTAsk")
// Check for errors
if error == nil && metaData != nil {
// Save reference in firestore DB
let db = Firestore.firestore()
db.collection("images").document("user1").setData(["url": path]) { error in
print("THIS: inside closure")
// If there was no errors, display the image
if error == nil {
DispatchQueue.main.async {
self.retrievedImages.append(selectedImage)
}
}
}
}
}
}
I've a cloud firebase result item:
let mpUserRef = db?.collection(MPUser.PROPERTY_DB)
.whereField(MPUser.PROPERTY_FIREBASE_USER_ID, isEqualTo: firebaseUSer.uid)
.limit(to: 1).getDocuments() { (document, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in document!.documents {
let mpUser = fromJsonToMpUser( userJson: "\(document.data())" )
if mpUser != nil{
delegate.mpUser = mpUser
}
}
}
}
And i want to decode result item in my business Object calling the method:
class func fromJsonToMpUser( userJson: String ) -> MPUser?{
let decoder = JSONDecoder()
do{
let json = userJson.data(using: .utf8)!
let mpUser = try decoder.decode(MPUser.self, from: json)
return mpUser
}catch{
print("Errore while ecode Club")
return nil
}
}
But this does not work, the error message that i have is:
"The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Badly formed array around character 17." UserInfo={NSDebugDescription=Badly formed array around character 17.}))).
So, how can i converte cloud firestore item result in valid Json?
I've resolved my question using CodableFirebase library ( https://github.com/alickbass/CodableFirebase created by #alickbass )
I'm trying to get a 3D Model which is stored in Firebase into my iOS Application.
Right now I stored the default Object (ship.scn) into my Firebase Storage.
How can I convert the Data, which I get from Firebase, to a SCNNode?
This is my Code right now:
let storage = Storage.storage().reference()
let modelPath = storage.child("models/ship.scn")
print("ModelPath: \(modelPath)")
modelPath.getMetadata { (metaData, error) in
if error != nil {
print("ERROR: ", error!)
}else{
print("Metadata: \(metaData!)")
}
}
// this is what firebase shows for images
// how can i get the Data as SCNNode?
modelPath.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
if error != nil {
print("Error getData: \(error!)")
}else {
print(data)
}
}
I solved this problem by downloading the 3D Object from firebase into the devices document folder.
So when I need the 3D-object I create a reference to the downloaded 3D-Object
write To Directory: (where modelPath is the storage.child('your path') in firebase)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let tempDirectory = URL.init(fileURLWithPath: paths, isDirectory: true)
let targetUrl = tempDirectory.appendingPathComponent("ship.scn")
modelPath.write(toFile: targetUrl) { (url, error) in
if error != nil {
print("ERROR: \(error!)")
}else{
print("modelPath.write OKAY")
}
}
load 3D file from directory:
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let tempDirectory = URL.init(fileURLWithPath: paths, isDirectory: true)
let targetUrl = tempDirectory.appendingPathComponent("\ship.scn")
var sceneForNode: SCNScene? = nil
do {
// load the 3D-Model node from directory path
sceneForNode = try SCNScene(url: targetUrl, options: nil)
}catch{
print(error)
}
// create node to display on scene
let node: SCNNode? = sceneForNode?.rootNode.childNode(withName: "ship", recursively: true)
I have an old type of web service built on ASP.Net. With the following function, I was able to fetch some type of data from the asmx web service:
func getJsonData(sql: String, spparamnames: String, spParamValues: String, completeonClosure: #escaping (AnyObject?) -> ()) {
let url = URL(string:"http://www.example.com/MyWebService.asmx/GetDataTableAsJson")
var request = URLRequest(url: url!)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") // the request is JSON
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept") // the expected response is also JSON
request.httpMethod = "POST"
let dictionary = ["sql" : sql, "spparamnames" : spparamnames, "spparamvalues" : spParamValues] //Parameters are here seperated with comma
request.httpBody = try! JSONSerialization.data(withJSONObject: dictionary)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error.debugDescription) // some fundamental network error
return
}
do {
if response != nil {
let myJson = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:AnyObject]
let isCorectJson = JSONSerialization.isValidJSONObject(myJson)
let charcount = (myJson["d"] as? String)?.characters.count
let cc = charcount ?? 0
if isCorectJson == true && cc > 0 {
completeonClosure(myJson as AnyObject?)
)
} else {
let str2 = "Connection Error"
completeonClosure(str2 as AnyObject?)
}
}
} catch let JsonError {
print(JsonError)
}
}
task.resume()
}
When I run a query with Swift, and cast the object type as NSDictionary, my output result is the following:
getJsonData(sql: "SELECT TOP 3 User_id, LoweredUserName FROM Users", spparamnames: "", spParamValues: "") {
returnJSON in
OperationQueue.main.addOperation {
let mystr = returnJSON as? NSDictionary
print(mystr!)
}
}
Result:
{
d = "[{\"User_id\":102,\"LoweredUserName\":\"abu alay\"},{\"User_id\":90,\"LoweredUserName\":\"ali es\"},{\"User_id\":95,\"LoweredUserName\":\"alper ay\"}]";
}
I think that the result is some kind of dictionary, I was not able to convert the result to an array, therefore I cannot iterate between the rows and use the result efficiently. What should I do in order to read the result like: print(returnJSON[0]["LoweredUserName"]) ? What is the meaning of the letter "d" at the beginning of the result? Many thanks in advance.
It looks like your response is an Array, try to cast to an array of dictionary objects.
if let myJson = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [[String:AnyObject]] {
// parse each object here
}
This example code I ran in a playground seems to work fine:
let jsonString = "[{\"User_id\":102,\"LoweredUserName\":\"abu alay\"},{\"User_id\":90,\"LoweredUserName\":\"ali es\"},{\"User_id\":95,\"LoweredUserName\":\"alper ay\"}]"
let jsonData = jsonString.data(using: String.Encoding.utf8)
if let json = try? JSONSerialization.jsonObject(with: jsonData!, options: .mutableContainers) as? [[String:AnyObject]] {
print(json)
}
Output:
Optional([["User_id": 102, "LoweredUserName": abu alay], ["User_id": 90, "LoweredUserName": ali es], ["User_id": 95, "LoweredUserName": alper ay]])
If the text you have shown is the entire body of the result you got:
{
d = "[{\"User_id\":102,\"LoweredUserName\":\"abu alay\"},{\"User_id\":90,\"LoweredUserName\":\"ali es\"},{\"User_id\":95,\"LoweredUserName\":\"alper ay\"}]";
}
Then this is not properly formatted JSON. For it to be formatted properly the "d" would have to be shown in double quotes.
It looks like you may need to do some custom parsing on the result to get at the JSON contained in the "d" area.
Whenever I download an image from Firebase Storage it download's perfectly, but once I try to change the imageview "my" to it, the imageview disappears. I don't have constraints and I navigated to the local URL and found the image perfectly there. Any help? Am I doing something wrong?
func loadImages(){
let documentDirectoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let newRef = storageRef!.child("Images/0.jpg")
let fileDestinationUrl = documentDirectoryURL.URLByAppendingPathComponent("p.jpg")
let downloadTask = newRef.writeToFile(fileDestinationUrl){ (URL, error) -> Void in
if (error != nil) {
print("problem")
} else {
print("done")
}
}
downloadTask.observeStatus(.Success) { (snapshot) -> Void in
print(fileDestinationUrl)
var temp = String(fileDestinationUrl)
print(temp)
var my = UIImage(contentsOfFile: temp)
self.image.image = my
}
}
Print the destinationUrl in your console .Go to your downloaded file location , open your terminal , drag and drop the DOWNLOADED image in the terminal and the terminal will give you its actual path.Now compare both the path the one that terminal gave you and the one that console gave you, match those. most like they are to be different ,change them accordingly.
Example code :-
Uploading Code : -
func profilePictureUploading(infoOnThePicture : [String : AnyObject],completionBlock : (()->Void)) {
if let referenceUrl = infoOnThePicture[UIImagePickerControllerReferenceURL] {
print(referenceUrl)
let assets = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl as! NSURL], options: nil)
print(assets)
let asset = assets.firstObject
print(asset)
asset?.requestContentEditingInputWithOptions(nil, completionHandler: { (ContentEditingInput, infoOfThePicture) in
let imageFile = ContentEditingInput?.fullSizeImageURL
print("imagefile : \(imageFile)")
let filePath = FIRAuth.auth()!.currentUser!.uid + "/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/\(imageFile!.lastPathComponent!)"
print("filePath : \(filePath)")
FIRControllerClass.storageRef.child("ProfilePictures").child(filePath).putFile(imageFile!, metadata: nil, completion: { (metadata, error) in
if error != nil{
print("error in uploading image : \(error)")
}
else{
print("metadata in : \(metadata!)")
print(metadata?.downloadURL())
print("The pic has been uploaded")
print("download url : \(metadata?.downloadURL())")
self.uploadSuccess(metadata!, storagePath: filePath)
completionBlock()
}
})
})
}else{
print("No reference URL found!")
}
}
Downloading code : -
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
print("paths in user home page : \(paths)")
let documentDirectory = paths[0]
print("documents directory in homePage : \(documentDirectory)")
let filePath = "file:\(documentDirectory)/\(user!.uid).jpg"
var filePath2 : String = filePath
print(filePath)
let storagePath = NSUserDefaults.standardUserDefaults().objectForKey("storagePath") as! String
print("storagePath is : \(storagePath)")
storageRef.child("ProfilePictures").child(storagePath).writeToFile(NSURL.init(string: filePath)! , completion :
{ (url, err) -> Void in
if let error = err{
print("error while downloading your image :\(error)")
}else{
print("Download successful !")
print("the file filePath of the downloaded file : \(filePath)")
filePath2 = "\(documentDirectory)/\(self.user!.uid).jpg"
if let downloadedImage = UIImage(contentsOfFile: filePath2){
self.profilePictureImageView.image = downloadedImage
print("displayed")
}else{
print("unable to display")
}
}
})
where storagePath is something that you stored in your NSUserDefaults for later reference , such as this, while uploading your image to your firebase storage
The codeBlocks that i gave you are just one of many solutions, there are plenty of ways to do this, go to https://firebase.google.com/docs/storage/ios/download-files