I am using this code to add custom objects to an array and then display that data in a custom TableView.
var tempCount = self.people?.count
for var k = 0 ; k < tempCount ; k++
{
if let PERSON = self.people?[k]
{
let name = (PERSON.compositeName != nil) ? PERSON.compositeName : ""
let number = (PERSON.phoneNumbers?.first?.value != nil) ? PERSON.phoneNumbers?.first?.value : ""
let image = (PERSON.image != nil) ? PERSON.image : UIImage(named: "aks.jpg")
let details = Contact(userImage: image!, userName: name!, phoneNumber: number!)
println(details.userName + " " + details.phoneNumber)
self.arrayOfContacts?.append(details)
println(self.arrayOfContacts?.count)
}
}
The count of the elements in the array always seems to be 'nil' for some reason. I have declared the array in the following manner
var arrayOfContacts:[Contact]?
, Contact being the type of Object that array is supposed to contain.
and the other one as
var people : [SwiftAddressBookPerson]? = []
The print statement does give out results but the object never gets added into the array.
Any idea about what I am doing wrong would be greatly helpful.
Your array is declared as an Optional array but is not created so it's nil.
Your declaration:
var arrayOfContacts:[Contact]?
Add the creation of an actual empty array:
arrayOfContacts = []
Or create it at once altogether:
var arrayOfContacts:[Contact]? = []
Your arrayOfContacts is nil, so arrayOfContacts?.count is nil as well.
If you really want to append to arrayOfContacts, don't write self.arrayOfContacts?.append(details) because this means "append to arrayOfContacts but actually I don't really care and if arrayOfContacts is nil, just give up".
Instead, write self.arrayOfContacts!.append(details), because now this means "append to arrayOfContacts, and since I really do care, tell me hard and loud, with a fatal crashing error, when arrayOfContacts is nil because well I'll have to figure out why on hell this array is nil when it should not be. I mean, I'm the master of the machine, not the opposite, and I know quite well that arrayOfContacts ought to be not nil when I want to append to it."
Often when you’re dealing with data you don’t just have a fixed amount of elements. Take for example a program where you compute the average of multiple grades in a class:
var grade1 = 4
var grade2 = 3
var average = Double(grade1 + grade2) / 2.0
println("Average grade: \(average)")
What if we wanted the program to also work when we have 3 grades?
We’d have to change our program to work with 3 grades.
var grade1 = 4
var grade2 = 3
var grade3 = 5
var average = Double(grade1 + grade2 + grade3) / 3.0
println("Average grade: \(average\)")
Related
I have an array myarray and I am using a for loop to get a few information which I add to myarray. But next time the for-loop runs, I don't want to create a separate index, but instead the 2nd time and so on, I want to append the information to myarray[0].
How do I do that?
var myarray = [String]()
for var j in 0 < 12 {
// do some stuff
for var i in 0 ..< 10 {
let parta = json?["users"][j]["name"].string
let partb = json?["users"][j]["Lname"].string
let partc = json?["users"][j]["dob"].string
myarray.append("\(parta)-\(partb)-\(partc)---")
// Here when the for loop comes back again (i = 1) , i dont want to make
// myarray[1] , but instead i want myarray[0] ,
// having value like [parta-partb-partc--parta-partb-partc]
}
}
Basically what I am trying to do is, append the new name/lname/dob values at myarray[0] without affecting the current value/string at myarray[0].
You can insert single element and also add array as below.
Swift 5
var myarray = [String]()
myarray.insert("NewElement", at: 0)
myarray.insert(contentsOf: ["First", "Second", "Third"], at: 0)
If I understand your question correctly, you want to create one long string and add the new data always at the beginning of the string. One way to do that would be:
// Store somewhere
var myString = String()
for var i in(0..<10) {
let parta = json?["name"].string
let partb = json?["Lname"].string
let partc = json?["dob"].string
let newString = "\(parta)-\(partb)-\(partc)---")
newString.append(myString)
myString = newString
// Here when the for loop comes back again (i = 1) , i dont want to make
//myarray[1] , but instead i want myarray[0] ,
//having value like [parta-partb-partc--parta-partb-partc]
}
I'm new in swift and I'd know how to do that in php, but I'm lost with all those dictionaries and I have no idea how to do that in swift 2. I've been googling for a while and didn't found what I need.
I'm parsing a jSon and storing it's values in an NSMutableDictionary in a loop and at the end of the loop I store the NSMutableDictionary in an NSMutableArray, so at the end I have an NSMutableArray with 43 elements, and each element have about 10 keys with their values. I need to sort those 43 elements from their "distance" key and sort them descending. I don't know if that is posible with this current approach. The value of the key "distance" is an int number (meters). I don't know if to use an NSMutableDictionary inside an NSMutable Array is the correct approach to do this but I'm using it because it is possible to have string keys, and not numbers indexes, so for me it's easier to access the key "distance" than the index 8...
First I load the jSon content:
private func parseJson(json : NSMutableArray, tableView : UITableView){
var c : Int = 0
for j in json {
var jsonValues = NSMutableDictionary()
//Create main value
guard let value = j.valueForKey("value")?.valueForKey("value")! else{
continue
}
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
continue
}
jsonValues["name"] = Name
//more code like this....
TableData.append(Name)
nsDict.insertObject(jsonValues, atIndex: c)
c += 1
}
this is my NSMutableArray content after being loaded:
And this is the code I have this far. Im trying to load the sorted content in a new array, but in this new array some keys are missing.
//Reorder Array by shop distance from user...
var sortDescriptor:NSSortDescriptor = NSSortDescriptor(key: "distance", ascending: true)
var sortedArray : NSArray = nsDict.sortedArrayUsingDescriptors([sortDescriptor])//Crashes
print(sortedArray)
I've managed to sort the array with this technique:
created a new class with for my array
import Foundation
class JsonArrayValues {
init(){
}
var name = String()
var distance = Float()
var lat = Float()
var lng = Float()
var openingTime = String()
var country = String()
var code = String()
var address = String()
var categories = String()
var city = String()
var type = String()
var brands = String()
}
I instantiated one before the loop:
var jsonArrData : [JsonArrayValues] = []
And another one inside the loop, in which I've added the values:
var c : Int = 0
for j in json {
var jsonValues : JsonArrayValues = JsonArrayValues()
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
continue
}
jsonValues.name = Name
//more code...
jsonArrData.append(jsonValues)
c += 1
}
And finally I've been able to call the function to reorder the array:
//Reorder Array by shop distance from user...
jsonArrData.sortInPlace({$0.distance < $1.distance})
One of your first steps in any non-trivial project really should be to spend some time looking around on github for tools that simplify your problem. In this case, you'd find there are so very many tools to simplify working with JSON in Swift. I'd suggest you look at EVReflection and Gloss particularly, although there are also many people who use SwiftyJSON.
You don't mention how you're accessing the network; you could look at AFNetworking or Alamofire. The latter also has AlamofireJsonToObjects to help.
I also found JSONExport to be incredibly useful.
You'd be spending a lot less time futzing with details as in this unfortunate question and more getting on with your larger goal.
I know I can initialize an array of Ints for example like:
var intArray = [Int](count: 10, repeatedValue: 0)
What I want to do is something like this:
var array = Array(count:6, repeatedValue:Array(count:0, repeatedValue:AnyObject()))
(Xcode returns with: AnyObject cannot be constructed because it has no accessible initializers)
With the same outcome as I could initialize the array like:
var anyObjectArray : [[AnyObject]] = [[],[],[],[],[],[]]
But doing the above is ugly if i need like 100 rows of lets say 3
The problem is I can append in my function like:
// init array
var anyObjectArray : [[AnyObject]] = [[],[],[]]
//inside a for loop
anyObjectArray[i].append(someValue)
That works ok, until of course i gets higher then the number of rows in the array.
A answer to this problem is also acceptable if I could do something like:
anyObjectArray[append a empty row here][]
But that is probably stupid :)
I hope there is a way to do this cause I don't feel like having a line like:
var anyObjectArray : [[AnyObject]] = [ [],[],[],[],[],[],[],[],[],[],[],[],[],[],[], ... etc ]
at the top of my page ;)
Thank you for your time!
You don't need the second repeatedValue initialiser, since you want an empty array. You can just use
var array = Array(count:6, repeatedValue:[AnyObject]())
You can try with 2 loops, working as a grid :
var items: = Array<Array<Item>>()
for col in 0..<maxCol {
var colItems = Array<Item>()
for row in 0..<maxRow {
colItems.append(Item())
}
items.append(colItems)
}
//Append as much as you want after
Try this
let columns = 27
let rows = 52
var array = Array<Array<Double>>()
for column in 0... columns {
array.append(Array(count:rows, repeatedValue:Int()))
}
Try using this
let array = Array(count:6, repeatedValue:[])
for (var i=0; i<array.count; i++){
array[i] = Array(count:0, repeatedValue: AnyObject.self)
}
in place of your code.
Swift 3:
var array = Array(repeating:[AnyObject](),count:6)
I have a question. I know that this can be done in Ruby, not sure about Swift, but never did anything similar.
What I'm working on is a program that works similar to this: if the user writes in a TextView "a + b", my code should elaborate the value of the sum between the variable "a" and "b".
What I mean is, how can I get variable names from a string? Is it possible at all?
If it's not, I'd use a switch (variable names are limited), but I'd need to "connect" a variable to the one written by the user. In the example, if the user writes "a + b", my sum function is something like "sum(par1,par2)", so, how can I make variable "par1" point to "a" and "par2" point to "b"? I can do that with pointers right? Is there any other way?
I'm not sure I've been clear, but it's quite hard to explain
Check this out. You can do with NSExpression and KVC.
class myclass:NSObject {
var a = 10;
var b = 20;
override init() {
super.init();
}
}
var obj = myclass();
// Expression from user
var expr:NSString = "a+b" ;
//Operators..
let opSet = NSMutableCharacterSet()
opSet.addCharactersInString("+-*/");
let components:NSArray = expr.componentsSeparatedByCharactersInSet(opSet)
let uniqueChars:NSSet = NSSet(array: components)
for variable in uniqueChars
{
expr = expr.stringByReplacingOccurrencesOfString ( variable as String,
withString : NSString(format: "%d", obj.valueForKey(variable as String) as Int),
options : NSStringCompareOptions.LiteralSearch,
range : NSMakeRange(0,expr.length) );
}
var result: AnyObject = NSExpression(format: expr).expressionValueWithObject(nil, context: nil)
print (result);
is there a possibility to get an object from an array with an specific property? Or do i need to loop trough all objects in my array and check if an property is the specific i was looking for?
edit: Thanks for given me into the correct direction, but i have a problem to convert this.
// edit again: A ok, and if there is only one specific result? Is this also a possible method do to that?
let imageUUID = sender.imageUUID
let questionImageObjects = self.formImages[currentSelectedQuestion.qIndex] as [Images]!
// this is working
//var imageObject:Images!
/*
for (index, image) in enumerate(questionImageObjects) {
if(image.imageUUID == imageUUID) {
imageObject = image
}
}
*/
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
var imageObject = questionImageObjects.filter( { return $0.imageUUID == imageUUID } )
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
You have no way to prove at compile-time that there is only one possible result on an array. What you're actually asking for is the first matching result. The easiest (though not the fastest) is to just take the first element of the result of filter:
let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first
imageObject will now be an optional of course, since it's possible that nothing matches.
If searching the whole array is time consuming, of course you can easily create a firstMatching function that will return the (optional) first element matching the closure, but for short arrays this is fine and simple.
As charles notes, in Swift 3 this is built in:
questionImageObjects.first(where: { $0.imageUUID == imageUUID })
Edit 2016-05-05: Swift 3 will include first(where:).
In Swift 2, you can use indexOf to find the index of the first array element that matches a predicate.
let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})
This is bit faster compared to filter since it will stop after the first match. (Alternatively, you could use a lazy sequence.)
However, it's a bit annoying that you can only get the index and not the object itself. I use the following extension for convenience:
extension CollectionType {
func find(#noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
return try indexOf(predicate).map({self[$0]})
}
}
Then the following works:
questionImageObjects.find({$0.imageUUID == imageUUID})
Yes, you can use the filter method which takes a closure where you can set your logical expression.
Example:
struct User {
var firstName: String?
var lastName: String?
}
let users = [User(firstName: "John", lastName: "Doe"), User(firstName: "Bill", lastName: "Clinton"), User(firstName: "John", lastName: "Travolta")];
let johns = users.filter( { return $0.firstName == "John" } )
Note that filter returns an array containing all items satisfying the logical expression.
More info in the Library Reference
Here is a working example in Swift 5
class Point{
var x:Int
var y:Int
init(x:Int, y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x:1, y:2)
var p2 = Point(x:2, y:3)
var p3 = Point(x:1, y:4)
var points = [p1, p2, p3]
// Find the first object with given property
// In this case, firstMatchingPoint becomes p1
let firstMatchingPoint = points.first{$0.x == 1}
// Find all objects with given property
// In this case, allMatchingPoints becomes [p1, p3]
let allMatchingPoints = points.filter{$0.x == 1}
Reference:
Trailing Closure
Here is other way to fetch particular object by using object property to search an object in array.
if arrayTicketsListing.contains({ $0.status_id == "2" }) {
let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!]
print(ticketStatusObj.status_name)
}
Whereas, my arrayTicketsListing is [TicketsStatusList] contains objects of TicketsStatusList class.
// TicketsStatusList class
class TicketsStatusList {
internal var status_id: String
internal var status_name: String
init(){
status_id = ""
status_name = ""
}
}