I'm trying to access the url of an object stored in an array, but I'm getting errors no matters what methods I'm using.
let userPhotos = currentUser?.photos
for var i = 0; i < userPhotos!.count ; ++i {
let url = userPhotos[i].url
}
Here I get
Could not find member 'url'
and with a foreach:
for photo in userPhotos {
Utils.getImageAsync(photo.url , completion: { (img: UIImage?) -> () in
})
}
I get:
'[ModelAttachment]?' does not have a member named 'Generator'
My array is var photos: Array<ModelAttachment>? and my ModelAttachment looks like this:
class ModelAttachment :Model {
var id: String?
var url: String?
var thumb: String?
}
Any pointers to what I'm doing wrong would be great :)
Unwrap and downcast the objects to the right type, safely, with if let, before doing the iteration with a simple for in loop.
if let currentUser = currentUser,
let photos = currentUser.photos as? [ModelAttachment]
{
for object in photos {
let url = object.url
}
}
There's also guard let else instead of if let if you prefer having the result available in scope:
guard let currentUser = currentUser,
let photos = currentUser.photos as? [ModelAttachment] else
{
// break or return
}
// now 'photos' is available outside the guard
for object in photos {
let url = object.url
}
Your userPhotos array is option-typed, you should retrieve the actual underlying object with ! (if you want an error in case the object isn't there) or ? (if you want to receive nil in url):
let userPhotos = currentUser?.photos
for var i = 0; i < userPhotos!.count ; ++i {
let url = userPhotos![i].url
}
But to preserve safe nil handling, you better use functional approach, for instance, with map, like this:
let urls = userPhotos?.map{ $0.url }
You can try using the simple NSArray in syntax for iterating over the array in swift which makes for shorter code.
The following is working for me:
class ModelAttachment {
var id: String?
var url: String?
var thumb: String?
}
var modelAttachementObj = ModelAttachment()
modelAttachementObj.id = "1"
modelAttachementObj.url = "http://www.google.com"
modelAttachementObj.thumb = "thumb"
var imgs: Array<ModelAttachment> = [modelAttachementObj]
for img in imgs {
let url = img.url
NSLog(url!)
}
See docs here
The photos property is an optional array and must be unwrapped before accessing its elements (the same as you do to get the count property of the array):
for var i = 0; i < userPhotos!.count ; ++i {
let url = userPhotos![i].url
}
Related
The function to use a set of Realm objects is always random.
Primary keys must not be changed and they must be unique.
So I added another variable for compare.
And I override isEqual(:) function.
See below my code.
class Model: Object {
#objc dynamic var key = ""
#objc dynamic var id = ""
override static func primaryKey() -> String? {
return "key"
}
override func isEqual(_ object: Any?) -> Bool {
if let object = object as? Model {
return id == object.id
} else {
return false
}
}
}
let model1 = Model()
model1.key = UUID().uuidString
model1.id = "hi"
let model2 = Model()
model2.key = UUID().uuidString
model2.id = "hi"
let model1Array = [model1]
let model2Array = [model2]
let set1 = Set(model1Array)
let set2 = Set(model2Array)
let result = set1.intersection(set2)
print(result) // []
let result = set1.intersection(set2)
print(result) // [Model { key = 9E814B97-D0CC-4550-BF7B-19645C1DB746; id = hi; }]
let result = set1.intersection(set2)
print(result) // []
let result = set1.intersection(set2)
print(result) // []
let result = set1.intersection(set2)
print(result) // [Model { key = 8A399388-1FA2-4699-8258-5DA5DFCEC203; id = hi; }]
Every time I run, the values come out randomly.
What did I do wrong?
For Set to work correctly, your objects need to have a correct implementation of Hashable. The Realm Object already implements Hashable, and presumably, the == implementation calls isEqual.
However, the hash should be consistent with isEqual as well, but you haven't overridden hash yet. You should implement hash such that two equal objects (as determined by isEqual) have equal hashes.
One way is to do it like this:
override var hash: Int {
return id.hash
}
I am getting data from a website using rss. I want to set those datas to the variables in struct but I am getting an error in for loop.
struct News {
var title: String
var link: String
}
class HaberTableViewController: UITableViewController, XMLParserDelegate {
var NewsArray:[News] = []
override func viewDidLoad() {
let url = "http://www.ensonhaber.com/rss/ensonhaber.xml"
Alamofire.request(url).responseRSS() { (response) -> Void in
if let feed: RSSFeed = response.result.value {
for item in feed.items {
print(item.title!)
for n in self.NewsArray
{
n.title.append(item.title)
n.link.append(item.link)
}
}
}
}
}
.
.
.
}
I think you are trying to populate the NewArray array with new News instances using values from feed.items. If that's the case then your code should be:
if let feed: RSSFeed = response.result.value {
for item in feed.items {
if let title = item.title, let link = item.link {
let news = News(title: title, link: link)
NewsArray.append(news)
}
}
}
Note that this also deals with item.title (and presumably item.link) being optional.
Please note that variable names should start with lowercase letters so NewsArray should be newsArray.
I have code:
struct FilesToDownload {
var fileInternetUrl: String?
var fileName: String?
var savedURL: String?
var productImageUrl: URL?
var fileSize: Int
}
var filesToDownload = [FilesToDownload]()
let fileToDelete = "img1000.jpg"
How can I delete one, selected file from array (to delete: fileToDelete)?
You can try
filesToDownload = filesToDownload.filter { $0.fileName != fileToDelete }
Get the index of the object that you want to delete and remove it:
var filesToDownload = [FilesToDownload]()
let fileToDelete = "img1000.jpg"
// get the index or nil if the array does not contain a file with the given name
let fileToDeleteIndex = filesToDownload.index { $0.fileName == fileToDelete }
// if there is a file -> delete it
if let fileToDeleteIndex = fileToDeleteIndex {
filesToDownload.remove(at: fileToDeleteIndex)
}
First find targeted item index and delet. simple!!
if let index = filesToDownload.index(where: {$0.fileName == fileToDelete} ) {
filesToDownload.remove(at: index)
}
With Swift is it possible to create a dictionary of [String:[Object]] from an array of objects [Object] using a property of those objects as the String key for the dictionary using swift's "map"?
class Contact:NSObject {
var id:String = ""
var name:String = ""
var phone:String = ""
init(id:String, name:String, phone:String){
self.id = id
self.name = name
self.phone = phone
}
}
var contactsArray:[Contact]
var contactsDict:[String:Contact]
contactsDict = (contactsArray as Array).map { ...WHAT GOES HERE... }
Let's say you want to use id as the key for the dictionary:
var contactsArray = [Contact]()
// add to contactsArray
var contactsDict = [String: Contact]()
contactsArray.forEach {
contactsDict[$0.id] = $0
}
The difference between map and forEach is that map returns an array. forEach doesn't return anything.
You can achieve this via reduce in a one-line functional-style code:
let contactsDict = contactsArray.reduce([String:Contact]()) { var d = $0; d[$1.id] = $1; return d; }
This also keeps contactsDict immutable, which is the preferred way to handle variables in Swift.
Or, if you want to get fancy, you can overload the + operator for dictionaries, and make use of that:
func +<K,V>(lhs: [K:V], rhs: Contact) -> [K:V] {
var result = lhs
result[rhs.0] = rhs.1
return result
}
let contactsDict = contacts.reduce([String:Contact]()) { $0 + ($1.id, $1) }
Swift 4
There's now a direct way to do this:
https://developer.apple.com/documentation/swift/dictionary/3127163-init
It's an initializer for Dictionary that lets you return a string key for each element in a Collection that specifies how it should be grouped in the resulting Dictionary.
Hey I just want to save my NSMutableArray with Class. But When i try to read the file my app getting crush. I found this and i tried to convert for NSMutableArray. Now I cant figure out what can i do.
My Class:
class Customer {
var name = String()
var email = String()
var phoneNumber = Int()
var bAdd = String()
var bAdd2 = String()
var sAdd = String()
var sAdd2 = String()
init(name: String, email: String, phoneNumber: Int, bAdd: String, bAdd2: String, sAdd: String, sAdd2: String) {
self.name = name
self.email = email
self.phoneNumber = phoneNumber
self.bAdd = bAdd
self.bAdd2 = bAdd2
self.sAdd = sAdd
self.sAdd2 = sAdd2
}
class func exists (path: String) -> Bool {
return NSFileManager().fileExistsAtPath(path)
}
class func read (path: String) -> NSMutableArray? {
if Customer.exists(path) {
return NSMutableArray(contentsOfFile: path)!
}
return nil
}
class func write (path: String, content: NSMutableArray) -> Bool {
return content.writeToFile(path, atomically: true)
}
}
My Array:
var ItemData:NSMutableArray = NSMutableArray()
and My Read Code:
let documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
let customerPath = documents.stringByAppendingPathComponent("Test.plist")
ItemData = Customer.read(customerPath)!
When i tried to read im gettin this crash:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Any Advice?
Your code works perfectly fine except that you do not actually have anything to read from in the beginning, therefore Customer.read(customerPath) returns nil, which you try to unwrap - therefore the error.
If you just write something beforehand and then try to read it again like this, everything works fine.
ItemData.addObject("aisnd")
Customer.write(customerPath, content: ItemData)
ItemData = Customer.read(customerPath)!
Of course that is not the way to actually do it, because it is normal that you don't have anything present in the beginning. Therefore you have to check wether or not the read function actually returns something useful:
var ItemData:NSMutableArray = NSMutableArray()
if let item = Customer.read(customerPath) {
ItemData = item
} else {
print("no value found")
}
Final note 1 because playground suggested it: remove the ! from the as! String. Final note 2: don't start variable names uppercase, the variable should be called itemData.
Edit
To write Customer objects you have to do something like this.