Unable to compare array value in swift ios - ios

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"]

Related

Casting Syntax to Loop Through Array of Arrays in Swift

I have an NSArray consisting of NSArrays of strings created in Objective-C.
I now want to loop through the items in the array in a swift class and am having trouble with the syntax.
The original Objective-C Array of arrays looks like the following:
NSArray* shapes =#[#[#"square",#"square.png"],#[#"circle",#"circle.png"],#[#"square",#"square.png"]];
I am able to get and print the Array from the Objective-C class using:
let shapes:Array = Utilities.sharedInstance().getShapes
The following to loop through the array, however, is not compiling:
var term : String = ""
var pic : String = ""
for shape in shapes {
term = shape[1] //ERROR HERE
pic = shape[2] //SAME ERROR HERE
}
It gives the error: Type 'Any' has no subscript members
What is the proper syntax to loop through the elements?
You can try
let shapes = Utilities.sharedInstance().getShapes as! [[String]]
Your Array elements are of type Any so you can't use [] with them until you cast , it's always the case when you use bridged code from objective-c , so you have to be specific about the actual type you use , also i encourage
struct Item {
let term,pic:String
}
Then
let res:[Item] = shapes.map { Item(term:$0[0],pic:$0[1]) }
an irrelevant note but important you can do
NSArray* shapes = #[#"square",#"circle",#"square"];
then the matter of appending .png is simple instead of having an [[String]] directly it's [String]

Swift 3 - No 'sort' candidates produce the expected contextual result type 'NSMutableArray'

I am attempting to sort a mutable array in Swift 3.1.1, but get the same error every time:
No 'sort' candidates produce the expected contextual result type 'NSMutableArray'.
Is there a way to sort a mutable array (Ints only) in ascending order?
In my code, elements from options are being removed. Removed (the array) is adding the removed elements. At the end of the code I am attempting to add the elements from the removed array back to options and sort it.
// set up tiles
var options = NSMutableArray()
var removed = NSMutableArray()
for i in 1...49 {
options.add(i as Int)
print("options\(options.count)")
}
for i in 1...49 {
print("i = \(i)")
options.remove(i)
let tilea: Int = options[Int(arc4random_uniform(UInt32(options.count)))] as! Int
options.remove(tilea)
let tileb: Int = options[Int(arc4random_uniform(UInt32(options.count)))] as! Int
options.remove(tileb)
removed.add([i, tilea, tileb])
print(options.count)
if options.count < 20 {
options.add(removed)
options = options.sort {
$0 < $1
}
}
}
As already mentioned, in Swift you should really be using the Array<T> for this (aka, [T]) instead of NSMutableArray. For instance:
var options = [Int]()
when adding elements to it, use append (and, by the way, you can drop the type cast as well):
options.append(i)
options.append(contentsOf: [i, j, k])
finally, when sorting the array, use the sort function (it doesn't return a value; the array is sorted in-place):
options.sort()
and you don't need even to provide a comparation function since integers conform to the Comparable protocol.
NSMutableArray, among other Objective C types, was implicitly bridged to/from its Swift counterparts. In a move to lessen peoples (usually unnecessary) reliance on these Objective C types, this implicit bridging has been changed in Swift 3, and now needs an explicit type coercion (e.g nsArray as [Int])

"Not a 'subtype' error" when calling function

I am attempting to load a plist that contains a rather large dictionary, shuffle it, and then save the shuffled version for use in the app. I think I'm close but I'm getting a type casting error, 'NSArray is not a subtype of NSMutableArray', when trying to set experiments = shuffleArray(experiments).
Here is the relevant code:
var experiments = NSMutableArray()
var menuIndex = 0
override init() {
super.init()
// Create the data model.
func shuffleArray<T>(var array: Array<T>) -> Array<T>
{
for var index = array.count - 1; index > 0; index--
{
// Random int from 0 to index-1
var j = Int(arc4random_uniform(UInt32(index-1)))
// Swap two array elements
// Notice '&' required as swap uses 'inout' parameters
swap(&array[index], &array[j])
}
return array
}
if let path = NSBundle.mainBundle().pathForResource("experiments", ofType: "plist") {
if let dict = NSDictionary(contentsOfFile: path) {
experiments.addObjectsFromArray(dict.objectForKey("experiments") as NSArray)
experiments = shuffleArray(experiments)
}
}
Any ideas?
You return Array<T> from shuffleArray, but Array<T> is not a subtype of NSMutableArray, so you can't assign it to the experiments variable.
If you really need generics, you should use Array<T> for both of them (unless you have a heterogenic array with different types of objects, but this is very rare and you should think carefully if it is what you want).
Assuming you know that all types are e.g. Int, String or some custom type (say class Experiment), you should use typed array, i.e. Array<Int> or Array<String> or Array<Experiment> for experiments and only use generic form Array<T> for shuffleArray.

Syntax explanation: square brackets in Swift

I'm studying Swift and got confusing with following syntax:
var treasures: [Treasure] = []
Treasure is custom class, declared as follow:
class Treasure: NSObject { }
In Objective-C square brackets mean method, but what do they mean in Swift?
Ok, this is the meaning of
var treasures: [Treasure] = []
var: you are declaring a variable
treasures: the name of your variable
[Treasure]: the type of your variable, in this case the type is Array of Treasure, the compiler will allow you to insert only object of type Treasure in your Array
[]: the actual object (Array) referenced by your variable, in this case an empty Array.
E.g. if you want the Array to hold 2 elements you can write
var treasures: [Treasure] = [Treasure(), Treasure()]
Hope this helps.
Update:
My example can also be written this way
var treasures = [Treasure(), Treasure()]
Infact thanks to the Type Inference the compiler can deduce the type of the variable treasures looking at the type of the assigned value.
[Treasure] is just a syntax sugar for Array<Treasure>.
The same way [String:Treasure] is just a syntax sugar for Dictionary<String,Treasure>.
[] is just an empty array of the type you defined. The same way [:] is an empty dictionary.
When it comes to Swift and square brackets, the rules are simple. They are used only in two situations:
1) working with Array and Dictionary types:
let vectors : [[Int]] = [[1,2,3],[4,5,6]]
let birthBook : [Int:[String]] = [1987:["John","William"], 1990: ["Mary"]]
2) for subscripting objects that support subscripting:
class RouteMapper {
private var routeMap : [String:String] = [:]
subscript(endpoint: String) -> String {
get {
if let route = routeMap[endpoint] {
return route
}
return "/"
}
set(newValue) {
routeMap[endpoint] = newValue
}
}
}
let routeMapper = RouteMapper()
routeMapper["users"] = "/v1/confirmed/users"
let url = routeMapper["admins"]
Since [ and ] are not allowed in custom operators, these are the only usages for now.

