I am very new to Swift. I have a table view controller in which I have declared the following:
var parts = [String:[String]]() //Key: String, Value: Array of Strings
var partsSectionTitles = [String]()
In my viewDidLoad function, I have:
parts = [
"Part 1" : ["1", "2", "3"],
"Part 2" : ["1", "2"],
"Part 3" : ["1"]
]
//Create an array of the keys in the parts dictionary
partsSectionTitles = [String](parts.keys)
In my cellForRowAtIndexPath function, I have:
let cell = tableView.dequeueReusableCellWithIdentifier("TableCell", forIndexPath: indexPath) as UITableViewCell
var sectionTitle: String = partsSectionTitles[indexPath.section]
var secTitles = parts.values.array[sectionTitle]
cell.textLabel.text = secTitles[indexPath.row]
I am trying to create an array, secTitles, consisting of the values from the parts dictionary that correspond to the keys, sectionTitle. However, I received this error message:
'String' is not convertible to 'Int'
I was able to do it in Objective-C:
NSString *sectionTitle = [partsSectionTitles objectAtIndex:indexPath.section];
NSArray *secTitles = [parts objectForKey:sectionTitle];
Also, I would like to know if I will be able to add/remove the the values in the arrays and dictionaries later on. In other words, are they mutable? I've read a few articles that say Swift arrays and dictionaries aren't actually mutable. I just wanted to know if anyone could confirm that. Thank you in advance for your responses.
You just don't need the values.array:
var chapterTitles = partsOfNovel[sectionTitle]!
Arrays inside dictionaries can be mutated as long as the dictionary itself is mutable, but you'll need to assign through an unwrapping operator:
if partsOfNovel[sectionTitle] != nil {
partsOfNovel[sectionTitle]!.append("foo")
}
Related
I'm a fresher in iOS
I'm unable to compare in an if statement.
It looks like:
for i in 0.. <array.count
{
if(array[i] == array[i+1])
{
let removedVal = array.remove(i+1)
}
}
The error shows on the if condition:
Binary operator '==' cannot be applied to two 'Any' operands
I googled it, but I am unable to understand what should I do in my case.
=======================================================================
Atlast able to find a solution.
And it worked for me
if ( ((tempArrayForTeamName[i]) as AnyObject).isEqual(tempArrayForTeamName[i+1] as AnyObject) )
need to compare array index position as Any object
And use .isEqual replace of ==
You have to Filter your Array
var newarray = [Int]()
let dictionary = ["A":0,"B":1,"C":1,"D":1,"E":1,"F":1,"G":1,"H":1,"J":0]
let newDictionary = dictionary.reduce([:]) { result, element -> [String: Int] in
guard element.value != 1 else {
return result
}
var newResult = result
newResult[element.key] = element.value
newarray.append(newResult[element.key]!)
return newResult
}
In Swift : Array is a Generic Structure, NSMutableArray is an Objective-C class[will work in Swift].
A NSMutableArray created is of type Any; an array that can contain heterogenous object(could be String, Int or Bool).
An Array is arbitrarily specilized to contain Any (using as [Any])
eg:
var array:Array = ["ABC", 123, true] as [Any]
var nsMutableArray : NSMutableArray = ["ABC", 123, true]
Generic Parameterization:
Even if there is an option to give generic parameterization(Datatype) to your NSMutableArray in Objective C[remember NSMutableArray in an Objective C class],this generic parameterization in unfortunately ignored/not allowed in Swift.
How to specify the datatype:
In Swift one cannot specify the datatype of a NSMutableArray.It would give a compilation error: Cannot specialize non-generic type NSMutableArray.
But one can always specify the datatype of Array(Swift structure) as say: Array<String>.
eg: var array:Array<String> = ["Tom", "Jerry", "Spike"]
Your code has another problem, consider your array has 3 items then i=2, and you are trying to access index 3 (i+1). And program will crash.
Crash point (array[i] == array[i+1])
Please declare specific types array for example
let myArray:[String] = ["a", "b", "c", "d"]
I am little bit confuse about, what is the difference between append and addObject.
I am using both in my code but confuse what is the difference between them.
addObject
self.dateArrayServer.addObject(date as! String)
append
dateArrayCalendar.append(dateFormatatter.stringFromDate(dateStart))
And Second problem is
Hi,
I am try to compare two date-
dateArrayForCompare, is the date which i get from NSDate and, dateArrayServer, is the date which i get from json response.
var dateArrayServer = NSMutableArray()
var dateArrayCalendar = NSMutableArray()
var dateArrayForCompare = NSMutableArray()
let dateHomework:NSArray = allAsign.valueForKey("date") as! NSArray
let homeWork = allAsign.valueForKey("assignmenttype") as! NSArray
for date in dateHomework{
self.dateArrayServer.addObject(date as! String)
}
let sys_date = NSDate()
print("System Date: \(sys_date)")
let df = NSDateFormatter()
df.dateFormat = "dd-MM-yyyy"
let currentDate = df.stringFromDate(sys_date)
print("String Date: \(currentDate)")
for dt in 0...self.dateArrayServer.count-1
{
if(self.dateArrayServer.objectAtIndex(dt) .isEqualToString("\(self.dateArrayForCompare)"))
{
print("Assignment on date: \(self.dateArrayServer.objectAtIndex(dt)) are:\n\(allAsign.objectAtIndex(dt))")
}else
{
print("\(self.dateArrayServer.objectAtIndex(dt)) doesn't match with \(self.dateArrayForCompare) ")
}
}
But get this result-
not a major different but i think i can explain it.
in swift two data type declare first "let" and "var" this two type accept all type of data .
but whenever you add array in "var" but not declare this is NSArray or NSMutableArray then you put any object on last position in it then you use append.
appen is like "+=" operator so it add that value on last position
var Array = ["1","2"]
Array.append(["3"])
//Result :- "1","2","3"
But you Declare as
NSMutableArray or NSArray
then you must use addObject like
var Array = NSMutableArray()
Array.addObject("1")
Array.addObject("2")
Array.addObject("3")
//Result :- "1","2","3"
And other different
append is get that value and put on last index .
addObject is get that Object and put on last index
and value and object have different meaning.
Add(anObject: Any) on a NSMutableArray is equal to Append(element: Element) on an array,
Append in documentation:
Adds a new element at the end of the array.
Use this method to append a single element to the end of a mutable array.
var numbers = [1, 2, 3, 4, 5]
numbers.append(100)
print(numbers)
// Prints "[1, 2, 3, 4, 5, 100]"
Because arrays increase their allocated capacity using an exponential
strategy, appending a single element to an array is an O(1) operation
when averaged over many calls to the `append(_:)` method. When an array
has additional capacity and is not sharing its storage with another
instance, appending an element is O(1). When an array needs to
reallocate storage before appending or its storage is shared with
another copy, appending is O(*n*), where *n* is the length of the array.
- Parameter newElement: The element to append to the array.
- Complexity: Amortized O(1) over many additions. If the array uses a
bridged `NSArray` instance as its storage, the efficiency is
unspecified.
Add object in documentation:
The object to add to the end of the array’s content. This value must not be nil.
Difference between append and addObject
Append : It appends your array with multiple items like for exa
var cityArray: String[] = ["Portland","San Francisco","Cupertino","Seattle"]
cityArray.append(["Vancouver", "Los Angeles", "Eugene"])
In append you can add multiple elements at a time
there is a property appendContentsof("collectiontype or sequencetype element") with it you can add multiple elements
AddObject : It add one object at a time at the end of array
but notice that NSArray and NSMutableArray doesn't have property append keyword, So you can not use append in this type of array
Mainly difference between append and addobject with example.
You already know the difference between NSArray and NSMutableArray. NSArray its a fixed array and NSMutablearray is the dynamic Array means you can increase the size of this Array in Run time so its depend on your requirement which one is the best. Because if you are using the NSArray means you don't have required to increase the value in run time then you can use NSArray with append and in Run time You want to increase the value then you can use NSMutablearray and addobject:.
NSArray when you are using the Array then you can use append object like this.
var str1:String = "John"
var str2:String = "Bob"
var myArray = ["Steve", "Bill", "Linus", "Bret"]
myArray.append(str1)
myArray.append(str2)
NSMutableArray when you are using the NSMutableArray then you can use addobject
var myArray1 : NSMutableArray = ["Hello"]
myArray1.addObject(str1)
I am trying to add sections to my table view. I need the first section to be an array of strings and the second section to be an array of NSManagedObjects, I use a fetch request to add the data to the array.
I add the section titles to the sections array.
let sections = ["Upcoming", "Checklist Notebooks"]
Then have a dictionary for the data
var sectionItems = [
"Upcoming" : ["1","2", "3", "4"],
"Objects" : [Object]()
]
However when doing the fetch request I get the following error,
Cannot Assign Through Subscript: Subscript is a get-only
Here's my fetch request,
self.sectionItems["Objects"] = delegate.managedObjectContext.executeFetchRequest(request) as! [Object]
How can I create an array/dictionary of two data types to used for the sections ?
Try to add definition for your compound dictionary. You can try this in the playground.
var sectionItems: [String: [Any]] = [
"Upcoming" : ["1","2", "3", "4"],
"Objects" : [AnyObject]()
]
sectionItems["Objects"] = ["123"]
sectionItems["Objects"]
So I have this NSDictionary itemsDict(in Swift):
var itemsDict : NSDictionary = [:] // Dictionary
var Sections : NSArray = [] // Array
itemsDict = [
["News"]:["a":"www.hello.co.uk","b":"www.hello.com"],
["Sport"]:["c":"www.hello.co.uk","d":"www.hello.com"],
]
print (itemsDict)
This is how the structure of the dictionary looks like:
{
(
News
) = {
a = "www.hello.co.uk";
b = "www.hello.com";
};
(
Sport
) = {
c = "www.hello.co.uk";
d = "www.hello.com";
};
}
From the dictionary above I want to be able to populate an NSArray with only the -
[News,Sports] elements.
I've tried this and a few other methods but they just don't seem to cut it. My Swift skills are not that advanced and I hope this post make sense.
Sections = itemsDict.allKeysForObject(<#anObject: AnyObject#>)
To get an Array of all Strings in your Dictionary's keys, you can use the allKeys property of NSDictionary along with a reduce function, like so:
var itemsDict = [
["News"]:["a":"www.hello.co.uk","b":"www.hello.com"],
["Sport"]:["c":"www.hello.co.uk","d":"www.hello.com"],
]
let keys = (itemsDict.allKeys as [[String]]).reduce([], combine: +)
println(keys)
Outputs:
[News, Sport]
However, I don't see a good reason to use Arrays of Strings as your Dictionary keys. Instead, I'd just use Strings as keys directly, like so:
var itemsDict = [
"News":["a":"www.hello.co.uk","b":"www.hello.com"],
"Sport":["c":"www.hello.co.uk","d":"www.hello.com"],
]
In which case, getting an Array of the Dictionary's keys is as simple as:
let keys = itemsDict.keys.array
Note: I'm using the keys property here and the allKeys property earlier because this is a native Swift Dictionary while the earlier code is an NSDictionary due to its use of NSArrays for keys.
I was referring to Apple's Swift programming guide for understanding creation of Mutable/ immutable objects(Array, Dictionary, Sets, Data) in Swift language. But I could't understand how to create a immutable collections in Swift.
I would like to see the equivalents in Swift for the following in Objective-C
Immutable Array
NSArray *imArray = [[NSArray alloc]initWithObjects:#"First",#"Second",#"Third",nil];
Mutable Array
NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:#"First",#"Second",#"Third",nil];
[mArray addObject:#"Fourth"];
Immutable Dictionary
NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:#"Value1", #"Key1", #"Value2", #"Key2", nil];
Mutable Dictionary
NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:#"Value1", #"Key1", #"Value2", #"Key2", nil];
[mDictionary setObject:#"Value3" forKey:#"Key3"];
Arrays
Create immutable array
First way:
let array = NSArray(array: ["First","Second","Third"])
Second way:
let array = ["First","Second","Third"]
Create mutable array
var array = ["First","Second","Third"]
Append object to array
array.append("Forth")
Dictionaries
Create immutable dictionary
let dictionary = ["Item 1": "description", "Item 2": "description"]
Create mutable dictionary
var dictionary = ["Item 1": "description", "Item 2": "description"]
Append new pair to dictionary
dictionary["Item 3"] = "description"
More information on Apple Developer
Swift does not have any drop in replacement for NSArray or the other collection classes in Objective-C.
There are array and dictionary classes, but it should be noted these are "value" types, compared to NSArray and NSDictionary which are "object" types.
The difference is subtle but can be very important to avoid edge case bugs.
In swift, you create an "immutable" array with:
let hello = ["a", "b", "c"]
And a "mutable" array with:
var hello = ["a", "b", "c"]
Mutable arrays can be modified just like NSMutableArray:
var myArray = ["a", "b", "c"]
myArray.append("d") // ["a", "b", "c", "d"]
However you can't pass a mutable array to a function:
var myArray = ["a", "b", "c"]
func addToArray(myArray: [String]) {
myArray.append("d") // compile error
}
But the above code does work with an NSMutableArray:
var myArray = ["a", "b", "c"] as NSMutableArray
func addToArray(myArray: NSMutableArray) {
myArray.addObject("d")
}
addToArray(myArray)
myArray // ["a", "b", "c", "d"]
You can achieve NSMutableArray's behaviour by using an inout method parameter:
var myArray = ["a", "b", "c"]
func addToArray(inout myArray: [String]) {
myArray.append("d")
}
addToArray(&myArray)
myArray // ["a", "b", "c", "d"]
Re-wrote this answer 2015-08-10 to reflect the current Swift behaviour.
There is only one Array and one Dictionary type in Swift. The mutability depends on how you construct it:
var mutableArray = [1,2,3]
let immutableArray = [1,2,3]
i.e. if you create an assign to a variable it is mutable, whereas if you create an assign to constant it is not.
WARNING: Immutable arrays are not entirely immutable! You can still change their contents, just not their overall length!
Just declare your (any)object or variable with
'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.
and
'var' key word -> for "Mutable" array, dictionary, variable, object..etc.
For more deeply information
“Use let to make a constant and var to make a variable. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once. This means you can use constants to name a value that you determine once but use in many places."
var myVariable = 42
myVariable = 50
let myConstant = 42
Read “The Swift Programming Language.”
If you want to work with Array (Swift) as with NSArray, you can use a simple bridge function. Example:
var arr1 : Array = []
arr1.bridgeToObjectiveC().count
It works the same for let.
From Apple's own docs:
Mutability of Collections
If you create an array, a set, or a dictionary and assign it to a
variable, the collection that is created will be mutable. This means
that you can change (or mutate) the collection after it is created by
adding, removing, or changing items in the collection. Conversely, if
you assign an array, a set, or a dictionary to a constant, that
collection is immutable, and its size and contents cannot be changed.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105
Other uses of immutable/mutable collections depend on why you want them to be mutable/immutable. Collections are value types in Swift, which means their contents is copied when they are assigned to another value, or passed to another function/method. Therefore, you do not need to worry about whether a receiving method function might change the original array. Therefore you don't need to ensure to return an immutable collection if your class is holding a mutable collection, for instance.
Swift Mutable/Immutable collection
[Unmodifiable and Immutable]
Swift's array can be muted
[let vs var, Value vs Reference Type]
Immutable collection[About] - is a collection structure of which can not be changed. It means that you can not add, remove, modify after creation
let + struct(like Array, Set, Dictionary) is more suitable to be immutable
There are some classes(e.g. NSArray) which doesn't provide an interface to change the inner state
but
class A {
var value = "a"
}
func testMutability() {
//given
let a = A()
let immutableArr1 = NSArray(array: [a])
let immutableArr2 = [a]
//when
a.value = "aa"
//then
XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
XCTAssertEqual("aa", immutableArr2[0].value)
}
It would rather is unmodifiable array