Proper way to parse with SwiftyJSON - ios

I'm using SwityJSON to iterate through my JSON data and parse it. It's working fine, but I would like to make sure I'm using the syntax correctly and efficiently. Please review my code below:
if let itemDict = json[0]["artists"].dictionaryValue {
for item in itemDict {
if let artist: Dictionary? = item.1.dictionaryValue {
// artist id
if let artistId = artist?["id"] {
if artistId.stringValue != nil {
// add value to object
}
}
// title
if let title = artist?["title"] {
if title.stringValue != nil {
// add value to object
}
}
// subtitle
if let subtitle = artist?["subtitle"] {
if subtitle.stringValue != nil {
// add value to object
}
}
// image url
if let imageURL = artist?["imageURL"] {
if imageURL.stringValue != nil {
// add value to object
}
}
}
}
}

This is new for all but Ray Wenderlich has provided good tutorial. Try to learn from it. It helped me a lot.

Related

Realm List not saving data

I am fetching data from FireBase and save it inside my realm but it is not working as expected :
for doc in docs {
let shopData = doc.data()
let newShop = RLMShop()
newShop.shopName = shopData["name"] as? String ?? "Empty Name"
self.saveShop(shop: newShop) // My issue is here
}
My saveShop function :
func saveShop(shop: RLMShop) {
do {
try realm.write {
realm.add(shop)
}
} catch {
print("Error saving shop \(error)")
}
}
Calling save function is not saving my object.
The problem you have is that you are creating a RLMShop object but it is not linked to a RLMShopsCategory object, therefore your shopsList will not contain the new object.
// Fetch the RLMShopsCategory that you wish to add the RLMShop too
// Using Primary Key here just as an example
let shopsCategory = realm.object(ofType: RLMShopsCategory.self, forPrimaryKey: "YourKey")
for doc in docs {
let shopData = doc.data()
let newShop = RLMShop()
newShop.shopName = // setting the properties etc
// This is the part you are missing
// You need to append the newShop to your shopsCategory object
try! realm.write {
shopsCategory.shopsList.append(newShop)
}
}

Is there a better way to remove all annotations from PDF document?

I need to remove all annotations from PDF document using PDFKit.
Here is my solution:
This solution doesn't work for me, because in one case im getting exception when mutating array while iteration on it.
func removeAllAnnotations() {
guard let documentCheck = document else { return }
for i in (0..<documentCheck.pageCount) {
if let page = documentCheck.page(at: i) {
for annotation in page.annotations {
page.removeAnnotation(annotation)
}
}
}
}
If you want to avoid the “mutate while iterating” problem, just create your own local copy of the array, and iterate through that:
func removeAllAnnotations() {
guard let document = document else { return }
for i in 0..<document.pageCount {
if let page = document.page(at: i) {
let annotations = page.annotations
for annotation in annotations {
page.removeAnnotation(annotation)
}
}
}
}
But, no, I don’t know of any better way to remove all annotations.
This is the objective-C solution, I came up with. This function will not encounter the “mutate while iterating” crash! Hope this will be helpful to someone.
- (void)removeAllAnnotations {
if (self.pdfDocument) {
for (int i = 0; i < self.pdfDocument.pageCount; i++) {
PDFPage *page = [self.pdfDocument pageAtIndex:i];
PDFAnnotation *annotation = page.annotations.lastObject;
while (annotation) {
[page removeAnnotation:annotation];
annotation = page.annotations.lastObject;
}
}
}
}

Error adding Firestore documents to Pickerview

I've recently changed a lot on my iOS application and now I got stuck.
I'm trying to insert data from Firestore which looks like this:
So, as you can see I've 6 different names in here.
And here is the code to insert into pickerView.
func getPerson()
{
let authentication = Auth.auth().currentUser?.uid
db.collection("users").document(authentication!).collection("person").getDocuments { (QuerySnapshot, err) in
//If error is not equal to nil
if err != nil
{
print("Error getting documents: \(String(describing: err))");
}
//Succeded
else
{
//For-loop
for _ in QuerySnapshot!.documents
{
//Cleaning the array for the new values
self.personArray.removeAll()
let document = QuerySnapshot!.documents
let data = document.data() //HERE IS THE ERROR
data.forEach { (item) in
if let person1Data = data["name"] as? String
{
self.personArray.append(person1Data)
print(self.personArray)
}
}
}
self.pickerView.reloadAllComponents()
}
}
}
I'm getting the error:
Value of type '[QueryDocumentSnapshot]' has no member 'data'
It used to have QuerySnapshot!.documents.first
but it does not work anymore when I've changed the Firestore data.
Edit:
So. the output is now:
["Joche"] ["Joche", "Joche"] ["Putte"] ["Putte", "Putte"] ["Rebecca"]
["Rebecca", "Rebecca"] ["Fredrik"] ["Fredrik", "Fredrik"] ["Anna"]
["Anna", "Anna"] ["Vickan"] ["Vickan", "Vickan"]
which means it adds everything but x3. How to solve this problem?
data is an instance method of a single QueryDocumentSnapshot not an array , You need
self.personArray.removeAll()
for elem in querySnapshot!.documents {
let data = elem.document.data()
data.forEach {
if let person1Data = $0["name"] as? String {
self.personArray.append(person1Data)
print(self.personArray)
}
}
}

