Is boolean or nil comparison faster? - ios

I am writing a code in Swift where I have a class as follows:
class Note
{
var isDeleted:Bool = false
var deletedDateTime:Date!
}
Suppose there is a data source that is filled with Notes and I want to make a filter based on comparison, then I can either compare by isDeleted or I can compare by deletedDateTime. Which one would be faster from the following two statements:
var dataSource:[Note] = [Note]()
// fill the datasource with objects
dataSource.filter({$0.isDeleted == false}) // 1
dataSource.filter({$0.deletedDateTime == nil}) //2
Can anyone please guide me?

There won't be much of a time difference, if you are talking about the execution time. But your class seem to be a bit obvious since you could remove the unnecessary boolean variable because as you have asked the both mean the same.

Related

Method to update properties in ios swift code while keeping the fuction pure as possible and testable?

Long time IOS developer/tinkerer here. I mostly taught myself programming, OBJ-C back in the day and now Swift. So apologies in advance if things I ask are too basic, its partly because I may not be well versed on some fundamentals.
I am currently working on an app. Alongside it I have been reading a fair bit on writing testable code and testing in general. I am not talking about purely TDD but I would like the libraries that I am creating for the app to have a good testset available. Partly because its good practice and partly because its soemthing I want to learn to do better.
So here goes, in my app class(es) I have a number of functions that take in parameters and give an output (as you do!). However, a number of these functions also make changes to class properties as data in these properties will be used in other class functions. For example:
class SomeClass() {
var someArrayProperty: [String] = []
var someInputParameter: String
init(input: String) {
//some initialisation code
self.someInputParameter = input
//Call function to build object
let object = self.buildObject(inputParameter: self.someInputParameter)
}
func buildObject(inputParameter: String) -> SomeObject {
let objectToReturn = SomeObject(withInputParameter: inputParameter)
let stringToAddToArray = "Object 1 created"
self.someArrayProperty.append(stringToAddToArray)
return objectToReturn
}
}
From what I have read about the testing, the code should ideally be such that it should do one job and not change something outside of the code as it becomes untestable for complex code. Here, the issue I have is that I am directly changing the someArrayProperty from within the method, i.e. changing something outside of the method.
Although its not an issue for the code and everything works fine, I would like to understand what do you guys feel about things like this from a testing point of view in your own code? And what pattern/changes you generally follow in your own code to avoid it?
Again, apologies if its too basic a question but I think it will help me fill in gaps in my knowledge to be able to write more beautiful code rather than something that just works and breaks next time a minor update is done somwhere. :)
Thanks
So if your function is called buildObject, it should do job inside it and have no return value. But if you call it buildedObject, it should return constructed object. You can read more about in Apple Naming Methods documentation.
And so your code should look like this:
class SomeClass() {
var someArrayProperty: [String] = []
var someInputParameter: String
init(input: String) {
//some initialisation code
self.someInputParameter = input
//Call function to build object
let object = self.buildedObject(inputParameter: self.someInputParameter)
// Other code which modifies data
let stringToAddToArray = "Object 1 created"
self.someArrayProperty.append(stringToAddToArray)
}
func buildedObject(inputParameter: String) -> SomeObject {
let objectToReturn = SomeObject(withInputParameter: inputParameter)
return objectToReturn
}
}

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

How NSMapTable works

