How to track how many times a UIButton has been pressed? - objective-c

I need to know how many times a button in my program has been pressed. I tried making a category of UIButton and adding properties to it so that each time a button is pressed I would say sender.someproperty++; but the compiler complains when I add properties to a category.
Any way I can track this? I wish every object in Xcode had a random unassigned integer property that you could randomly assign it different values to keep track of each object
the first time I press the button, I want something to happen, the second time, I want something else to happen, the third time, I want something else to happen, and then the fourth time I want it to default so its like I'm pressing it the first time.

What youre going to want to do is to create a buttonPressedCounter property in the view controller of the view that the button is in, and keep track of it that way.
As for the changing functionality, define it for buttonPressedCounter = 0, 1, and 2, and after that either reset the counter in your behavior for buttonPressedCounter = 2, or your check should be based on buttonPressedCounter % 3.
EDITED FOR COMMENTS:
What you can also do, I think, is to create a new class that extends UIButton, and declare a counter property inside of it. This should work for you, and may fit your tastes better than an array of counter variables.
Might look something like this,
#interface UIButtonCountable : UIButton
{
int _clickCounter;
}
#property (nonatomic) int clickCounter;
#end
Another option again, is to not use a UIButton, but to use either a slider with 3 possible values, or segmented control, though I have little to no experience with either of those.

Subclassing UIButton is definitely dangerous, because UIButton not a single class but a class cluster. I highly recommend not doing this. According to Apple:
The class cluster architecture involves a trade-off between simplicity and extensibility: Having a few public classes stand in for a multitude of private ones makes it easier to learn and use the classes in a framework but somewhat harder to create subclasses within any of the clusters.
A new class that you create within a class cluster must:
-Be a subclass of the cluster’s abstract superclass
-Declare its own storage
-Override the superclass’s primitive methods
Instead of adding a property to the category, you can use associative references and add getter and setter methods to the category to simulate a property on the button.

Related

Creating Multiple windows of same NSWindowController class type

I want to create a NSWindow of same NSWindowController class type each time user sends an action.
This is my Code.
objController = [[MyController alloc] initWithWindowNibName:#"MyController"];
[objController showWindow:nil];
This is a simple two liner which gives me NSWindow. but the thing is, If I don't make a class level object, the window doesn't get displayed. So, I had to make a class level object. It worked well and gave me NSWindow of type MyController.
But, since it is a class level object, If I want to trigger this action every time user clicks on a button, previous window gets closed. And new window gets appeared.
I don't want this to happen. I want to keep all the previous NSWindows in memory and user can interact with them.
How do I do it ?
I think, this should be something small but at the time I don;t have any solution in my hand.
Kindly help me to get this.
Thank you.
My guess is that by "class level object" you mean a #property of type MyController, which can indeed only hold a single window controller. If you need to store several instances of MyController and do not want to create a separate #property for each of them, you need to put them into an array type, namely a NSMutableArray.
Add a #property NSMutableArray *myControllers to your class and initialize the array (for example in the - init method or your class) with self.myControllers = [NSMutableArray array].
Now you can add newly created window controllers to it with [self.myControllers addObject:] which makes them stay in memory instead of overwriting each other by sharing the same property for storage.

Right way to create a customizable uiview

this question is about "style", because i think this is a very common problem and i'm looking for an elegant solution.
I have created some "advanced" UIView and i try to make them very customizable.
Usually i create the UIView structure inside a custom init method, but i need to know the value of all customizable parameter inside init method so sometimes i need a very long init method like:
initWithFrame:color:font:verticalspace:verylonglist:
I tried to use delegate design pattern but i need also to pass delegate inside init method.
My actual best solution is to leave empty the init method and move everything about layout inside a "configure" method. everytime i chance a property like background color or font i will call this method and i will rebuild the view.
I think there is a best way to solve this problem...
I'd be curious to see the code of UITableView Class, because with that class you can pass a delegate outside init method.
Check out something like a UIButton or UILabel. They both have tons of configurable aspects, however to simply create an instance of one of those objects, they need very little information.
In general, provide init methods that allow the consumer of your class to specify the least amount of information for the class to work.
If you do want to give the consumer a way to initialize the class with a bunch of values, consider using some sort of initWithDictionary: method that takes an NSDictionary of parameters. This keeps your method names short and allows the user to customize an arbitrary number of settings for your class.
You could also consider providing a way for the consumer to request an instance with some standard set of values. UITableViewCell, for example, has an initWithStyle:reuseIdentifier: method. The important part is the style - UITableViewCell provides several default styles like UITableViewCellStyleDefault and UITableViewCellStyleSubtitle.
I don't know if it is the standard/best practices way but I use a dictionary in cases like this and pass that to an initWithDictionaryinitializer. Would be possible too to create a class method that returns a 'default settings' type dictionary which can then be customized (and delegate set), so that not every param needs to be specified whenever the class is used.

Objective-C / Cocoa Touch: Is it good design to set label texts in the setter of the UILabel object?

Let's say I have a two subclasses of UIViewController called MasterViewController and DetailViewController.
DetailViewController has a property of type NSNumber called level and a UILabel called levelLabel.
MasterViewController has a segue to DetailViewController called ToDetail. MasterViewController's prepareForSegue is like so
- (void)prepareForSegue:(UIStoryboardSegue)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ToDetail"]) {
DetailViewController *detailVC = (DetailViewController *)segue.destinationViewController;
detailVC.level = [NSNumber numberWithInt:10]; // never mind the literal...pretend there was some algorithm for it
}
}
So then, in DetailViewController we implement the setter for levelLabel like so:
- (void)setLevelLabel:(UILabel *)levelLabel
{
if (levelLabel) {
_levelLabel = levelLabel;
_levelLabel.text = level.stringValue;
}
}
Is this good code design? Also, could you critique my code writing style? I pretty much wrote all this code on the fly so this is pretty much how I write code for the most part.
I thought of this question while showering because this is how I implement the setting of almost all the label texts that depend on a segue.
What follows is my own way of thinking about such relationships. Italics applies to your question.
You have the thing being controlled (the label) the controller (destination view controller) and the context it is being controlled within (the source view controller). This can also be expressed as model-view-controller, but I think thinking about a context can apply to much more specific and localised situations.
You should generally try to keep information flow going in one direction, from the context downwards. Objects should not have to be aware of the context in which they exist, ie they shouldn't have to ask for any information, they should be told everything they need to operate. So the source view controller should push the level to the destination view controller, the destination view controller should push this information to the label. This is what you already have, sort-of.
To build upon the above, not only should information flow in one direction, but I also try to ensure the relationships are causal, ie pushing information from one object to another should cause it to subsequently be pushed to the next object. Your code is not doing this which is probably why you have a bad feeling about it.
A more appropriate thing to do is set the text property of the label within the level setter, so that when you set or change the level, the label will update subsequently. The label may or may not be loaded so you will have to check whether it is using -isViewLoaded; -viewDidLoad is the appropriate place to set the text property upon first load.
(When I say 'push' that's just my way of thinking about setting properties or passing arguments because it implies directionality. It is really dependency injection. An example of pulling information would be delegates and data sources. But note here still the object isn't aware of any context, delegates and data sources are clearly defined as protocols, not classes, and usually within the same header file, and are themselves pushed onto the object from a surrounding context. So yes the object is asking for information, but on its own terms and from a system it has no knowledge of.)
Re coding style:
That's exactly how I write code but note Apple reserves the use of underscore prefixes

