Cocoa Bindings and Checking for String content - objective-c

OK, here's what I want to do :
Let's say I have an item, e.g. an NSTextField
Let's also say we want to bind its hidden value to a BOOL variable - that's easy.
Now, here's the twist :
I want to bind the hidden property to a check in the fashion of (someStringVariable == "Some String")
In a few words : set the element to hidden when someStringVariable is equal to some string.
How can I do that from within the IB? Is it doable?

Well, this is basically a duplicate of this question which I answered. But somebody other than the questioner has put a bounty on this one, so:
Entirely within IB? No.
You can bind to a string-typed property and then use a custom value transformer to convert that string to a boolean according to its equality to the desired value.
However, it's probably just easier to add a property to the class that has the string-typed property:
// Assumed to exist:
#property (copy) NSString* someStringProperty;
+ (NSSet*) keyPathsForValuesAffectingShouldBeHidden
{
return [NSSet setWithObject:#"someStringProperty"];
}
- (BOOL) shouldBeHidden
{
return [self.someStringProperty isEqualToString:#"desired string"];
}
Since this property is really part of the UI rather than the model, you may wish to define it in a category on the model class. The category itself would be declared and defined in the controller code.
Once it's defined, you can bind to the shouldBeHidden property.

You mean someting like this?
string1=string2 ? hidden=true : hidden=false

Related

Remove object from arraylist by property value

I have the following problem:
I have a arraylist called "list" which contains objects of the class "SampleClass", the objects have a property "name".
Now I would like to remove a object with a certain "name" value, without knowing the index.
I have tried the following:
list.remove(SampleClass("Village"))
So, the idea would be that the instance of SampleClass where the property name contains "Village" is removed from the list.
It compiles allright, but its not working.
If you want to remove all elements with that name, you can use removeAll:
list.removeAll { it.name == "Village" }
If you only want to remove the first item with that name:
If the name is the only property of the class, you should just make it a data class so equals() is based on the name. Then you could use the code you posted.
If it is not the only property, you will have to get the index in the list and remove it that way:
list.removeAt(list.indexOfFirst { it.name == "Village" })
The way you have it now, you would have to override the equals method in SampleClass to check if the name property is the same. Right now, it probably doesn't work because the default equals method won't compare the name property and so the SampleClass instance you want to remove with that property as "village" will be considered not equal to the SampleClass instance you're passing in.
Otherwise, you can also use list.filter { it.name != "village" }

What do you call a variable that has a getter and setter defined, with no backing variable?

What is it called when you define a variable/property with a getter and setter, such that the language does not automatically generate a backing variable?
E.g. in Swift, we could define a modalViewController property that doesn't create a backing variable:
extension MyViewController {
var modalViewController: UIViewController? {
get { return self.presentedViewController }
set { self.present(newValue, animated: true) }
}
}
What's the proper term to describe the modalViewController property?
I know that if it's only gettable, it would be called a computed property:
extension Int {
var isEven: Bool {
get { return self % 2 == 0 }
}
}
However, I'm looking for a term for something that is both settable and gettable.
The reason I'm looking for a term is that I want to ask a question related to these types of properties, and would like to use common, non-ambiguous language. I thought this would be called a virtual property, but it doesn't appear to be the proper name as virtual has a different meaning in OOP.
Even though they have a setter too, Swift (at least) calls these "computed properties" (emphasis added):
In addition to stored properties, classes, structures, and enumerations can define computed properties, which do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.

Collection<KProperty1<I,*>> How to get the property instance

I'm currently using Reflection to inspect an element at runtime using the class.memberProperties function. The type of properties is collection<KProperty1<I, *>> so I run through each of the KProperty objects to find the one that I want by checking if the name is equal to "nameIWant", though I would much rather be able to get the instance of the property from the KProperty by using the .get() method on the property, so that then I could do a check such as:
if (property.get(receiver) is ClassIWant) {
//Do something
}
My code looks like this:
val properties = request.payload::class.memberProperties
properties.forEach { property ->
run {
if (property.name.equals("nameIWant")) {
}
}
}
So far I've been trying to use the .get() method on the KProperty1 type but it takes an argument receiver of type Nothing. I'm not able to work out what I need to pass in order to call the .get() method and get the particular instance of the property. I've also checked the documentation here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property1/index.html but it hasn't really helped at all.
justPassingBy is right. but the more simple way is to use:
myObj.javaClass.kotlin.memberProperties.foreach { property ->
property.get(myObj)
}
If you want to get the value of the property, cast the class into invariant type.
instance::class.memberProperties.first() // returns KProperty1<out Instance, *>
(instance::class as KClass<Instance>).memberProperties.first() // returns KProperty1<Instance, *>
If your KClass<Instance> is KClass<*>, use Any as Instance.
Why did the KProperty.call take Nothing as receiver?
Because instance::class returns KClass<out Instance>, which propagates the covariant type argument down to the property, which it becomes KProperty<out Instance, *>, which narrows down the possible method receiver to any subtype of Instance, but because we do not know which, we can not safely supply any instance of Instance, as show by the rules of variance, which here limit the generic type argument to Nothing, which means it is impossible to call the method at all.
Why is ::class designed to be covariant?
To guarantee safety. This has been an issue of great debates as it seems somewhat illogical.
If you want to know the type of the value that the property can return, use
property.returnType
It returns a KType, wich is Kotlin's version of Java's Type, which is a more generic concept of a Class (which is one of the implementations of Type).
If you need to 'convert' the KType to a KClass, you need to do the same as if you needed to convert Type to a Class, which is get the raw type of the type. Raw type is type stripped of the any generic information, yes, an erased type. The way to do this is (seemingly) more complicated (involves handling each possible KType/Type implementation) and I recommend checking for answer to this problem separately.
You will be able to reuse Java implementation (that you will surely find on your own) using:
kType.javaType.covertJavaTypeToJavaClass().kotlin // returns KClass<*>
Corrections in your question. I recommend using the proper terms if you wish to receive proper answers:
* I in your question is type of the method receiver, not the value of the property
* collection is not a type, Collection is
* property is ClassIWantis ambiguous as property.type is type of the value in the property and property::class is simply the property implementation, is is also an instanceof check, but in reflection, you need to use KClass.isSubclassOf, or what is known in Java as type.isAssignableFrom (watch the call order), which then makes your condition to be ClassIWant.isSuperclassOf(property.type.getRawType())
* instance of the property properties have values, not instances. Only classes have instances. Instances are values and values are instances (of some class), but you must still say instance representing the value of the property
You can create a KType for your ClassIWant and then check the property's returnType. It will be something like this:
val properties = request.payload::class.memberProperties
val desiredType = ClassIWant::class.createType()
properties.forEach { property ->
if (property.name == "nameIWant" && property.returnType == desiredType) {
//todo
}
}
btw you can cast your property variable to correct type and use get
val properties = request.payload::class.memberProperties
properties.forEach { property ->
val value = (property as KProperty1<Payload, *>).get(request.payload)
if (property.name == "nameIWant" && value is ClassIWant) {
//todo
}
}
prop.getter.call(obj) as String?

Send object in function & comparison them to coincidence with other objects

I want to send some object to function for check it and set him some data.
For example:
i have 4 properties (with int type) of self class (inherit from NSObject class). And i want to change their data in one function. I must send dress of this properties into function, check it to compare with this dresses of this properties: self.opt1, self.opt2, self.opt3, self.opt4, and set them some values.
I try to create function:
- (void)setupMultiplierForObject:(id)object
but i don't know how i can check object argument to comparison self.opt1 (object to object, not their values).
What if must set into if (<here>) {} construction?
I fix-it with next construction:
[self setupMultiplierForObject:&((*self).time1)];
- (void)setupMultiplierForObject:(int*)object {
if (object == &((*self).time1)) {
// Doing something with self.time1, because we know that ended object - is self.time1
}
}

property doesn't set after lazy initialization objective-c

I have a BOOL property and at the start this property equals NO. I want to set this property to YES from the start of my program, but with opportunity to toggle it.
For this, I made this getter:
-(BOOL)turn
{
if(!_turn)
_turn = YES;
return _turn;
}
This getter set my turn property to YES, but it makes it "constant", always YES.
Why?
I thought
if(!_turn)
construction is specially for the reason where you want set the "not set yet" object value
Can you answer me why this is so? And how can I set my property value to what i want. Thanks.
Look at your action table:
turn: False True
!turn turn = YES Do Nothing
When _turn is false, you flip it too true. When _turn is true, you do nothing (there's no else statement). Then you return the value of _turn. So yea, you are returning true in all cases.
To be honest, the design is not very good. If you want to set the initial value of the variable to a certain value, do that in the init method. Then provide another method that simply toggles the value:
-(BOOL) toggleTurn {
_turn = !_turn;
return _turn;
}
Usually the lazy initialization technique is used with pointers to objects, not with primitive types. This because a BOOL has only two possibile states: NO and YES, there isn't the "undefined state" which is usually associated with nil for objects.
The reason why it doesn't toggle is that you aren't toggling it, you are just setting it to YES when it's equal to NO, but you aren't handling the case when it's equal to YES. If you want to toggle it just do that:
-(BOOL)turn
{
return _turn= !_turn;
}
PS: Whoever could argue that your method isn't properly a getter, because you are altering the variable before returning it. So I suggest to just return _turn without toggling it, and to create another separated method to toggle the variable.
Also I would like to mention that what you are doing is not called lazy initialization, I'll show you a case of lazy initialization:
// In the interface:
#property(nonatomic,readonly) NSNumber* turnObject;
// In newer compiler versions it should be auto synthesized to _turnObject
// In the implementation:
-(BOOL) turn
{
// In this case I am not toggling it
if(!_turnObject) // Equal to if(turnObject==nil)
_turnObject= #(NO); // Equal to _turnObject=[NSNumber numberWithBOOL: NO];
return _turnObject;
}