Saving Coredata to a Web Server with Swift 3.0

Saving CoreData to a Web Server with Swift 3.0

The question that you have linked is not trying to explain how to communicate with a web server. It is explaining how to store data in core data and tag/mark it in a way that you know which records have been sent to the web server or not.

So the Predicate will fetch all records that have not been sent to the web server and allow you to send them when you have an internet connection available.

Communicating with a web server can be a broad topic and will depend on your web server and API setup, so it is too much to explain here fully. I refer you to some free online resources that will help you understand networking in Swift.

  • Udacity - Networking with Swift
  • Ray Wenderlich - Alamofire Tutorial
  • Stack Overflow - Swift POST Request

Here is an example of a POST Request from the StackOverflow answer above

var request = URLRequest(url: URL(string: "http://test.tranzporthub.com/street45/customer_login.php")!)
request.httpMethod = "POST"
let postString = "user_id=chaitanya3191@gmail.com&password=123"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}

if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")

}

let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
}
task.resume()

Using code similar to this, you should be able to send data to your web server, then your web server can do whatever it likes with it.

UPDATE:

To encode your parameters to JSON you can use the following code as a guide

var dictionary = [
"username": "Test User",
"password": "Password"
]

if let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options: []) {
// jsonData is a byte sequence, to view it you would need to convert to string
print(String(bytes: jsonData, encoding: String.Encoding.utf8))
}

Which would output:

Optional("{\"username\":\"Test User\",\"password\":\"Password\"}")

Note: you would send it as data, not the string version. so your code might look like this:

request.httpBody = jsonData

Swift Core Data Sync With Web Server

  1. Add new BOOL attribute to your CoreData Entity and name it as synched. This will basically store the synched status for each object.

  2. Now you will have to check for internet connectivity. Refer to this link

  3. Whenever you have internet connectivity, just fetch the objects from CoreData using the following NSPredicate in your fetch request:

    let isSynchedPredicate = NSPredicate(format: "synched = %@", false)
  4. Now you can just use your webservice to sync and update all the fetched objects to server. On successfull upload, DONOT forget to change the synched property to true

sync core data with web server

Following might be helpful

http://publications.csail.mit.edu/tmp/MIT-CSAIL-TR-2005-014.pdf

http://iphone2009.crowdvine.com/talk/presentation_file/5104/Grover_Syncing.pdf

https://stackoverflow.com/a/5052208/1294448

Swift 3 - Saving images to Core Data

replace

let image: Data = images.value(forKey: "image")! as! Data
let dataDecoded : Data = Data(base64Encoded: image, options: [])!
let decodedimage = UIImage(data: dataDecoded)

with

let image: Data = images.value(forKey: "image")! as! Data
let decodedimage = UIImage(data: image)

Base64 is a way to to convert data to a string. There is no reason to use it here. You already have the data from the database you just want to convert it to a UIImage.

also change

let image = data?.base64EncodedData()
saveImageToDB(brandName: imageBrandName, image: image!)

to

saveImageToDB(brandName: imageBrandName, image: data!)

base64EncodedData is turning the data from image data into a utf-8 encoded based64encoded string. There is no reason for that.

You should get the base64 encoded string from server, convert it to data and then you never need base64 again. Read and write data to your database, and after you read it convert it to a UIImage. Base64 is an encoding method to transfer data. If you are not talking to the server there is no reason to use base64.

CoreData Swift: How to save and load data?

Saving data:

var person = NSEntityDescription.insertNewObjectForEntityForName("Person", 
inManagedObjectContext: self.managedObjectContext!) as Person
person.name = "Mary"
person.age = Float(arc4random() % 100)

var error : NSError? = nil
if !self.managedObjectContext!.save(&error) {
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
}

Loading data:

var error: NSError? = nil
var fReq: NSFetchRequest = NSFetchRequest(entityName: "Frases")
fReq.predicate = NSPredicate(format: "id contains[c] %@", String(day))
var sorter: NSSortDescriptor = NSSortDescriptor(key: "id" , ascending: false)
fReq.sortDescriptors = [sorter]
fReq.returnsObjectsAsFaults = false
let result : [AnyObject] = self.managedObjectContext!.executeFetchRequest(fReq, error:&error)!

Swift - Saving to Core Data

Background

iOS devices, like most computers, have persistent storage. (e.g. a hard drive or an ssd)

To persist data across system shutdown events, etc., your app can save it directly to this store using the filesystem. This is a quick and simple way of storing data.

If you need a more structured approach, you could use a database. This approach allows you to work with your data in a more organized fashion (i.e. in rows and columns, with relationships, etc.) This database would be stored on the filesystem, but your app would work directly with the database file(s) itself.

On iOS, the typical database used is SQLite.

Core Data is another layer on top of one (or rarely, multiple) databases. This approach allows you to focus on your data as entities with relationships to each other. (e.g. User -> multiple Follower, etc.) Using Core Data, you can usually ignore the databases and the filesystem underlying it.

On iOS, Core Data is typically implemented with one SQLite database as a store.

Your Use Case

If all you need is to store a few images or videos to your device, then storing directly to the filesystem can work pretty well.

Assuming you already have your file in hand, you just need to:

  • 1 – get a directory location

    var documentDirectoryUrl: URL
    do {
    try documentDirectoryUrl = FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    let imageUrl = documentDirectoryUrl.appendingPathComponent("imageFileName.jpg")
    } catch {
    // error handling
    }

  • 2 – write your file to disk

    if (try? imageData.write(to: imageUrl)) == nil { // nil == false
    print("Error: could not save image to file system.")
    }

Reference

  • iOS File System
  • Core Data
  • SQLite on iOS Tutorial

Saving custom object as core data property

As mentioned, have your prayer class subclass NSObject and conform to NSCoding which requires two methods : -initWithCoder: and encodeWithCoder:

Once those are implemented, you can use NSKeyedArchiver/NSKeyedUnarchiver class methods to transform your objects into NSData objects and back, thus allowing you to store your objects as CoreData properties under the supported NSData type.



Related Topics



Leave a reply



Submit