Changing the class of an ivar (to a derived class), in a subclass

Assume I have two base classes, Container and Gizmo. Class Container has an instance variable of class Gizmo.
Now I subclass Container (call that SubContainer) and I also subclass Gizmo (SubGizmo). In some of the methods of SubContainer I need to send a message to some properties that Gizmo doesn't have but SubGizmo does. Is there any way to override the ivar to be of class SubGizmo in SubContainer, so I can send those messages?
Right now I can make it work by casting my inherited ivar to SubGizmo every time I need to use such a property or method.
Here is why I want such a behavior: I already have a game that works, but the more modes I add, the harder it gets to maintain. If I want to change/add a method that will run on each mode; I would need to go to three different game - controller objects and make the change.
By subclassing, I wanted to keep the main game mechanics in the base classes and create a subclass for each mode. this way a change I make in a base class would reflect on each mode. However each controller and game object have new methods for different modes, and they send messages to each other. This is where my problem is arising from.
just introduce type safety and conversion logic using an approach like this:
#interface SubContainer ()
- (SubGizmo *)subGizmo;
// setter is often unnecessary
- (void)setSubGizmo:(SubGizmo *)pSubGizmo;
#end
#implementation SubContainer
...
- (SubGizmo *)subGizmo
{
Gizmo * ret = self.gizmo;
// sanity check the type to ensure this is properly initialized,
// or return nil if holding a Gizmo is valid in this context:
assert([ret isKindOfClass:[SubGizmo class]]);
return (SubGizmo *)ret;
}
- (void)setSubGizmo:(SubGizmo *)pSubGizmo
{
self.gizmo = pSubGizmo;
}
- (void)addWater
{
[self.subGizmo addWater];
}
#end
however, the creeping complexity suggests more variations in types is worth consideration.
just use type id for your ivar, you only have to include the proper header file to avoid warnings.
The easiest way would be to use SubGizmo in Container, not Gizmo. :-)
However, if you can't do that directly for some reason, you can modify SubContainer at runtime (seek for class_addIvar or class_addMethod, I can give you an example when you need it), but that does not help to avoid Xcode's warning.
You canu use NSNotifications for sending updates to all your game controllers.

objective-c identifying contentView items

Is there a way to identify unique objects within the contentView? For example, I in my mainWin I have a NSView and 2 NSButtons. Using
[[mainWin contentView] subviews];
I can get all the objects within the mainWin. This works fine for my needs if the object is a subclass of NSView and I've given it a class, for example, in this case I've named the class vHUD and when I log the object it comes back as
<vHUD: 0x146e10>
This is fine for NSViews I am creating because for the most part if I am making them they are going to serve multiple purposes (content container, being toggled around screen, etc.) and a class should be necessary. I could subclass all the buttons (under NSObject) and go that way, but it seems like a sledgehammer approach if I end up having a lot of buttons. Is there a way I can uniquely identify all of the buttons with something descriptive in IB that can then be retrieved from the object itself? I tried "description" but that didn't return anything.
Have you tried using the tag instance variable in the NSView class?