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
Add new
BOOL
attribute
to yourCoreData Entity
and name it assynched
. This will basically store the synched status for each object.Now you will have to check for internet connectivity. Refer to this link
Whenever you have internet connectivity, just fetch the objects from
CoreData
using the followingNSPredicate
in your fetch request:let isSynchedPredicate = NSPredicate(format: "synched = %@", false)
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 totrue
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
How to Add a Show More/Show Less Uibutton to Control Uitextview
Best Way to Structure My Firebase Database
Swift Enumerate Functions. How Does It Work Behind
Swift: Incrementing Label with Delay
Property with '= {Return}()' or '{Return}'
Get Current Url from Browser in MACos
Swift Firebase Using an Unspecified Index
Create a Loading Image/ Activity Indicator, Until the Image Is Shown in the Screen in Swift
Hmac Sha512 Using Commoncrypto in Swift 3.1
How to Perform Face Detection in Swift
Sharing Highscore with Social Media
Play Mp4 Using Mpmovieplayercontroller() in Swift
Textfield Delegate Shouldchangecharactersinrange
How to Use the "Handler" of Uialertaction to Call Another Uialertaction