Swift Can't append to String array [duplicate] - ios

This question already has answers here:
Simple swift array append not working
(3 answers)
Closed 4 years ago.
I have this array defined inside a class:
var pickOption: [String]?
inside my classes init, I am trying to append to the array:
override init!(reuseIdentifier identifier: String!) {
self.pickOption?.append("aaa")
print(self.pickOption)
}
but self.pickOption is returning nil, why? and how can I fix it?

With first statement var pickOption: [String]? you have just declared the array of type string but never allocate the memory. As this is optional type, it will be nil at the time of declaration.
You need to allocate memory for array before using it. You can declare array as this var pickOption = [String]() and rest of code will do the work!!

You have to init it declare it like this
var pickOption = [String]()
as this line
self.pickOption?
with the optional won't run as in it's moment pickOption is nil

Related

Ambiguous use of 'mutableCopy()' Swift3

I tried to update Swift 3 and I got the following error :
Ambiguous use of 'mutableCopy()'
Before update to swift 3. It runs well.
Swift 2.3
NSUserDefaults.standardUserDefaults().objectForKey("listsavednews")?.mutableCopy() as! NSMutableArray
Swift 3.0
(UserDefaults.standard.object(forKey: "listsavednews")? as AnyObject).mutableCopy() as! NSMutableArray
I found that mutableCopy in Swift3 return Any that doesnt have method mutableCopy() so that it needs to cast to AnyObject.
Any helps thanks.
I dont know why I can't comment.
Thanks all, I'll be using :
UserDefaults.standard.mutableArrayValue(forKey: "listsavednews")
mutableCopy is an Objective-C method from NSObject. There's little reason to use it in Swift 3.
Since you are dealing with UserDefaults and mutableCopy, you must be dealing with either an array or dictionary. Or it could be a string.
The proper way to do this in Swift 3 is to use the proper UserDefaults method to get an array or dictionary. And assign the result to a var. That combination will give you a mutable array or mutable dictionary.
var someArray = UserDefaults.standard.array(forKey: "somekey")
or:
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey")
In the two above cases, you end up with an optional since there might not be any data for the given key. And you also get a non-specific array or dictionary which isn't ideal. It would be better to cast the result to the appropriate type.
Let's say you have an array of strings and you want an empty array if there is nothing currently in user defaults. You can then do:
var someArray = UserDefaults.standard.array(forKey: "somekey" as? [String]) ?? []
Adjust as necessary if the array contains something other than String.
If you actually have a dictionary, the code would be similar.
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey") as? [String:String] ?? [:]
If your original object is just a string, then you could do:
var someString = UserDefaults.standard.string(forKey: "somekey") ?? ""

ios - filter two arrays with objects Swift [duplicate]

This question already has answers here:
How to remove common items from two struct arrays in Swift
(3 answers)
Closed 6 years ago.
I have got two arrays with objects.
var filteredData:[MainData] = [MainData]()
var removeData:[MainData] = [MainData]()
struct MainData {
var open:NSTimeInterval
var works = [Visit]()
}
I want remove data from filteredData using function filter with parameter filteredData.open == removeData.open
I can't filter two arrays with objects.
You can try like this, first get an Array of open from removeData array and check that it is contains object from the filteredData Array opens.
let opens = removeData.map { $0.open }
filteredData = filteredData.filter { !opens.contains($0.open) }

Extending Array to append SKTextures [duplicate]