how to update realm object based on the certain property in Realm?

I have products in my Realm database like this
I want to update my realm database based on productID, so I don't need to add another product over and over again. let say I want to update quantity of product that has productID = "a" to be 5.
I have tried to write something like this.
let selectedProductID = "a"
let productsInRealmDatabase = realm.objects(Product.self)
let productIndex = productsInRealmDatabase.index(where: {$0.productID == selectedProductID})
if let productIndex = productIndex {
do {
try realm.write {
var productRealm = productsInRealmDatabase[productIndex]
productRealm.quantity = 5
productsInRealmDatabase[productIndex] = productRealm // ERROR HERE
}
} catch {
// error Handling
}
}
but I got error in : productsInRealmDatabase[productIndex] = productRealm
Error Message: Cannot assign through subscript: subscript is get-only
so how to update realm object based on the certain property in Realm?
You should use Realm's own filter method which accepts an NSPredicate and returns an auto-updating Results instance rather than Swift's filter when operating on Realm collections. Than either update the properties of the fetched prouduct or create a new one and save that to Realm.
let selectedProductID = "a"
let productsInRealmDatabase = realm.objects(Product.self)
let matchingProduct = productsInRealmDatabase.filter("productID == %#", selectedProductID).first
if let matchingProduct = matchingProduct {
do {
try realm.write {
matchingProduct.quantity = 5
}
} catch {
// error Handling
}
} else {
let newProduct = Product()
newProduct.productID = selectedProductID
newProduct.quantity = 5
do {
try realm.write {
realm.add(newProduct)
}
} catch {
// error Handling
}
}
If you want your Products to be unique based on their productID property, you use also set productID as the primaryKey of your Object subclass.
class Product:Object {
#objc dynamic var productID = ""
...
override static func primaryKey() -> String? {
return "productID"
}
}
Try this -
let selectedProductID = "a"
let productsInRealmDatabase = realm.objects(Product.self)
let filteredProducts = productsInRealmDatabase.filter("productID = \(selectedProductID)")
do {
try realm.write {
filteredProducts.forEach { product in
product.quantity = 5
}
}
} catch {
// error Handling
}
While inserting data to your database inside the insert function mark update key as true and then try updating the value. eg:
static func insertData() {
//Your insertion code//
try! realm.write {
realm.add(request, update: true)
}
}
static func updateData(productId: String, quantity: Int) {
let product = self.getProductData(prodId: productId)
let realm = try! Realm()
try! realm.write {
product?.quantity = quantity
}
}
Hope this helps you out.

Add / Update custom object dictionaries array in swift 4

I have an array of dictionary with custom object in swift.
Now I am comparing the object for add & update.
The logic is as simple to add the data if not exist and update if any change in dictionary.
User is custom object type:
#objc public class User: NSObject , Mappable
from the getUserID i can able to get userID
The below code is execute in for loop from where i am passing User object.
var peopleList = [User]()
if self.peopleList.count > 0 {
if self.peopleList.contains(where: {$0.getUserID() == users.getUserID()})
{
// check for any update in dist
if let index = self.peopleList.index(of: users)
{
if users.isEqual(self.peopleList[index])
{
print("equal no updates")
}
else
{
print("need to updates objects..")
}
}
//already exist room
}
else
{
self.peopleList.append(users)
}
}
I know it may be related to equatable
so I am using below fuction
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool? {
guard let a = a as? T, let b = b as? T else { return nil }
return a == b
}
But I am getting index = nil.
Is there any idea or suggestion to solve it.
If any other way to do it efficiently them most welcome.
I think this simplified version should work
if self.peopleList.isEmpty, let user = self.peopleList.first(where: { $0.getUserID() == users.getUserID() }) {
if user == users {
// is equal
} else {
// do update
}
} else {
self.peopleList.append(users)
}

Resources