0
votes

I have a very simple toolbar button in one of my apps allowing the user to upload an object. While the object is being edited I hide the toolbar (to not allow uploaded while editing). Also I want to enable/disable the upload button depending on whether the object has any changes that were not uploaded yet. (E.g. after a successful upload the upload-button is disabled, after editing but before uploading it is enabled)

I have a property with the uploadButton like this

@property UIBarButtonItem *uploadButton;

and set it up in viewDidLoad like this:

self.uploadButton = [[UIBarButtonItem alloc] initWithTitle:@"Upload" style:UIBarButtonItemStyleDone target:self action:@selector(upload:)];

During an upload operation I use the toolbar to display a progress bar for the upload, but before that and after an upload I add the upload button to the toolbar like this:

NSArray *toolbarItems = @[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL],
                             self.uploadButton,
                             [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL]];
            [self setToolbarItems:toolbarItems animated:YES];

However, sometimes setting the self. self.uploadButton.enabled property does not seem to have an effect (the button's appearance is not changed). In a case where the button should be enabled but appeared disabled, I checked with the debugger and found that self.uploadButton.enabled actually was correctly set and even was YES after the actual change event.

I then digged a little deeper looking at the view hierarchy and noticed something odd:

(lldb) po [[0xf72eba0 uploadButton] view]
 nil

(the pointer points to the view controller object so it's the same as "self" above) Also: [0xf72eba0 uploadButton] is non-nil, so it's not a case of messaging nil. And: yes -view is not a documented method on UIBarButtonItem, but as a UIBarButtonItem is not a UIView itself, I figured it has to have a view and apparently I was right.

To put that into context, the following

(lldb) po [[0xf72eba0 editButtonItem] view]
<UINavigationButton: 0xf782de0; frame = (645 8; 42 30); opaque = NO; layer = <CALayer: 0xf784500>>

has a view. Also on a subsequent run, when everything worked as expected the upload button had a view as well:

(lldb) po [[0xf72eba0 uploadButton] view]
<UIToolbarTextButton: 0x1196eb40; frame = (323 0; 57 44); opaque = NO; layer = <CALayer: 0x1196f330>>

To summarize:

  • The uploadButton is not released, it's a strong property. Also, it's still there when I check.
  • The enabled property is correctly set.
  • Strangely sometimes the uploadButton does not seem to have a -view. This seems to be related to it not being updated correctly.
1

1 Answers

0
votes

While writing the question I realized what the actual problem was:

I sometimes update the upload-buttons title (e.g. when the localization changes, as that can happen at runtime in my app) and to do so I replace all the barButtonItems. But I only added the new uploadButton to the viewControllers -uploadButton property, NOT to the toolbar.

But since I do add the uploadButton from the property to the toolbar after a successful update, the problem would go away after an upload happened and it only occurred rarely.

So the actual problem was: The UIBarButtonItem added to the toolbar was not the one saved in my property. Instead the one in the toolbar was an old one that should have been replaced. And as I was only setting the enabled property of the button saved in the property that obviously didn't change the barButtonItem in the toolbar. Also: my property-barButtomItem did not have a -view as it had not been added to the toolbar yet.

I hope someone else having problems with UIBarbuttonItems not being updated correctly might get on the right track by reading about my problems. ;-)