Alamofire.request does not map with custom object - swift3

I was trying to create a sample app in swift that maps with alamofire with alamofire object mapper. The whole idea of this sample app is to map json response with custom model that I make. But when I try to loop the object list, it says that custom object is not compatible and its a dictionary.
Here is my network layer code
// MARK: retrieve country list
func retrieveCountryList(completion: #escaping (_ result: NSArray) -> Void) {
Alamofire.request("https://restcountries.eu/rest/v2/all").
responseJSON{(response: DataResponse<Any>) in
let result = response.result.value;
let resultsArray = result as! NSArray
completion(resultsArray)
}
}
and model
class Country : Mappable {
var name:String?
var capital:String?
required init(map : Map) {
}
func mapping(map: Map) {
name <- map["name"]
capital <- map["capital"]
}
}
It seems that the response is doesn't directly maps with model. what might be the issue ?
alamofire version 4.3

You first need to install "AlamofireObjectMapper" .
For which you should add into your project by including "pod 'AlamofireObjectMapper'" followed by command "pod install" .
Now in your API call class "import AlamofireObjectMapper" and try typing ".responseObject" you'll get it.

Related

How to fetch Coredata List in IntentHandler class (WidgetKit-SwiftUI)?

I am not able to fetch data in my IntentHandler class. My Goal is select Todo from the CoreData list and display it in Widget.
I am trying to display a list from CoreData in Widget Intent and I am expecting to resolve this issue.
extension IntentHandler : ConfigurationIntentHandling {
func provideTodoNameOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: #escaping (INObjectCollection<TodoData>?, Error?) -> Void) {
var arrTodoData = [TodoData]()
coreDH.getAllTodos().forEach { todos in
let todoIntent = TodoData(identifier: todos.id?.uuidString, display: todos.name ?? "")
arrTodoData.append(todoIntent)
}
let collection = INObjectCollection(items: arrTodoData)
completion(collection, nil)
}
}
class IntentHandler: INExtension{
let coreDH = CoreDataHandler.shared
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
If your IntentHandler doesn't get called:
Ensure your Widget uses IntentConfiguration not StaticConfiguration
Ensure your time line provider conforms to IntentTimelineProvider
Run the app scheme, then run the intent scheme, you should be able to debug and breakpoints would work.
Widgets Code-along, part 3: Advancing timelines (5:31)
Add Configuration and Intelligence to Your Widgets
If you need to share data between your app and extension:
App's data is sandboxed and is not accessible by extension
Configure App Groups and you could create core data file in the shared container to be able to access in your extension
If App and Extension use exactly the same data you could use the same sqlite file in the shared container (both app and extension would have access to it)
If App and Extension use different data and there is only a small portion that is common, then use History Tracking
Configuring App Groups
Consuming Relevant Store Changes

Creating Repository pattern for use with local .SQLite db in Swift

I am building a SwiftUI app that pulls information from a local .SQLite database (using the SQLite.swift wrapper from https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md). I need to build a repository that sits between the View Service and the Database Manager. I am very new to repository pattern, and am struggling to find 1) documentation for using repository pattern in Swift 5, and 2) what exactly needs to be in the repository.
I found this example for using repository pattern in Swift, but it uses a web-based API for its code examples, and I can't find anything for use with a local db.
Code below is what I have in the repository so far:
struct doMaster: Codable {
let doID: Int64
let doName: String
let doState: Bool
let doCompletedState: Bool
let doCategory: String
}
struct doDescription: Codable {
let doID: Int64
let doDescription: String
}
struct doStreaks: Codable {
let doID: Int64
let doStreak: Int64
}
struct doCategories: Codable {
let category: String
let categoryColor: String
}
class LocalRepository {
let path: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""
let task =
}
Any help would be very much appreciated. Thank you in advance!

FMDB & Swift, " Optional("no such table: Student info") " in real device but it can be done in simulator

