iPhone Checkboxes à la Mail - iphone

After reading the iPhone Human Interface Guidelines, I notice there's little mention of checkboxes in the style that one may encounter them on the desktop or web.
Checkboxes are generally handled by UISwitchs on the iPhone, but for an app I'm presently working on, they're really not the right control. Instead, the control you'll see in Mail is a much better fit:
Actual mail blanked out. Obviously.
How would I go about using these checkbox controls in my app? Are they standard, or will I need to imitate them with a custom control?
Cheers friends.

You'll need to create a custom control. It won't be difficult since UIControl already has 'selected', 'highlighted' and 'state' properties at your disposal. You'll just need to draw and toggle appropriately.

Don't subclass UIControl. What you want is a UIButton of "custom" type. Load it with your "unlit" image in IB (or programmatically in -viewDidLoad--you can set it appropriate to its data there too, if you came here with that property already "checked").
Point its touchUpInside event at a method called -(void)toggleCheckBox, and in that method, toggle whatever setting you're toggling (probably a BOOL property of the objects you're listing), and toggle the "lit/unlit" status of the button image by using its -setImage: forState: method. Use the control state UIControlStateNormal.
I do something similar where I let people poke a button to toggle the "favorite" status of the thing ("thisEvent"--a member of an array of local cultural/arts events) they're looking at:
- (IBAction)toggleFavorite {
if (self.thisEvent.isFavorite == YES) {
self.thisEvent.isFavorite = NO;
[self.favoriteButton setImage:[UIImage imageNamed:#"notFavorite.png"] forState:UIControlStateNormal];
}
else {
self.thisEvent.isFavorite = YES;
[self.favoriteButton setImage:[UIImage imageNamed:#"isFavorite.png"] forState:UIControlStateNormal];
}
}

I'm pretty certain there is no standard way to do this. However it's fairly simple to achieve, all you need is two images, one for each state. I would probably do something simple like subclass UIImageView and add a setState:(BOOL)theState method, which would then simply select the relevant image.

I'd rather subclass UITableViewCell then UIImageView. UITableViewCell allready comes with selected/unselected states and handlers for editmodes etc.

As said before, you'll need to subclass UIControl. The actual process was discussed here w little while ago.

I also found a description of another way to do this using the same image/method that the Mail app uses:
http://networkpx.blogspot.com/2009/07/multiple-row-selection-with-uitableview.html
but as this implements undocumented features of the iOS SDK, it may not be best for apps intended for the official App Store.

Related

Design pattern for UI controls' state management in iOS

Similar to this question, but I am looking for a generic solution or design pattern or framework.
Q. How to add state management into all UI controls in my iOS app automatically without the need to rewrite the existing controls' class?
Example:
e.g. When I click on a UIButton, it will create a new UIWebView showing Google home page. That is easy, but problem arise when user sometimes.. click the button just too fast, so two webview will be displayed.
To solve this question, I would need to make a singleton class which contain the webview, and have a state variable isOpended and if it is true, reuse the existing webview instead of creating a new one.
But the problem is: If I want this behavior in other controls also, then I would need to create many many singleton classes..I am just thinking if there is better way to handle this without the new to re-invent the wheel.
Thanks.
I think you're solving the wrong problem here. Why don't you disable the button until the UIWebView is done processing. That way the user cannot click it twice.
- (IBAction)showMapHomepage:(UIButton*)sender
{
sender.enabled = NO;
[self taskThatTakesALongTimeWithCompletion:^{
sender.enabled = YES;
// Finish processing
}];
}
You are misinterpreting the best way to go about solving your problem. First of all, you should never find yourself in a situation where you are creating many many singletons. Singletons are a necessary evil, but you should not overuse nor abuse them. Here is a good post about singletons in objective-c.
There are numerous ways you could go about preventing a second UIWebView from being displayed when the user clicks your button.
As someone else stated, one solution would be to disable the button so that the user cannot "double-click" it. You do this using:
button.enabled = NO;
You could also hide your button using:
button.hidden = YES;
Or, in the header of the class that contains your UIButton, you could create a boolean that will handle the logic of whether or not the button has been pressed;
// declare this in your header
BOOL buttonPressed;
// this is the IBAction that your button hooks up to
- (IBAction)createWebViewButtonPressed:(id)sender {
if(!buttonPressed) {
buttonPressed = YES;
// insert code here to create your UIWebView
}
}
Again, there are numerous ways to accomplish what you are trying to do. You just have to determine which method is the best for you.
I agree with other answers that you should probably disable the control if you don't want it to be activated twice. However, if you do want an answer for your actual question about a generic pattern that you can use on all controls then you can use associated objects...
- (IBAction)buttonAction:(UIButton*)sender
{
NSString* webViewKey = #"AssociatedWebView";
// See if there is web view already
id webView = objc_getAssociatedObject(sender, webViewKey);
if(webView == nil)
{
// There is no existing web view, create it
webView = [self theWebView];
// Associate it with the button
objc_setAssociatedObject(sender, webViewKey, webView, OBJC_ASSOCIATION_RETAIN);
// Add the web view
[self.view addSubview:webView];
}
}
The above shows a generic way to associate an object to an instance of UIButton so you can check if it is already associated and re-use the existing one. I provide this answer in case you intend to use this in some other way that isn't fully described in your question, but in practice, you could use a property of your controller for the webView that lazy-loads the webView if it isn't already loaded.
If you really want to simulate the singleton style that you discuss in your question (so that you can have many UIButton instances that all share the same webView object if it already exists) then you could associate the webView onto the [UIButton class] object or even the [UIControl class] object instead of your specific instance. You would do that by replacing the sender with [UIControl class] in the code above.
One possible solution is to store a pointer to the webview in a property of the viewController. In the getter for the webview, create the webview if it doesn't exist already. The button action just need to display the webview, as it will just redisplay the webview if it already exist, and it will create the webview if it doesn't. When you are done with the webview, just set it to nil.

General advice on tracking an object's changes

I have an option menu where a user can change the application's settings. I need to track the changes. There is a DONE button, I want to make changes to the data model only when the button is pressed.
My question is, I am not sure the best way to track the changes. I don't want to introduce a giant if blocks in the doneButtonPressed button. Any general advice?
Well, the generic answer is: add callback to your controls in your options screen.
For example if you are using UISlider, then you have to customize it slightly. Probably create a subclass, that would receive touch events and then you redirect them to the delegate. OR you can use this one: RCSwitch
If you are using UIButton's then it's even easier: just add action to it.
After that you can create method like:
-(void) controlDidChange:(UIView*) control {
//mark changed items here
}

Xcode - Equivalent to Actionscript 3 event listener

Is there a similar method in xcode to the AS3 "AddEventListener" code?
I want to be able to watch for a certain thing to happen, but not use up too much memory.
Basically I have 8 buttons. Obviously I can't just go through a for loop to see if a touch is on them, I need an event or a trigger or something.
(The reason I don't just use normal buttons is that I need to be able to slide onto them.)
Any ideas?
I assume you are implying you are using UIView and not UIButton. What you are looking for is a UIGestureRecognizer, which you would attach to the view. Review the SimpleGestureRecognizers sample project for examples of how to accomplish this.
[yourButton addTarget:self action:#selector(clickHandler:) forControlEvents:UIControlEventTouchUpInside];
-(void)clickHandler:(id)sender{
//your actions
}

creating a reference for use in identifiying if a button was clicked

How is it possible create a reference for an uibutton to check if it was pressed and do something like make the value for that button true in order to be able to use that value later on. I heard of ivars but i havent seen any documentation on how to use them and im not sure if they would work for my ibaction uibutton...
This is really a fundamental question and a full explanation will take along time.
Basically, you need to understand the concept of MVC (Model-View-Controller). In this case, the "View" will be your UIButton created in Interface Builder. It needs to have a target/action setup to point to some "Controller". This will be a custom class you design that performs some action when the UIButton is released. This controller can also track finger up/down/move/drag and what not. This Controller will store the fact the button was pressed in a "Model" class.
Here is some more reading:
http://developer.apple.com/iphone/library/documentation/general/conceptual/devpedia-cocoacore/MVC.html
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html
In the simplest cases, this can be done with Core Data and IB without writing any code and simply making connections.

how to get input from UIAlertView?

I want take player name as input by using UIAlertView. Is it possible to add textField on the UIAlertView?
Since iOS 5, UIAlertView provides this: change the alertViewStyle property to one of the following:
UIAlertViewStylePlainTextInput (1 text field)
UIAlertViewStyleSecureTextInput (1 password field)
UIAlertViewStyleLoginAndPasswordInput (both a text field and password field)
Then use textFieldAtIndex: to get the text field you want. This way, you can even use the alertViewShouldEnableFirstOtherButton: delegate method to enable the button.
Yes, it's definitely possible, and it isn't a hack. You would need to subclass UIAlertView and place controls into it. Since it's a subclass, it will retain the same look & feel, etc.
For full details, see this tutorial by Jeff LaMarche (co-author of Beginning iPhone Development, from Apress).
Yes, but not without some hacking, see this previous question.
You'd have to directly manipulate the UIAlertView's subviews and add a UITextField and then resize the UIAlertView's frame. You're better off creating your own view.