Check If Any Property in an Object Is Nil - Swift 3

check if any property in an object is nil - Swift 3

I would strongly recommend against this. State validation is something which should happen from inside a class. From inside the class, you should know better how to check validity.

class Vehicle {
var name: String?
var model: String?
var VIN: String?

func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}

let objCar = Vehicle()
objCar.name = "Volvo"

if objCar.isReadyToAdvance() {
// Go to other screen
}

If there are subclasses with different rules for isReadyToAdvance() they can override that method.


If isReadyToAdvance() doesn't make sense for the base class, then add it as an extension.

extension Vehicle {
func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}

@iPeter asked for something a bit more compact when there are lots of properties.

extension Vehicle {
func isReadyToAdvance() -> Bool {
// Add all the optional properties to optionals
let optionals: [Any?] = [name, model, VIN]
if (optionals.contains{ $0 == nil }) { return false }

// Any other checks

return true
}
}

How to check object is nil or not in swift?

If abc is an optional, then the usual way to do this would be to attempt to unwrap it in an if statement:

if let variableName = abc { // If casting, use, eg, if let var = abc as? NSString
// variableName will be abc, unwrapped
} else {
// abc is nil
}

However, to answer your actual question, your problem is that you're typing the variable such that it can never be optional.

Remember that in Swift, nil is a value which can only apply to optionals.

Since you've declared your variable as:

var abc: NSString ...

it is not optional, and cannot be nil.

Try declaring it as:

var abc: NSString? ...

or alternatively letting the compiler infer the type.

How to test if a @property from ObjC object is nil in Swift?

The error message tells us the problem:

-[NSNull countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance

Your attribute.values isn't nil or an NSMutableArray. It's [NSNull null].

NSNull is a real object that's used instead of nil in collections, because the common Foundation collections (NSArray and NSDictionary) cannot store nil as a value.

We most often come across NSNull when decoding a data structure from JSON. When the JSON decoder finds null (a JSON literal) in an array or object, it stores [NSNull null] in the corresponding NSArray or NSDictionary.

Something like this should work:

if let values = attribute.values where values != NSNull() {
for val in values {
print(val);
}
return true;
}

How can I check if a property has been set using Swift reflection?

I used @ebluehands technique of reflecting the Any value to modify the original function. It cycles through the properties with an initial mirror, then reflects each one individually using displayStyle to determine if the property is optional.

func allPropertiesHaveValues(obj: AnyObject) -> Bool {
let mirror = Mirror(reflecting: obj)
for child in mirror.children {
let value: Any = child.value
let subMirror = Mirror(reflecting: value)
if subMirror.displayStyle == .Optional {
if subMirror.children.count == 0 {
return false
}
}
}
return true
}

Objective-c Property returns 'nil' in Swift 3

Don't post answers in comments.

Here is a complete answer:

The problem is that you never create an audio object, so your audioSwift variable is indeed nil.

Change your Swift code like this:

var audioSwift = audio()  //Create a new audio object. 
print(audioSwift.count)

Since the code above creates an audio object right away, it doesn't need to be an Optional any more.

Note that in both Swift and Objective-C class names should start with an upper-case letter, so your audio class should be named Audio instead.

Properties in Realm results are nil

You've made a tiny error in the declaration of the Product class there, and it's just a common gotcha with using Realm.

If you look back over all the Realm examples in their documentation, you'll see that each member field should be declared such as this corrected one:

@objc dynamic var itemImage = Data()

Yep, you've missed out the dynamic modifier on each of your properties. Go back and add that to each property and it should just start working. For completeness, this should be the properties declaration:_

// MARK: Properties
@objc dynamic var itemImage = Data()
@objc dynamic var itemName: String = ""
@objc dynamic var price: Float = 0.0
@objc dynamic var unit: String = ""
@objc dynamic var quantity: Int = 0
@objc dynamic var isInCart: Bool = false

You can google the dynamic keyword for an explanation. It's based on the fact that the object you have is just a proxy to a database object, and Realm needs to intercept the property access to actually interrogate the database and retrieve the value of the property. You can see the same effect as your problem if you ever try to look at an object in the debugger - it's just full of the default values.

Swift how to create and test an object with nil properties?

You can make the init parameter an optional String?, with a default
value
nil:

class Contact {
var displayName: String?

init(displayName: String? = nil) {
self.displayName = displayName
}
}

let contact1 = Contact()
let contact2 = Contact(displayName: "John")

The same works for the Contacts class:

class Contacts {
func create(displayName: String? = nil) -> Contact {
return Contact(displayName: displayName)
}
}

let contacts = Contacts()
let contact3 = contacts.create()
let contact4 = contacts.create("Mary")

How to check if an object has a stored property?


import Foundation
class MyClass: NSObject {

var myVar1 : AnyObject!

// ...
}

let myClass: MyClass = MyClass()
let hasClassMemberMyVar1 = myClass.respondsToSelector(Selector("setMyVar1:")) // true
let hasClassMemberMyVar2 = myClass.respondsToSelector(Selector("setMyVar2:")) // false

it works for me ...

UPDATE, based on OP notes

import Foundation
class C:NSObject {}
class MyClass: NSObject {
var myVar1 : C? // Objective-C representable
var i: Int = 0 // Objective-C representable
var j: Int? = 10
}

let myClass: MyClass = MyClass()
let hasClassMemberMyVar1 = myClass.respondsToSelector(Selector("setMyVar1:")) // true
let hasClassMemberMyVar2 = myClass.respondsToSelector(Selector("setMyVar2:")) // false
let hasClassMemberI = myClass.respondsToSelector(Selector("setI:")) // true
let hasClassMemberJ = myClass.respondsToSelector(Selector("setJ:")) // false, because Optional<Int> is not representable in Objective-C !!!
print(myClass.i.dynamicType, myClass.j.dynamicType) // Int Optional<Int>

with class type properties only

import Foundation
class C:NSObject {}
class C1 {}
class MyClass: NSObject {
var c : C?
var cO1: C = C()
var cO2: C!
var c1: C1 = C1()
var c2: C1?
var c3: C1!
}

let myClass: MyClass = MyClass()
let hasClassMemberC = myClass.respondsToSelector(Selector("setC:")) // true
let hasClassMemberCO1 = myClass.respondsToSelector(Selector("setCO1:")) // true
let hasClassMemberCO2 = myClass.respondsToSelector(Selector("setCO2:")) // true
let hasClassMemberC1 = myClass.respondsToSelector(Selector("setC1:")) // false, class C1 is not Objective-C representable ...
let hasClassMemberC2 = myClass.respondsToSelector(Selector("setC2:")) // false, Optional<C1> is not Objective-C representable ...
let hasClassMemberC3 = myClass.respondsToSelector(Selector("setC3:")) // false, ImplicitlyUnwrappedOptional<C1> is not Objective-C representable ...


Related Topics



Leave a reply



Submit