RxSwift - Class property's binding - ios

I have an question about binding:
I have an array of objects of my custom class: Array. Every object can be updated (change his properties value) in bg.
Also I have separated Controller, which take and store one object from list as variable and can update it (object still the same, so in list it will be updated too)
Is there any way to bind all object.property -> UILabels on Controller in way, when property changes automatically call label update?

Of course, there are multiple ways how to do it, but from your description I would use some kind of subject (because u said there will be changes in background so you will probably need hot observable )....For example Variable or PublishSubject. So you can crate
let myArrayStream: Variable<[MyObject]> = Variable([])
you can pass this variable as dependency to wherever you want, on one side you can subscribe to it, on the other side you can update it's value.

Related

Modify behaviour of subobjects

Is there any way to modify the behaviour (methods) of a sub-object by redefining them when subclassing a component . e.g I am subclassing Tlistbox , and i want to modify the behaviour of Delete() method of its Items subobject . Is there a formal way to do so ?
Thanks
Based on your comments, you don't actually need to change the behavior of the Items property itself. There are other ways to detect when items are being manipulated in the ListBox so you can update your own internal objects as needed.
When deleting items, the Items.Delete() method simply calls TCustomListBox.DeleteString() passing it the index to delete. DeleteString() can be overridden by a descendant. Simple enough.
When adding/inserting new items, it is not quite so straight forward. Items.Add() sends a LB_ADDSTRING message directly to the ListBox's HWND (unless the ListBox's Style is set to virtual mode, in which case Add() simply exits without doing anything). Same with the Items.Insert() method (LB_INSERTSTRING message). To catch those message, you have to override the ListBox's virtual WndProc() method.
Items.AddObject() calls Items.Add() first, and then uses the Items.Objects[] setter to assign the object to the new item. Same with Items.InsertObject(), calling Items.Insert() instead of Items.Add().
When updating an existing item's string via the Items.Strings[] property, things get a bit complex:
TCustomListBox.InternalGetItemData() (can be overridden) is called to retrieve the item's existing object, if any. By default, InternalGetItemData() calls GetItemData() (which can also be overridden), which by default sends a LB_GETITEMDATA message to the ListBox's HWND.
TCustomListBox.InternalSetItemData() (which can be overridden) is called to set the item's object to nil (in case Delete() in the next step tries to destroy it). By default, InternalSetItemData() calls SetItemData() (which can also be overridden), which by default sends a LB_SETITEMDATA message to the ListBox's HWND.
Items.Delete() is called to remove the item.
Items.InsertObject() is called to insert the new string with a nil object
TCustomListBox.InternalSetItemData() is called to restore the original object to the new item.
When updating an existing item's object via the Items.Objects[] property, if the ListBox's Style is not set to virtual mode then TCustomListBox.SetItemData() is called.
When moving items around using the Items.Exchange() method, if the ListBox's Style is set to virtual mode then Exchange() simply exits without doing anything. Otherwise, it uses the Items.Strings[] property to swap the two item strings, and calls Internal(Get/Set)ItemData() to swap the two item objects.
So, basically, everything you need to manage internal objects boils down to overriding these methods:
TCustomListBox.DeleteString()
TCustomListBox.WndProc() to handle LB_(ADD/INSERT)STRING, and maybe LB_(GET/SET)ITEMDATA.
TCustomListBox.Internal(Get/Set)ItemData() or TCustomListBox.(Get/Set)ItemData()

If I am observing a collection via KVO, am I notified of changes to objects within the collection?

