How Do I Create An Array With Multiple Variables In Swift - ios

I am new to iOS development, and for some reason I can't figure out how to do this even though I realize it has to be simple. I want to create a collection with 2 string values. For instance:
var firstName = "Bob"
var lastName = "Smith"
So the first index would contain ("Bob", "Smith") and so one for each first and last name I want to add to the collection. What object do I use? I tried a dictionary but it seems you have to add your values to that up front, and I need to add my later on programmatically.

You could use a dictionary but I'd create a Person struct that contains a firstName and a lastName and put those into an array.
struct Person {
var firstName: String
var lastName: String
}
var firstName = "Bob"
var lastName = "Smith"
var array = [Person(firstName: firstName, lastName: lastName)]
It also has the benefit of being able to access the parts using .firstName and .lastName
array[0].firstName
As opposed to a dictionary that that requires a string
array[0]["firstName"]

To create an array with only string you use
var shoppingList: [String] = ["Eggs", "Milk"]
And to add to the end of the array (push) you use
shoppingList.append("Bread")

The struct way is preferred, but if you want to do something more similar to the initial request you could do an array of tuples

Related

Using Generic in iOS

I am new to iOS development . I wanted to create a dictionary which is looks like
var userInformation: UserInformation = UserInformation()
var genericDictionary: Dictionary<Int,userInformation> = [Int:userInformation]()
here ,userInformation is an object of UserInformation class .
class UserInformation{
var name:String?
var phonenumber:String?
init(_ name:String ,_phoneNumber:String){
self.name = name
self.phoneNumber = phoneNumber
}
and lastly i tried genericDictionary.append(). i wanted to store name and phone number here. i don't know how it works!
i tried , but it shows various kinds of error. is it possible to do this ?
Problem is in declaration of dictionary with value type you are specifying the object that you have created instead of its type, means it should be UserInformation class type instead of instance of it userInformation. Try like this way.
var genericDictionary = [Int:UserInformation]()
Edit: With latest edit of your question I thin'k you are looking for array not dictionary, if it is true try like this way.
var array = [UserInformation]()
array.append(userInformation)
Do like this :
var genericDictionary : [Int : UserInformation] = [:]
You are declaring the dictionary using a variable instead of the class. Instead of userInformation, you need to use UserInformation like this:
var genericDictionary: Dictionary<Int,UserInformation> = [Int:UserInformation]()

Swift3: Using Two Arrays to populate grouped Table

I currently have two populated arrays using a custom struct.
struct Group {
var id: String
var type: String
var desc: String
var name: String
init() {
id = ""
type = ""
desc = ""
name = ""
}
}
Data gets appended to:
var clientArray: [Group] = []
var departmentArray: [Group] = []
I essentially want to join them together to have the format something like [[clientArray], [departmentArray]] so I can use "section" and populate two different groups on a table with the respective arrays.
So far I've tried the following, but I get the error "fatal error: index out of range".
var masterArray = [[Group]]()
//Then further down the page...
self.masterArray[0] = self.clientArray
self.masterArray[1] = self.departmentArray
How can I get this to work? Thanks for any help.
You could write:
var masterArray = [self.clientArray, self.departmentArray]
Otherwise use append:. The docs state:
You can’t use subscript syntax to append a new item to the end of an
array.

Populate List in Swift 2.0 and display results

I've been learning iOS development for the past three weeks, I'm currently following a course on Udemy so far so good.
However I'm following one of the lectures whereby we build an Instagram Clone.
The instructor is using three arrays which are as follows:
var usernames = [""] // Stores all usernames
var userIds = [""] // Stores all Id's of the given usernames
var isFollowing = [false] // Stores where or not you're following that user
To me trying to keep track of what userId goes with what username using two arrays is basically an accident waiting to happen so I decided to set off and find a more feasible approach. I reverted back to my .Net days and decided to create a list so I went and created a class as follows:
class Users{
var Username : NSString = ""
var UserId : NSString = ""
var Following : Bool = false
}
Now inside my ViewController I make a call to Parse which returns me a list of users and I'm basically trying to loop through the response, and add them to the list class as shown here:
var t = [Users]() // After googling the web, this seems to be the syntax for a list declaration ?
let u = Users()
for object in users{
if let o = object as? PFUser {
u.Username = o.username!
u.UserId = o.objectId!
u.Following = o.IsFollowing!
self.t.append(u)
}
}
print(self.t)
Now when I print this to the console I see the following:
ParseStarterProject_Swift.Users
As I have one user at present, however when I try to loop through T and display the username in the console it doesn't display anything.
for x in t {
print(x.Username)
}
Your basic intuition is correct, it's better to have an array of custom objects, not multiple arrays.
Regarding making it more Swifty, consider your Users type. You might want something like:
struct User {
let username: String
let userId: String
let following: Bool
}
Note,
property names should start with lowercase letter;
Users should probably be called User, as it represents a single user;
we don't generally initialize values to default values like that, but rather specify them in the initializer;
we probably use String not NSString;
if a property cannot change, you'd use let, not var;
properties begin with lower case letters;
Then you can do something like:
var t = [User]()
for object in users {
if let o = object as? PFUser {
t.append(User(username: o.username!, userId: o.objectId!, following: o.IsFollowing!)
}
}
print(t)
Clearly, with all of those ! forced unwrapping operators, you'd want to be confident that those fields were populated for all of those properties.
Using struct is nice because (a) it's a value type; (b) you get the initializer for free; and (c) you can just print them. If you really wanted User to be a reference type (a class), you'd do something like:
class User {
let username: String
let userId: String
let following: Bool
init(username: String, userId: String, following: Bool) {
self.username = username
self.userId = userId
self.following = following
}
}
And if you wanted to be able to just print them, you'd define it to conform to CustomStringConvertible:
extension User: CustomStringConvertible {
var description: String { return "<User; username = \(username); userId = \(userId); following = \(following)>" }
}
With the class, you can feel free to change that description computed property to show it in whatever format you want, but it illustrates the idea.
You are correct in considering that keeping track of what userId goes with what username using two arrays is dangerous, you in the correct direction with your approach.
First, I would just like to suggest that you use correct naming convention:
Classes should be singular (except in very specific cases).
Variable/property names should begin with lowercase.
This would mean that your user class should look like this:
class User {
var username : NSString = ""
var userId : NSString = ""
var following : Bool = false
}
I will keep your existing naming use for the next part. The main problem with your code is that the variable "u" is a object which you create only once and then modify it. You should be creating a new "Users" object for each user instead of modifying the original. If you don't do this you will just have an array with the same user multiple times. This is how your code would look now:
var t = [Users]()
for object in users {
if let o = object as? PFUser {
let u = Users()
u.Username = o.username!
u.UserId = o.objectId!
u.Following = o.IsFollowing!
self.t.append(u)
}
}
print(self.t)
Next you mention that when you print to console you see the text: ParseStarterProject_Swift.Users, that is because Swift does not automatically print a pretty text with the content of your object. In order for it to print something more detailed, your "Users" object would need to implement the CustomStringConvertible. You can see a more detailed answer about that here: how-can-i-change-the-textual-representation-displayed-for-a-type-in-swif.
Lastly, you mention that when you loop trough "t" and display the username in the console it does not display anything. This is caused by one of two things:
Because there are no users being returned from parse, so the "t" array is actually empty. Try print(t.count) to see how many objects are in the array.
Because your "Users" object declares an empty string "" as the default username and the username is not being set correctly when getting the data from the parse. Which means that it IS actually printing something, just that it is an empty string. Try defining a different default value like var username : NSString = "Undefined" to see if it prints something.
Good luck learning swift!

Swift. Refer to instance variables by string name

I've got a number of user properties in a user viewcontroller class ie
//user vars
var email: String?
var givenName: String?
var familyName:String?
var phone: String?
var dob: NSDate?
In a method within that class i retrieve user data from coredata and set the user text fields with that data in a loop
for i in 0 ..< userTextFields.count {
let field = userTextFields[i]
let fieldName = userTextFieldKeyNames[i]
let fieldText = currentUser.valueForKey(fieldName) as? String
field.text = fieldText
}
the fieldName variable in the loop matches the class's ivars above. Is there a way i can reference the ivars within the loop by matching it with the fieldName string so I can set the values of the ivars with the fetched coredata values ie in a literal sense saying something like the following ...
if self.property.name.text == fieldName {
self.property.value == fieldText
}
ie somehow resolving the various property names withing the class ... or is this bad design? .... if so any suggestions on achieving the same result in a better way
Not Swift-ish, as it's bypassing compile time type checking. Best option is to keep them all in a dictionary, and use a protocol to define allowed data types in the dictionary, but even that is rather poor

Populate Class Properties via 1 line within a for loop?

Let's say I have a class that has 10 properties. I have an XML response (AEXMLDocument in this case) where the element tags match the property names exactly. Is there a way I could populate the values in a for loop rather than writing out 10 lines of code? I used ***property.name**** to show where I would like to put these variables. That part is not actually in the code.
class User(){
var firstName = String()
var lastName = String()
var middleName = String()
...
var property10 = String()
}
func populateUser (xml: AEXMLDocument) -> User{
var returnUser = User()
for property in xml.root["SOAP-ENV:Body"]["ns1:getUserResponse"]["return"].children{
returnUser.***property.name*** = property.value
}
return returnUser
You can use setValue(_, forKey:) method as long as you subclass from NSObject.
If the class inherits from NSObject, you can use key-value coding:
returnUser.setValue(property.value, forKey: property.name)
Be careful with this though. Anyone who can modify the XML sent to your app can modify any property on the User object.

Resources