I'm trying to figure out how NSMapTable works
So I'm trying in playground the following code:
class Person {
var name: String
init(name: String ) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
var hobyePerson : NSMapTable? = NSMapTable<Person, NSMutableString>
(keyOptions: .weakMemory, valueOptions: .weakMemory)
var rob : Person? = Person(name: "Rob Appleseed") // print : Rob Appleseed is being initialized
hobyePerson?.setObject("golf", forKey: rob)
hobyePerson?.count // return : 1
rob = nil // print : Rob Appleseed is being deinitialized
hobyePerson?.count // return : 1 (WHY ???!!!!)
as written in the documentation: "Keys and/or values are optionally held “weakly” such that entries are removed when one of the objects is reclaimed."
why even though I initialized the object so that it has a weak reference to the key-value pair when rob is deallocated, I still have an element in hobyePerson?
NSMapTable's weak behavior options work best when you don't care when keys/values are released, but rather, you do care that the keys/values aren't strongly retained and will be released at some point after the object of interest becomes nil.
Why so?
As a Foundation class, the authors of NSMapTable had to balance both features and performance.
Consequently, as an "optimization" for performance, they chose that weakly referenced objects that become nil are NOT immediately removed from the map table...! Rather, this happens "later" when it can be efficiently done -- such as when the map table internally gets resized, etc.
As #Luke also mentions in his answer, see this excellent writeup about an experiment done on NSMapTable's behavior for more details:
http://cocoamine.net/blog/2013/12/13/nsmaptable-and-zeroing-weak-references/
Yes, this is a strange and unfortunate behavior. This article goes into it in some depth. Although it doesn't explore weak-to-weak specifically, the behavior described is the same. As that author notes, hobyePerson.keyEnumerator().allObjects.count and hobyePerson.objectEnumerator().allObjects.count will contain 0 as expected at the end of all this. He also points out that Apple has sort of documented this behavior in the Mountain Lion release notes.
However, weak-to-strong NSMapTables are not currently recommended, as
the strong values for weak keys which get zero’d out do not get
cleared away (and released) until/unless the map table resizes itself.
Sorry I don't have a better explanation for you.
It didn't work for me so I implemented simple weak map like this.. Will improve it overtime but for now works:
import Foundation
private struct WeakValue<Value:AnyObject> {
weak var value: Value?
}
public class CSWeakValueDictionary<Key:AnyObject, Value:AnyObject> {
private let dictionary = NSMutableDictionary()
public subscript(source: Key) -> Value? {
get {
let value = (dictionary["\(source)"] as? WeakValue<Value>)?.value
if value == nil { dictionary.removeObject(forKey: "\(source)") }
return value
}
set { dictionary["\(source)"] = WeakValue(value: newValue) }
}
}

Equatable Testing in Swift

I'm looking for suggestions on good practices to test the equality of swift objects
If I have a complex object with many properties it's easy to miss the equality implementation.
What are the good practices to enforce the equality implementation?
More details:
Of course, you can write tests to check that two value are equal when they should, but the problem here is that this can break easily.
You have a struct in your project, after six months another developer adds a property to that struct.
Assume that he forgets to add the property to the equality. The equality still works, the tests pass but your app will break when only that property changes. My question is, there is a way to avoid this problem?
In a non trivial app is really easy to end up having model objects with 10 values, and use nested model objects. So how can I keep under control the equality of my model objects? How can I reduce the human error risk in the equality implementation?
Possible solution:
One solution I have in mind is to write a script that looks at compile time for classes and struct that conform to a certain protocol
Diffable : Equatable {}
For all the classes/structs that adopt Diffable I'll check for the existance of a test file, i.e.:
For the class Foo I'll look for a test class Foo_Tests_Diffable
than for all the properties inside Foo I'll check for the existance of a test function that conform to the following name pattern
test<property name>Diffable
i.e.:
class Foo : Diffable {
var title: String
var color: UIColor
var tag: Tag
}
I'll check for the following tests inside Foo_Tests_Diffable
func testTitleDiffable {
// Test
}
func testColorDiffable {
// Test
}
func testTagDiffable {
// Test
}
If all the script finds all the expected tests than the compile step pass, otherwise it fails
But this solution it's time consuming and I don't know if I'll be able to implement it, so any suggestion is welcome
I would create unit tests specifically for this purpose.
class YourObjectEquatableTests: XCTestCase
{
func testPropertyOne()
{
var object1 = /* ... */
var object2 = /* ... */
object1.propertyOne = nil
object2.propertyOne = nil
XCTAssertEqual(object1, object2)
object1.propertyOne = "different value"
XCTAssertNotEqual(object1, object2)
/* etcetera */
}
func testPropertyTwo()
{
/* ... */
}
}
Note: if you write your test cases before implementing the Equatable details, you're actually doing TDD which is very cool!
I didn't try it a lot but Swift has Reflection capabilities.
https://appventure.me/2015/10/24/swift-reflection-api-what-you-can-do/
So in your case, you can mirror a class and then put some conditions in your test.
for example, you can set a fix number or attribute or methods for a class in your test.
let nbAttributes = 6
and then check it:
aMirror.children.count
I wrote a simple example in the playground and if I add a method variable, the children count increases. I don't know if it's possible to check the methods though.
class toto{
var io = 9
var tutu = "yo"
func test(){
}
}
let toto1 = toto()
let aMirror = Mirror(reflecting: toto1)
aMirror.children.count
another link:
Reflection in swift 2
Hope that helps :)
Yes, expanding on #Mikael's answer, you should probably use Reflection.
An example would be:
String(reflecting: obj1) == String(reflecting: obj2)

Swift: Random number arrays inside images and variables with a for loop

I am creating a game in which, depending on the number of 'swipes' chosen to do, (let's say 3), 3 different patterns show on the screen, one by one. I am working on developing the first pattern.
So I have this:
if (swipes.no_of_swipes) == 3 {
swipeArray = Array<UInt32>(count: 3, repeatedValue: 0)
for i in 0 ..< 3 {
swipeArray[i] = arc4random_uniform(84)}
}
As far as I am aware, this code creates an array with three UInts which can be accessed by doing swipeArray[0], swipeArray[1], and swipeArray[2]. My first question is how long will this swipeArray stay the same? Until the close the view? Should I have a 'refresh button' when the user loses - and if so, how would I make one?
Then I have a property observer. You will notice the for loop, which I am using to keep code concise. I understand that I could do something like x++ somewhere in here so that it will go through each one.
var playBegin: Bool = false{
didSet {
if playBegin == true {
println("\(playBegin)")
var swipes = Menu()
if (swipes.no_of_swipes) == 3 {
for i in 0 ..< 3 {
patternRoom.image = UIImage(named: "pattern\(swipeArray[x])")
//rest of code
}
}
}
The pattern image comes from a set of 84 images named like pattern7 and pattern56. My second question is, how could I code the for loop to go through each swipeArray[x].
Thank you in advance,
Will
how long will this swipeArray stay the same?
This is a bit too open ended. It’ll stay the same until you assign a new value to it, either from this same bit of code or a different part. Only you can know when that will be, by looking at your code.
Since you express an interest in keeping the code concise, here’s a couple of code tips.
You might think about writing your first snippet’s loop like this:
swipeArray = (0..<swipes.no_of_swipes).map { _ in
arc4random_uniform(84)
}
This combines creating a new array and populating the values. By the way, just in case you don’t realize, there’s no guarantee this array won’t contain the same value twice.
It’s also probably better to make swipeArray of type [Int] rather than [UInt32], and to convert the result of arc4random to an Int straight away:
Int(arc4random_uniform(84))
Otherwise the UInt32s will probably be a pain to work with.
For your second for loop, you can do this:
for i in swipeArray {
patternRoom.image = UIImage(named: "pattern\(i)")
// rest of code
}
When writing Swift, usually (but not always), when you find yourself using array[x] there’s a better more expressive way of doing it.

Resources