I'm newbie, plz help me to solve this out, I still have lots of other things to work on, really thank you thank you very much!
This is a further question after How to use FMDB on the generic iOS device instead of simulator?
When I execute the app on my device and the error threw out: "no such table: Student info", I've print all the path and they all pointed to the same file so I assumed the database has already copied? Console shows like this:
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/
file:///var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
/var/mobile/Containers/Data/Application/B5E42F3C-524E-4BBF-8667-1EED0C963A77/Documents/Data.db
<NSFileManager: 0x17401c1b0>
2017-03-13 16:43:25.446039 Test1.3[16360:5045427] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2017-03-13 16:43:25.457278 Test1.3[16360:5045427] [MC] Reading from public effective user settings.
Insert failed:
Optional("no such table: Student info")
The Data.db is in my bundle resources in target; and the contents in my device is a blank Data.db;
The 2nd question: If you look at the Utility.Swift in the previous question, although the app works good on simulator but after it was loaded, there should be an alertView said "Your database copy successfully", but it didn't. Following is that part of the code:
class func copyFile(_ fileName: NSString){
let dbPath: String = getPath(fileName as String)
let fileManager = FileManager.default
print(dbPath)
print(fileManager)
if !fileManager.fileExists(atPath: dbPath) {
let documentsURL = Bundle.main.resourceURL
let fromPath = documentsURL!.appendingPathComponent(fileName as String)
var error : NSError?
do {
try fileManager.copyItem(atPath: fromPath.path, toPath: dbPath)
}
catch let error1 as NSError {
error = error1
}
if(error != nil){
self.invokeAlertMethod("Error Occured", strBody: "\(error?.localizedDescription)" as NSString, delegate: nil)
}
else{
self.invokeAlertMethod("Successed", strBody: "Your database copy successfully", delegate: nil)
}
}
}
Okay for answering this question I went through your demo.
Where I found couple of mistakes. Let me go through one by one.
1) Your class Utility have a getPath method. What it does it will
keep copying db every time although db is already present in documents
directory and your documents directory db will be replaced with the sample structure. You should always check that if db is already present in documents directory or not.
2) Your db was getting copied into documents directory but structure
wasn't. There was no Student info table in db of documents directory.
3) Please avoid using space or any special characters in table names.
So what I did just corrected your method getPath in utility class.
Please replace your method with this one
class func getPath(_ fileName: String) -> String {
let bundlePath = Bundle.main.path(forResource: "Data", ofType: ".db")
let destPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileManager = FileManager.default
let fullDestPath = URL(fileURLWithPath: destPath).appendingPathComponent("Data.db")
if fileManager.fileExists(atPath: fullDestPath.path){
print("Database file is exist")
print(fileManager.fileExists(atPath: bundlePath!))
}else{
do{
try fileManager.copyItem(atPath: bundlePath!, toPath: fullDestPath.path)
}catch{
print("\n",error)
}
}
print(fullDestPath.path)
return fullDestPath.path
}
After changing this piece of code I tried to run in my device and inserted couple of records.
Let me know if you have any more questions.
If you find this answer helpful just accept it.
First trying delete your app and then reinstall it.
OR
I have created a project over FMDB in Swift which you can use to solve your issue. FMDB Wrapper class you can use in Objective C project as well.
https://github.com/LalitKY/Swift-FMDB
Hope this helps.

Web scraping in apple swift 3

I'm a Swift beginner and I'm trying to figure out how to retrieve text from a web article, create a new text file and save the text data into it (Using Swift Playgrounds). Is this possible?
The only thing I could find online regarding the subject was this, and I don't think it is even written for Swift 3:
P.S. If my question needs more details, please let me know instead of putting it on hold. Thanks!
import Cocoa
var url = NSURL(string: "http://finance.yahoo.com/news/tv-news-ces-2017-120931816.html")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
print(data)
if error == nil {
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!
print(urlContent)
That's Swift 2.3. In Swift 3 use URL instead of NSURL and use URLSession rather than NSURLSession, etc. You'd also use String rather than NSString. E.g.
let url = URL(string: "http://finance.yahoo.com/news/tv-news-ces-2017-120931816.html")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
print("\(error)")
return
}
let string = String(data: data, encoding: .utf8)
print("\(string)")
}
task.resume()
If you're going to do this in a playground, remember that this runs asynchronously, so you'll need to set needsIndefiniteExecution.
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
To actually parse the HTML, you should consider using a HTML parser like TFHpple (written in Objective-C, but still works great from Swift) or NDHpple (a Swift version, in which I don't have as much confidence as TFHpple, but probably would work fine).
You might want to see How to Parse HTML on iOS. It's dated, but walks you through the concepts (making sure you're not violating ToS of the web site, how to use the parsers, etc.).
If you want to save this to a file, you can do something like:
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("test.dat")
try! data.write(to: fileURL)
You can use whatever file extension you want.

fetching from Coredata in ios app widget extension in ios 10

Im trying to fetch entities from my coredata database of my main app and display them in my apps widget Extention. However the fetch always returns an empty results from my database. Can ayone help me out. Swift 3, ios 10.
I solved it. After creating the App Group, I created a subclass of NSPersistentContainer and override the class method defaultDirectory() to return the shared app group directory. Also override the init(name: String, managedObjectModel model: NSManagedObjectModel). Then in the coredata stack you replace the boilerplate persistentcontainer code with a new instance of the PersistentContainer class created.
import UIKit
import CoreData
class PersistentContainer: NSPersistentContainer{
override class func defaultDirectoryURL() -> URL{
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bundleId.SomeApp")!
}
override init(name: String, managedObjectModel model: NSManagedObjectModel) {
super.init(name: name, managedObjectModel: model)
}
}
Then in the CoreDataStack Code *wherever that maybe, either in the Appdelegate or or its own file. Mine was in its own file named CoredataStack
static var persistentContainer:PersistentContainer = {
let container = PersistentContainer(name: "SomeApp", managedObjectModel: CoreDataStack.managedObjectModel)
container.loadPersistentStores(completionHandler: { (storeDescription:NSPersistentStoreDescription, error:Error?) in
if let error = error as NSError?{
fatalError("UnResolved error \(error), \(error.userInfo)")
}
})
return container
}()
Hope this helps out
Today Extension runs in a different process from its containing app, thus do not share sandbox, UserDefaults, or database tabled. That is why you get an empty set when trying to fetch data saved in container, from the widget.
If you want the containing app and the widget to share data, you should add to your app the capability "App Group" via the iOS developer portal and give it a shared group identifier string.
Next, when you instantiate the FileManager object for the database (or UserDefaults), you must use initWithSuiteName method to, passing in the identifier of the shared group.