This question already has answers here:
Is it possible to make an Array extension in Swift that is restricted to one class?
(4 answers)
Closed 7 years ago.
Being fairly new to Swift I decided I would look at extending Array (or more specifically [SKTexture] Arrays of SKTexture) with a function to add a specified number of frames from the application bundle.
// FRAMES
FuzzyRabbit_0001#2x.png
FuzzyRabbit_0002#2x.png
FuzzyRabbit_0003#2x.png
FuzzyRabbit_0004#2x.png
// CALL
var rabbitTextures = [SKTexture]()
self.rabbitTextures.textureFromFrames("FuzzyRabbit", count: 4)
My first attempt is listed below, I am getting the error Cannot invoke 'append' with an argument list of type '(SKTexture!)' which from looking at the function fuzzyPush is because I am trying to append an SKTexture rather than the generic T.
Is this possible, or am I limited by the fact that I don't want the function to be generic but rather specific to Arrays of SKTexture.
extension Array {
// ONLY SKTexture
mutating func textureFromFrames(imageName: String, count: Int) {
if !(self[0] is SKTexture) { return }
for index in 1...count {
let image = String(format: "\(imageName)_%04d", index)
let texture = SKTexture(imageNamed: image)
self.append(texture) // ERROR: Cannot invoke append with an argument list of type SKTexture!
}
}
// WORKS FINE
mutating func fuzzyPush(newItem: T) {
self.append(newItem)
}
}
I was just curious if this is something I could do with an extension, its not a problem as I have this as a function that takes 3 parameters (imageName, count, arrayToAppend) so I can quite easily use that.
This extension is not possible to write today. You cannot apply an extension method to only certain types of arrays.
There are two good solutions. You can use a HAS-A pattern by creating a struct (TextureList) that contains a [SKTexture], or you can use a function.
You can replace :
self.append(texture)
with
self.append(texture as T)
I checked this on an array of strings though and it worked.
About the first check add another check to see if the array is empty otherwise the self[0] is SKTexture will fail.
This is the code I tested on an online swift compiler (SKTexture was not available obviously) :
extension Array {
mutating func textureFromFrames(imageName: String, count: Int) {
for index in 1...count {
let image = String(format: "\(imageName)_%04d", index)
self.append(image as T)
}
}
}
var arr = Array<String>()
arr.textureFromFrames("testing", count:4)
for tmp in arr {
println("\(tmp)")
}

EXC_BAD_INSTRUCTION object array assign Swift

I have an array of Printable objects, but I need them Equatable and AnyObject compliant.
private(set) var items: [Printable] = []
class func withItems<T: AnyObject where T: Equatable, T: Printable>(items: [T], selectedItem: T? = nil) {
... instance init ...
instance.items = items
}
And it result on EXC_BAD_INSTRUCTION:
fatal error: array cannot be bridged from Objective-C
This is one try to this problems:
Generic function and attribute with Equatable and Printable as parameters in Swift
why?
A Swift Array must contain all one kind of object (e.g. all String or all Int). An Objective-C NSArray can contain many different kinds of objects (e.g. some NSStrings and some NSNumbers). Hence if you get that kind of array from Objective-C you can't magically assign it into a Swift array reference.
What I do in that situation is munge the array to make it acceptable to Swift. I don't know what the details are of what you're getting back from Objective-C; your actual strategy will depend on those details and what you want to do with the array. One approach is to assign / cast into a Swift array of AnyObject. Or you might decide to leave it as an NSArray and work with it entirely through NSArray methods.
Here's an example from my own code. arr is an NSArray that's a mixed bag of NSString and NSNull objects. I know none of the NSString objects are the empty string, so I substitute the empty string for all the NSNull objects, thus giving me an array of just strings, which Swift can deal with:
let arr2 = (arr as Array).map { $0 as? String ?? "" }
Now arr2 is a pure Swift [String] array.

Set objects to empty NSDictionary in Swift [duplicate]

This question already has answers here:
Swift dictionary bug?
(6 answers)
Closed 8 years ago.
I can create an NSDictionary
var namesDictionary=Dictionary<String,String>()
namesDictionary["Jacob"] = "Marry"
But, when I create a empty dictionary like coded below, line 1 i okie, but line 2 (adding values) throws an error.
var namesDictionary =[:]
namesDictionary["Jacob"] = "Marry"
Error is "Cannot assign to the result of this expression". Is there any other way to assign the values.
It looks like it's an issue with swift interpreting the type of your dictionary. Try explicitly typing your empty dictionary.
var namesDictionary: Dictionary<String, String> = [:]
namesDictionary["Jacob"] = "Marry"
I think a better use for [:] is for emptying an already defined dictionary. If you add a third line namesDictionary = [:], you will be able to call namesDictionary["Jacob"] = "Marry" again since the compiler knows what type of dictionary it is from the inital declaration.

Resources