0

OSX desktop ap in Objective-C...

I think this is a basic question, but even after spending a good deal of time with the KVO guide and various related questions I can't quite wrap my brain around what's going on in this particular case (alternatively, this is just bad form and I should stop)

  1. Create a custom class, let's call it "OtherClass" and give it a property:

    @interface OtherClass : NSObject{}
    @property NSString* aString;
    
  2. Inside a ViewController, create an instance of this custom class

    oc = [[OtherClass alloc] init];
    
  3. In the interface builder associated with the ViewController class, bind a field like so:enter image description here

What I'd like to happen is that whenever something like [oc setAString:@"SomeValue"] is called, the UI is updated, but the text field does not update when the value changes.

For what it's worth, the actual use case is a singleton class which is a manager for an external piece of hardware. I would like to be able to have other parts of my program (inside the code for the hardware, for instance) update a status string when the hardware status changes. It would be super nice if I could just bind a UI field to "viewController.hardwareMgr.status" and then call "[hardwareMgr setStatus:@"allGood"]" wherever I like, and be done with it.

I do understand conceptually that the problem is the nib isn't receiving the update notifications but I'm not sure the best way to fix this. I can of course manually register a listener on the viewController, for instance, and could use this to "proxy" updates to a local property on the viewController, but this seems awkward at best. As my manager class is a singleton, I could also create another "instance" inside IB and bind to this, but this seems awkward for different reason and not applicable to non-singleton cases.

How to accomplish this, or is this pattern simply a bad idea?

andrew
  • 218
  • 3
  • 12
  • Is `oc` a property of the viewController? In any event, it matters where in the VC code you initialize it. Since it's in the VC, it doesn't exist a program startup, it only exists when the VC exists and has gotten to whatever method you stuck the oc alloc-init line in. You could instead create the oc instance in the application delegate and bind through the application to `delegate.oc`. However if it's just a single string, the common OSX pattern is make the string a value in the NSUserDefaults to bind to the shared user defaults controller. – stevesliva Jan 22 '16 at 17:19
  • Yes, oc is a property of the VC. The timing might make sense but I tried doing this via the application delegate with the same results - I can't seem to get properties of properties working. NSUserDefaults would totally work, but is that really the usual way? It seems a bit awkward for values that you don't really want to be persistent (and anyway it's mostly relying on the singleton again, so I could just do that) hrm... – andrew Jan 22 '16 at 18:24
  • If it doesn't persist, delegate should work. You might need `self.oc.astring` as the keypath in your image. There is a debug switch you can use to get warnings in your log if the IB bindings are not finding a target. – stevesliva Jan 22 '16 at 18:49
  • What you want to do should work. How is oc defined? Is the ViewController in the xib the same ViewController where oc is defined? Are the ViewController and OtherClass KVO-compliant? – Willeke Jan 23 '16 at 13:28
  • @Willeke Ok thanks, good to know I'm not totally off base. Yes the VC is same as the one in xib. OC is an ivar but is really just OtherClass* oc = [[OtherClass alloc] init]; The actually OC class itself is apple boilerplate with a single property (aString) defined by @ property. As for KVO compliance, possibly not? In this instance I've done nothing other than add the prop. I'm basing this on apple docs that say "Typically, if you follow standard Cocoa coding and naming conventions, you can use automatic change notifications—you don’t have to write any additional code," but maybe I should? – andrew Jan 23 '16 at 17:56
  • willeke Ah-ha! Thank you for pointing me in the correct direction with the question about How is oc defined. Turns out I was initializing oc in the awakeFromNib method, which was too late. I moved the initial oc = [[OtherClass alloc] init]; into initWithCoder instead and it works perfectly. This is also pretty much exactly what @stevesilva said in the first line of his first comment. If either of you would like to write that as an answer I'd be happy to accept it. – andrew Jan 23 '16 at 18:26
  • @stevesliva hah :D Ok. – andrew Jan 28 '16 at 14:41
  • @Willeke would you like the answer? If not no problem, I'll write it up. – andrew Jan 28 '16 at 14:41
  • I didn't sugest to move oc to initWithCoder. It should also work if you set oc in awakeFromNib but you have to do it in a KVO compliant way `self.oc = …`. – Willeke Jan 28 '16 at 16:31

0 Answers0