Swift: different objects in one array?

Is there a possibility to have two different custom objects in one array?
I want to show two different objects in a UITableView and I think the easiest way of doing this is to have all objects in one array.
Depending on how much control you want over the array, you can create a protocol that both object types implement. The protocol doesn't need to have anything in it (would be a marker interface in Java, not sure if there is a specific name in Swift). This would allow you to limit the array to only the object types you desire. See the sample code below.
protocol MyType {
}
class A: MyType {
}
class B: MyType {
}
var array = [MyType]()
let a = A()
let b = B()
array.append(a)
array.append(b)
If you know the types of what you will store beforehand, you could wrap them in an enumeration. This gives you more control over the types than using [Any/AnyObject]:
enum Container {
case IntegerValue(Int)
case StringValue(String)
}
var arr: [Container] = [
.IntegerValue(10),
.StringValue("Hello"),
.IntegerValue(42)
]
for item in arr {
switch item {
case .IntegerValue(let val):
println("Integer: \(val)")
case .StringValue(let val):
println("String: \(val)")
}
}
Prints:
Integer: 10
String: Hello
Integer: 42
You can use AnyObject array to hold any kind of objects in the same array:
var objectsArray = [AnyObject]()
objectsArray.append("Foo")
objectsArray.append(2)
// And also the inmutable version
let objectsArray: [AnyObject] = ["Foo", 2]
// This way you can let the compiler infer the type
let objectsArray = ["Foo", 2]
You can use the "type" AnyObject which allows you to store objects of different type in an array. If you also want to use structs, use Any:
let array: [Any] = [1, "Hi"]

Resources