I assume not, but always like to double check.
Let's say I have an NSMutableArray I'm KVObserving. It holds a bunch of Employee object. If I fully assign the array, then no doubt I'll observe the change. However, what if I change one of the Employee objects references/value/objects in the array, such as employee.salary.
I assume there is no KVO notification, here correct?
And if you ever wanted something like this, how would it be achieved?
One quick nitpick: you can't be key-value observing an NSMutableArray. That's not what KVO does. What you're doing is key-value observing some property (say "employees") of some object. That property may be typed as an NSMutableArray (although that's a terrible idea) or merely backed by an NSMutableArray. But you're not observing the array. You are observing the object for changes in its employees property.
Key-value observing a collection property does not observe the properties of the objects in the collection. In general, there's no way to observe all properties, wholesale, of any object.
If you want to observe some specific property or properties of the objects in a collection, you should:
Consolidate all mutations of that collection to separate methods. You should already have done this to make your employees property KVO-compliant. In particular, I recommend that you implement the indexed collection mutating accessors.
Within those methods, use -addObserver:toObjectsAtIndexes:forKeyPath:options:context: and -removeObserver:fromObjectsAtIndexes:forKeyPath:context: to start and stop observing some key path(s) of the elements that are being added to or removed from the collection. You need to do this in the setter (-setEmployees:) for the employees property, too (stop observing all of the elements of the old array, replace it with the new array, start observing all of the elements of the new array).
Don't forget to stop observing the elements before the array is released, for example in -dealloc.
Try this :
[[employee mutableArrayValueForKey:#"salary"] addObject:...]

Detect if at least one property of object was modified

I have class with many strings and mutable arrays. All this objects represent form data. So if I modify textfield or add new photo to array I keep this data in my properties of object.
How can I create validator that will check if some of that properties were changed.
For example I have add some photos to array. Then I save it. When I reopen this screen again I see saved photos, but right now I want to add new photos.
The initial state and state after I add new photos to array will be different and I want to track it.
The simplest way I see here save current state of all objects and then compare it with new stat.
Let's say I have next variables:
NSString *name;
NSString *lastName;
NSMutableArray *photos;
I can use for example KVC to detect if some object was modified, but it works for example for array. So if array was modified, we can suppose that the data was changed. But for example if I property name had string #"Alex" and then I put here string #"Alex" again from text field, I can compare it with previous state and current state and make a conclusion that state was changed if strings will be different. Is this right way?
You can try Method Swizzling, ex: http://nshipster.com/method-swizzling/. To hook whether your set method be called.
You can use KVC or Delegate to notify the changing.
You can use immutable object to make sure your object is not changed, then hook when it's created.

Sending NSNotifications to all objects of a class

I have an object that can be selected by a user click. With the current requirements of the app, at any time, there is no more than one of these items selected at any point during app execution.
I implemented a mechanism to enforce this, as follows:
Each of these objects has a unique identifier as a property.
When each object is created, it subscribes to the NSNotificationCenter listening for the MY_OBJECT_SELECTED notification.
When each object is selected, it posts the MY_OBJECT_SELECTED notification, with its unique Id as part of the userInfo dictionary.
Then, when each object receives the notification, it checks to see if its id is the same as the one in the userInfo. If it is, it does nothing, but if it isn't, it sets itself to unselected.
Is this a decent approach to the problem? If not, how would you do it?
It is a decent way of doing it, although it is not very efficient. The more objects you have, the more time you spend comparing IDs. The easiest way is to store your object pointers and IDs in a map table (or similar) and remember the last selected object. Whenever you select a new object, you clear the selection flag of the last selected object, then look up the new object and set its selection flag. It requires you to keep a collection of your objects, though.
The time required to update selections with this approach is independent of the number of objects you have.
If the object is spread all over the app,i.e. if it is a member in various classes. You can have a global object of same type and assign it to only that object which has been touched. In steps it will be like:
Have a global variable of object type.
At any object touch assign globalObject = currentObject;
do all operations on globalObject throughout app like calling methods and modifying object members(have a check for nil to ensure safety).
Reassign to different object with new touch.

Creating new Objects With SPRING.Net

I'm new on spring.net, and I'm tring to create an List<> of objects.
The list is initialized by a loop that calls:
IObj obj= (IObj)ContextRegistry.GetContext().GetObject("obj")
change object properties....
add it to the list...
the problem is : I keep getting the same object every step of the loop
so I get a list of the same object
If your object definitions are not singletons, then you will get a new object each time. Note, by default, singleton is set to true, so you have to explicitly set it to false.
For example, if you are using xml files to configure your objects, set the singleton attribute to false:
<object name="name" type="..." singleton="false"/>
It is not clear what you are trying to achieve by looping over the "GetObject("obj")" method. Maybe you can post the loop-code?
What "GetObject("obj")" does is to ask the Container for the Object with the name "obj". You stated that want to change the object's properties and add it to a list. This is something the container can do for you:
Set the properties of an Object:
http://www.springframework.net/doc-latest/reference/html/objects.html#objects-simple-values
Create a list:
http://www.springframework.net/doc-latest/reference/html/objects.html#objects-collections-values
This list can be injected into an Object you choose.
If you just want non-singleton objects of your IObj, naders answer is correct. Spring calls these non-singleton objects "prototypes". An overview of available Scopes can be found here: http://www.springframework.net/doc-latest/reference/html/objects.html#objects-factory-scopes

Resources