(I posted the question below on the Three20 forum, but no response so far! Maybe you guys can help out.)
I use the TTTableViewController in my iOS app and there is one thing I wish to achieve.
Each of the TTTableItem classes has a method to assign a delegate & selector when initializing it.
Eg: TTTableTextItem has (+itemWithText:delegate:selector:) Now, the selector method would hav a signature like this: -(void)selectorMethodForTableItem:(id)sender; I would like to identify uniquely the tableItem that was selected, but within the selector method I only have the TTTableTextItem object, which only has the 'text' parameter. (The 'text' parameter is a string and it could be the same for 2 tableItems)
I can easily solve this if I provide a TTUrl for each tableItem, but I do not want to navigate to a new screen when a tableItem is pressed. Just say, I want to display an alert based on which tableItem a user selects.
How do I solve this problem? Do I have to define a custom TTTableItem class?
you can set a TTURL for each of your TTTableTextItem and "catch" the touches in the TTTableViewController, before TTNavigtor takes over, so your app won't navigate to a different page.
in your TTTableViewController, add this function:
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath *)indexPath {
TTTableItem* item = object;
NSLog(#"%#", item.URL);
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Note this function doesn't call the parent didSelectObject, meaning it won't pass the object to the TTNavigator.
Related
I am designing apple watch application where i need to show top10 feed title and i have successfully shown it. in next step i have to add action event to tap which will redirect user to next screen but i am confused which controller to use here. i have to show all feeds in pagination format and then on click i have to show its detail view.
does anyone tried with this approach? i am using UIButton over there but its having text limitation so cant use it and for tableview it scroll verticaly where as i need horizantle scroll.
alph0x's answer is pretty useful. But you can also do another thing to perform what you are asking in case you only want that the action will do when push in a specific button of the row.
This second solution consists on create a class for the custom row with an IBAction
#import <WatchKit/WatchKit.h>
#interface MyRow : NSObject
// Methods
- (IBAction)buttonClick;
#end
And in the buttonClick method, you can specify the action as in the follow example using pushControllerWithName:context to go to a specific interface controller
#import "MyRow.h"
#implementation MyRow
- (IBAction)buttonClick {
[self goToInterface:#"feedInterface"];
}
- (void)goToInterface:(NSString *)interfaceName{
NSDictionary *contextToSend = [NSDictionary dictionaryWithObjectsAndKeys:#"FeedTitle", #"title",
#"lalala", #"secondValue",
#"lelele", #"thirdValue",
#"other value", #"other", nil];
[self pushControllerWithName:interfaceName context:contextToSend];
}
#end
You can send your row info through context. In that example I have decided to send a dictionary with some values.
In the interfaceName param you have to specify the Interface Controller Identifier that you can set in your storyboard. See the image below:
And tell to the XCode that your table row has the custom class MyRow
Note: don't forget to assign your button to the IBAction method ;)
If I understand, you need to have a table with 10 rows, and you need to be able to tap in one row, and view the details about the one you selected, if thats correct, you only need to use the Method from WKInterfaceTable "- (id)rowControllerAtIndex:(NSInteger)index", with this one (works like UITableView one with the delegate) you can handle every row action after being tapped.
I have a method in AppDelegate which get some data from server, this method get called every time when application become active. I want to reload some table in another view when server data received successfully. How can i do this without using NSNotification?. I know passing notification can do this job. I want to know is there any other way to perform this?
well comments by users already explained what to do.
But i had another approach.I don't prefer, but it will work.
Always set some constant tag value to your table view (say 1001).And make sure than you never use the same tag on others.
Then in that method of appDelegate, you can do->
UITableView *tableView =(UITableView*)[self.window viewWithTag:1001];
[tableView reloadData];
I am reminding you again, don't use this. use NSNotification class.
Although it creates an unneeded dependency between the view and the app delegate, I'd implement this way:
create a ViewReloader protocol with a method - (void) reloadTable;
implement that protocol in the view
add a property of type id<ViewReloader> to the app delegate
when the view is instantiated, assign it to the property defined above
when you need to reload, call the reloadTable method of the id<ViewReloader> property from the app delegate (but always check for property != nil)
if the view is destroyed/deallocated, remember to reset the app delegate property
Well samething you can do with using custom delegates as well. If you want to pass message from one object to another. You can use notification also, but use only when you want to broadcast the message.
What's the difference between declaring a UIButton in Xcode like this:
- (IBAction)testButton;
and declaring a button like this:
- (IBAction)testButton:(id)sender;
I understand that in the .m file you would then implement the buttons accordingly, as shown below:
- (IBAction)testButton
{
// insert code here..
}
and setting it up like this:
- (IBAction)testButton:(id)sender
{
// insert code here..
}
Is there any additional things you can do by declaring the button with :(id)sender, is there some additional stability, or is there no difference?
With :(id)sender you are able to access the button itself through the sender variable. This is handy in many situations. For example, you can have many buttons and give each a tag. Then use the [sender tag] method to find which button was tapped if many buttons are using this IBAction.
- (IBAction)someMethod:(id)sender {
// do stuff
}
Using (id)sender, you have a reference to who sent the method call. Please note, this doesn't have to be limited to a UIButton.
If you're created this method via control-dragging from the storyboard an only hooking up a single button, then sender is basically useless (it will always be the same), and should probably be marked as unused:
#pragma unused (sender)
(The compiler can better optimize your code if you do this.)
However, there's nothing wrong with hooking up several UI elements to the same IBAction method. You can then distinguish the sender via:
[sender tag]
...which returns an int that was either set via the storyboard or programmatically.
Moreover, you can call this method elsewhere in your class. You can either pass nil as the sender, or you can pass it a particular UI element in order to force it into the results you've coded for objects of that tag.
Nonetheless, if you plan to call the method with a nil argument, you can always throw:
if(!sender)
... into the method in order to handle special logic for when the method has been invoked programmatically as opposed to via user interaction.
It allows you to know which button you are working with. I have posted a simple example for a card game below
- (IBAction)flipCard:(id)sender {
[self.game flipCardAtIndex:[self.cardButtons indexOfObject:sender]];
self.flipCount++;
[self updateUI];
}
This method is used for a card flipping game. There are multiple buttons on the screen representing different cards. When you hit the button, a card in the model must be flipped. We know which one by finding the index of the variable sender
When creating a UIActionSheet to prompt a user to delete an item from a list, I currently have to maintain the deleted item (or at least its index in the list) as an instance variable in my view controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath row] == 4) {
// Delete button pressed
_deletingItemIndex = [indexPath section];
UIActionSheet actionSheet = ...
}
}
Then when the UIActionSheet closes, if the user decided to delete the item, I have to reference that _deletingItemIndex variable, then set it to -1 or some other nil value.
What I would like to do, is maintain either the deleting item, or its index, in the actual UIActionSheet without needing to subclass UIActionSheet.
I find it strange that the delegate method for UIActionSheet provides the sheet to the delegate, but you can't store any contextual information (not even a dictionary) in the sheet itself.
There are quite a few categories out there for adding block-based dismiss handlers to UIActionSheet and UIAlertView now. I personally use Mugunth Kumar's UIKitCategoryAdditions.
This would let you do the following...
[UIActionSheet actionSheetWithTitle:#"Hooray" message:#"Blocks Are Awesome!" buttons:#[...] showInView:self onDismiss:^(int buttonIndex) {
//Now you have access to all your local variables here!
} onCancel:^{
//And here!
}];
You should use objc_setAssociatedObject()
Have a look at http://darkdust.net/writings/objective-c/attaching-objects for some code.
UIActionSheet is a system object which should only be concerned with presenting a user with choices and getting a button index out.
Using an instance variable of view controller also doesn't make sense, because this isn't really a state of view controller, but rather of a current action which started existing the moment user started deleting.
The correct pattern, thus, is to create a new object, save information there, and use as a delegate:
MyDeletionAction *action = [MyDeletionAction actionWithIndex:[indexPath section]];
UIActionSheet actionSheet = ...
actionSheet.delegate = action;
...
and somewhere else, define MyDeletionAction as a class implementing the delegate protocol.
An added bonus of this approach is that you can take the code out of your view controller into separate classes, which is a good thing. Moreover, it's likely that your MyDeletionAction, MyInsertionAction etc. will share some common code.
Perhaps even the presence of action sheet should be an implementation detail of your action. For example, what if you provide an option to delete without confirmation?
Note also that in this approach someone should retain an action object, for example by object retaining itself until the action is fully completed, or by using a VC instance variable for this purpose:
self.lastAction = [MyDeletionAction actionWithIndex:[indexPath section]];
[self.lastAction start];
This also allows you to remember the state of last action for possible postprocessing.
start here appears because my actions usually have this kind of inheritance: MyDeletionAction <- MyAction <- NSOperation. Your mileage may vary.
I need to pass a parameter to IBAction (but it has only sender(id) - UIButton in my case), so I'm wondering if it possible to convert description of some object to an object. Right now I'm passing parameter as button's [titleLabel text]:
[[button titleLabel]setText:[someObject description]];
And in IBAction I'm getting description:
- (IBAction)AddToCalendarEvent:(id)sender {
NSString * description = [[sender titleLabel]text];
NSLog(#"description is %#", desc);
}
And now I want to convert this description to an object. Is it possible?
UPD
I'm dynamically filling table view with cells. Each cell has four buttons and I want these buttons to keep some object as parameter to pass to IBAction.
I think the best solution for you, based on what I've read and currently understand about your problem, is to maintain an array (or some other appropriate data structure) of your buttons on your View Controller. Then, in your action method that each button calls when it is tapped, you can search your array of buttons for the sender of your action method. Then, once you've figured out which button has been tapped, you can use that to then find whatever data you're looking for in your data model. You should apply this solution to your situation and it will probably end up looking a bit different, but the basic idea is sound. You should avoid maintaining state in your view (in this case your buttons) and it looks like you're approaching that from your description of the problem.
You definitely don't won't to convert in this way.
A simple option is to set the tag of each UIButton to a unique integer, and store an array of the objects you need to look up:
- (IBAction)AddToCalendarEvent:(id)sender {
NSInteger senderTag = [sender tag];
NSLog(#"Sender index = %d", senderTag);
// Use this tag as an index to the array.
}
A more complicated route is to subclass UIButton (usually not recommended), to store the associated data with each UIButton. Then you can look it up, once again from the sender.