Index Of in Cocoa - ios

I'm used to making iPhone apps but now I need to make a Mac app.
I thus have to switch to the Cocoa framework.
Is there anything similar to the array.index(of: ) in Cocoa?
iOS example:
let string = "Hello.World"
let needle: Character = "."
if let idx = string.characters.index(of: needle) {
let pos = string.characters.distance(from: string.startIndex, to: idx)
print("Found \(needle) at position \(pos)")
}
else {
print("Not found")
}
The actual code I'm having problems with is here:
func checkBoxTapped(_ sender: NSButton) {
if (sender.state == 1) {
self.selectedReferrals.append(self.referralApplicationList[sender.tag])
}
if (sender.state == 0) {
// Remove
// self.referralApplicationList[sender.tag]
// let foofoo = self.referralApplicationList.indexOf(self.referralApplicationList[sender.tag])
}
}

Your question has nothing to do with Cocoa or macOS versus iOS at all. Really what you are asking is how to get an index(of:) function on a Swift array, and the answer to that is the elements in the array need to be Equatable.
In your iOS example, characters is an instance of String.CharacterView which explicitly has an index(of:) function.
In your Mac example, in which you don't provide enough info, the selectedReferrals variable is presumably an Array of some Referral type; eg a [Referral]. For there to be a similar index(of:) your Referral type needs to implement the Equatable protocol. Otherwise you'd need to use something like index(where:) to find the one you want.

Related

Checking if array is nil or not [duplicate]

This question already has answers here:
Check if optional array is empty
(8 answers)
Closed 4 years ago.
I have a array of my custom model, and I want to check if it is not nil and its size is greater then 0.
Following is my array with custom object
var listCountries : [Countries]? = nil
now In viewDIdLoad I want to make a check on it. I am new to Swift. I have good experience in working in Java.
I have read out Optional values concept and guard, if let statements. But I am unable to understand how efficiently they may be used. I have read too much SO questions but failed to figure out.
for example , if I want to check the upper given array in java I have only to do
if(listCountries != null && listCountries.size()>0){
//DO something
}
So to summarize my question:
How to make the upper given(Java code) check in to swift 4.? What is more smooth and reliable way.
What is a use of if let , guard, guard let statements. if I declare a variable (array, string) as optional I have to bear optional check like force wrapping each and every place. This is for me so making too much confusion.
Please help. I know this question has been asked in different ways. But this has some different context.
Just use ??.
if !(listCountries ?? []).isEmpty {
However, since you want to probably use listCountries in the if block, you should unwrap
if let listCountries = self.listCountries, !listCountries.isEmpty {
Ideally, if nil and empty means the same to you, don't even use an optional:
var listCountries: [Countries] = []
I would do it something like...
if let list = listCountries, !list.isEmpty { // Can also use list.count > 0
// do something
}
Even though you are not using the list inside the braces you are still using the list in the condition.
Or, like Sulthan said... make it non-optional to begin with if it makes no difference.
Obviously, I would assume that you are able to recognize the difference between nil array and empty array.
So, if we tried to implement a literal translation to your question:
I want to check if it is not nil and its size is greater then 0
For the first condition:
// "I want to check if it is not nil":
if let unwrappedList = listCountries {
// ...
}
and for the second condition:
// "I want to check if it is not nil":
if let unwrappedList = listCountries {
// "and its size is greater then 0":
if !unwrappedList.isEmpty {
// ...
}
}
However, you could combine both of the conditions by using the comma to achieve the multi-clause condition:
// I want to check if it is not nil and its size is greater then 0
if let unwrappedList = listCountries, !unwrappedList.isEmpty {
// ...
}
Or by using guard statement:
// I want to check if it is not nil and its size is greater then 0
guard let unwrappedList = listCountries, !unwrappedList.isEmpty else {
return
}
if let list = listCountries {
if(!list.isEmpty && list.count > 0) {
//value
}
}

CoreData with Swift and iOS 8+ still needs willAccessValueForKey()?

I'm writing a function in my NSManagedObject subclass called Friend.
I wonder if I should write this (user is another NSManagedObject User):
func firstCharacterOfComputerDisplayName() -> String
{
guard let user = self.friend else {
return ""
}
return user.firstCharacterOfComputerDisplayName()
}
or that:
func firstCharacterOfComputerDisplayName() -> String
{
self.willAccessValue(forKey: "friend")
guard let user = self.primitiveValueForKey("friend") as? User else {
self.didAccessValue(forKey: "friend")
return ""
}
let dispName = user.firstCharacterOfComputerDisplayName()
self.didAccessValue(forKey: "friend")
return dispName
}
Whether to use willAccessValue(forKey:), primitiveValueForKey(_:) and didAccessValue(forKey:) isn't related to whether you use Swift or iOS 8. It's strictly a Core Data thing. Core Data uses KVO to maintain data graph integrity and so on, so it has certain expectations about when it will observe changes and access.
Mostly you don't need to care about those methods unless you are overriding an accessor method. If you want the value of self.friend, just ask for it as self.friend. Unless you're overriding the accessors for friend, except you're not doing that here.

Remove a specific list of SKAction from a SKNode

During the development of some interactions between different nodes, I realized I need to remove a specific list of actions from a node.
The current version of Sprite-Kit framework provides some instance methods as:
removeAllActions()
action(forKey key: String)
hasActions()
Obviously every action that running in my node has a String key for its identifications.
So I thought of something that was very similar to removeAllAction, then I made an SKNode extension:
public extension SKNode {
func removeAllAction(in list:[String]) {
list.forEach { if self.action(forKey: $0) != nil { self.action(forKey: $0)?.speed = 0.0; self.removeAction(forKey: $0)}}
}
}
And in my project I can use it as:
let actionList = ["idle_walk_sx","idle_walk_dx","walk_dx","walk_sx","walk_idle_sx","walk_idle_dx","rotate_sx_dx","rotate_dx_sx"]
self.removeAllAction(in: actionList)
The code works well.
But I'm not really sure about two factors:
the effectiveness of the speed corrections (to zero), I thought it
appropriate to introduce it in the face of repeated actions. Should I remove it due to avoid strangness or leave it ?
How is it possible to extend this extension (expanding it) to any
childrens that have the same list to remove?
I agree with the comments. Probably speed is not necessary so the code + the scanning to the children nodes could be something like:
public extension SKNode {
func removeAllAction(in list:[String]) {
list.forEach { if self.action(forKey: $0) != nil { self.removeAction(forKey: $0)}}
self.children
.filter { $0.hasActions() }
.forEach { $0.removeAllAction(in: list) }
}
}

How to remove an element of a given custom type value from an array in Swift

I want to remove element of custom type value from an array.
I want to pass a variant instance to function to remove it from array, I don't want to use removeAtIndex().
var favoriteVariants: [Variant]
func removeVariant(variant: Variant)
{
}
If Variant is Equatable and you only want to remove the first one that matches:
if let idx = favoriteVariants.indexOf(variant) {
favoriteVariants.removeAtIndex(idx)
}
If it isn’t Equatable and you have some other matching criteria to find just one to remove:
let idx = favoriteVariants.indexOf {
// match $0 to variant
}
if let idx = idx {
favoriteVariants.removeAtIndex(idx)
}
(these are assuming Swift 2.0 – if 1.2, it’s find(favoriteVariants, variant) instead of indexOf, and there isn’t a version that takes a closure, though it’s not too hard to write one)
If there are multiple ones you want to remove in one go:
favoriteVariants = favoriteVariants.filter {
// criteria to _keep_ any given favorite
}
All of these could be wrapped in extensions if what you want to do is general enough to justify it.

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)")
}

Resources