I was following the tutorial here.
The code I have is:
- (void) didSelectObject:(id) object atIndexPath:(NSIndexPath*) indexPath
{
Group * group = (Group *)((RKMappableObjectTableItem *) object).object;
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
group.unread = 0;
[self.tableView reloadData];
TTURLAction *action = [[[TTURLAction actionWithURLPath:#"tt://group"]
applyQuery:[NSDictionary dictionaryWithObject:group forKey:#"kParameterUser"]]
applyAnimated:YES];
[[TTNavigator navigator] openURLAction:action];
}
I have set the mapping as:
[map from:#"tt://group" toSharedViewController:[TopicsViewController class]];
and inside my TopicsViewController I have both tried:
- (id) initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
but it didn't work. It's as if it can't find any mapping. Why is this? What am I doing wrong?
UPDATE:
Here's the updated code based on the suggestion:
TTURLAction *action = [[[TTURLAction actionWithURLPath:#"tt://group"]
applyQuery:[NSDictionary dictionaryWithObject:group forKey:#"kParameterUser"]]
applyAnimated:YES];
[[TTNavigator navigator] openURLAction:action];
[map from:#"tt://group?" toSharedViewController:[TopicsViewController class] selector:#selector(initWithNavigationURL:)];
- (id) initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query
what am I doing wrong here?
You are not telling it what selector to cal! First, add a ? to the end of your mapping: #"tt://group?"
When you add any query dictionaries, they are sent like normal params in a url (?foo=bar&apple=orange).
Next, if you aren't going to use the selector as part of the URL mapping, use the from:toSharedViewController:selector: method to set the selector to the selector you wish to call.
I don't know three20 very well, I think however you first need to create an URL to the object you'd like to pass, which can be mapped.
It appears like three20 provides a category on nsobject which allows you to call:
NSString* url = [myFooObject URLValueWithName:#"barName"];
This method should be inherited from NSObject by almost any Framework Class.
See NSObjects to URLs in the chapter URL mapping methods from the tutorial you posted.
Related
Finally been making it through Apple's (rather dismal) documentation on the new UIActivityViewController class and the UIActivityItemSource protocol, and I'm trying to send different data sets to different actions called from the activity view. To simplify things, I'm looking at two things.
A Facebook posting action, which should say "Check this out!" and also attach a URL to the post (with that cute little paperclip).
A Twitter posting action, which should say "Check this out, with #hashtag!" and also attach that same URL (with the same paperclip).
Here's the code I've got implemented right now.
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
return #"Check this out!";
} else if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
return #"Check this out, with #hashtag!";
}
return #"";
}
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController {
return #"";
}
And then when I set up this activity view controller (it's in the same class), this is what I do.
UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:#[self] applicationActivities:nil];
[self presentViewController:activityView animated:YES completion:nil];
My dilemma is how to attach that NSURL object. It's relatively easy when calling the iOS 6 SL-class posting modals; you just call the individual methods to attach a URL or an image. How would I go about doing this here?
I'll note that instead of returning NSString objects from -activityViewController:itemForActivityType, if I return just NSURL objects, they show up with that paperclip, with no body text in the post. If I return an array of those two items, nothing shows up at all.
Evidently it was as simple as this: passing in an array to the first argument of UIActivityViewController's init call, with each item in the array handling a different data type that will end up in the compose screen. self handles the text, and the second object (the NSURL) attaches the URL.
NSArray *items = #[self, [NSURL URLWithString:#"http://this-is-a-url.com"]];
UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
[self presentViewController:activityView animated:YES completion:nil];
Really wish there was more on this, but here it is.
When the user posts to FB or Twitter I want to know that the share completed, or the view was dismissed with an x.
Does anyone know if there is a delegate method built into ShareKit or if I have to write my own methods into it?
Right now I'm using the sharers directly, but I may switch to use the sharekit popup. I'm just using the two line code:
SHKItem *item = [SHKItem text:someText];
[SHKFacebook shareItem:item];
I faced your problem and came out with a solution, perhaps not the prettiest one, but it does solve the problem. There is a delagate called SHKSharerDelegate, which can be used with sharers for this purpouse, so if you are calling sharers directly from your code (no action sheet), then you should do something like this:
NSString* mySharerClassName = #"SHKFacebook";
SHKSharer* classItem = (SHKSharer*)[[NSClassFromString(mySharerClassName) alloc] init];
Class sharerClass = [classItem class];
if ( [sharerClass canShare] ){
[classItem performSelector: #selector(setItem:) withObject: item];
//Assuming that the class where this code is conforms to the SHKSharerDelegate protocol
[classItem performSelector: #selector(setShareDelegate:) withObject: self];
[classItem performSelector: #selector(send)];
}
If you have to use the ActionSheet, it gets a little trickier, mostly because there is no support for it, just go to the ActionSheet header file (ShareKit/UI/SHKActionSheet.h) and add a delegate property:
#property (nonatomic, retain) id sharerDelegate;
Notice that is not id<SHKSharerDelegate>, try doing that and you'll experience a whole lot of pain. That's why I said that is not the prettiest one. Once you added and synthetized the property, look for this method:
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
And where it says
id sharer = [sharers objectAtIndex:buttonIndex];
[NSClassFromString(sharer) performSelector:#selector(shareItem:) withObject:item];
Change it for
id sharer = [sharers objectAtIndex:buttonIndex];
if ( sharerDelegate == nil ){
[NSClassFromString(sharer) performSelector:#selector(shareItem:) withObject:item];
}else{
SHKSharer* classItem = [[NSClassFromString(sharer) alloc] init];
[classItem performSelector: #selector(setItem:) withObject: item];
[classItem performSelector: #selector(setShareDelegate:) withObject: sharerDelegate];
[classItem performSelector: #selector(send)];
}
If you are more interested in this, I'll try to make a blog post soon and edit the answer to reference it.
Hope I can still help somebody!
Im currrently going through a geolocation tutorial which adopts the MKAnnotation Protocol into a class.
The tutorial suggests to create the following methods in the Theannotation.h class
+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coord;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord;
and in the implementation
+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coord {
return [[[[self class] alloc] initWithCoordinate:coord] autorelease];
}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord {
if ( self = [super init] ) {
self.coordinate = coord;
}
return self;
}
The second method is then called in a viewcontroller
Theannotation *annotation = [[SimpleAnnotation alloc] initWithCoordinate:Coords];
I understand the second method completely however Im puzzled to the inclusion of the first. The class method isn't called at any other place in the example tutorial and im struggling to understand why you would use a class method in this case.
You can omit this class method but in some cases it is useful because it provides you a mechanism to create 'temporary' annotation that will be autoreleased. Of course you can do it manually, but class method is a way of convenience in that case.
please go through this blog here
or you can download the code-
link
and see the code, you will know that which things are mandatory and which will not.
I've subclassed MKAnnotation so that i can assign objects to each annotation, this is so that when the rightCalloutAccessoryView is clicked i can push a navigation controller with the object passed to it and display the objects data in another view.
This all works great apart from one thing, i've extended upon initWithCoordinate like so:
-(id)initWithCoordinate:(CLLocationCoordinate2D)coord andObject:(NSManagedObject *)object {
[self setPlace:object];
coordinate = coord;
title = [place valueForKey:#"name"];
subtitle = [place valueForKey:#"address"];
return self;
}
Although everything is working great i'm recieving the warning:
NO '-initWithCoordinate:andObject:' method found
Which means i'm doing something wrong somewhere, what is the correct way to go about adding upon initWithCoorinate?
Put the prototype -(id)initWithCoordinate:(CLLocationCoordinate2D)coord andObject:(NSManagedObject *)object in .h file.
following situation:
in a TTTableViewController i added some Cells with URLs.
they are opening a class with #"tt://photos" for example. this works quite fine.
the first thing is, i saw some urls in TT Examples like #"tt/photos/1". is it possible to fetch this "1" in my photos class and say, for example okay, please open picture one, ore is this only another URL that was declared in TTNavigatior to open a specific Class?
the other thing is: is it possible to forward an object to the linked class?
clicking a cell opens #"tt://photos" (the linked class in my TTNavigator)
working with normal tableviews i can overwrite my init method and send an object with my initialize method, is this also possible by clicking my TTItems?
thanks!
figured it out myself, for those who need it:
First (passing "subURLs" in your navigator map)
navigating to an URL with #"tt://photos/firstphoto" is possible, you can fetch the "firstphoto" like this:
//Prepare your Navigator Map like this
[map from:#"tt://photos/(initWithNumber:)" toViewController:[PhotoVC class]];
In your PhotoVC you can access this Number:
-(void) initWithNumber: (NSString*)number {
NSLog(#"%#",number);
}
calling your View Controller with this url would look:
PhotoVC* controller = [[PhotoVC alloc] initWithNumber:#"1"];
[navigationController pushViewController:controller animated:YES];
[controller release];
Second (passing objects in an TTTableViewController)
its a bit tricky, but you dont have to Subclass anything.
first, nil the URL in the TableItem
[TTTableLink itemWithText:#"TTTableLink" URL:nil]
in your TTTableViewController write down this method
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath*)indexPath {
TTURLAction *urlAction = [[[TTURLAction alloc] initWithURLPath:#"tt://photos"] autorelease];
urlAction.query = [NSDictionary dictionaryWithObject:#"firstphoto" forKey:#"photo"];
urlAction.animated = YES;
[[TTNavigator navigator] openURLAction:urlAction];
}
now in your your PhotoVC you need something like this
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
if (self = [super init]) {
NSLog(#"%#",query);
}
return self;
}
and you are done ;)
I was trying to implement choise's answer, learned a lot, and eventually had to get the callouts showing up and keep the implementation with many urls simple, so here's what i did.
Keep URL in the TableItem,
Use this code in the TTTableViewController subclass.
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath*)indexPath {
NSLog(#"Its url is %#", [object URL]);
TTURLAction *urlAction = [[[TTURLAction alloc] initWithURLPath:(NSString *)[object URL]] autorelease];
urlAction.query = [NSDictionary dictionaryWithObject:self.user forKey:#"user"];
urlAction.animated = YES;
[[TTNavigator navigator] openURLAction:urlAction];
}
- (BOOL)shouldOpenURL:(NSString*)URL {
return NO;
}
That "shouldOpenURL:" was discovered looking through TTTableViewController, I tried it out, and it worked. Now the table view is not opening a duplicate view, and there are callouts!
Thanks choise!
Although choice's answer works for multiple params when u are creating the TTURLAction in code it is not very useful when u want to embed links to view controllers in your TTStyledLabel.One solution to that is to use multiple params in a single string.
<a href='app://view2/param1=value1¶m2=value2&...'>LabelName</a>
if you want the code to parse such urls and get the params please feel free to send me a message and I will send you my parser classes.
(or you can build your own with NSScanner!)
Also dont forget to escape the &s otherwise TTStyledLabel would not like it!
You don't need to run this on current version 1.0.6.2 for TTTableViewController. The "URL" option is working as expected. If it's not working for you, then your URL is broken or your are calling the wrong function on your ViewController. The function you have to call through URL must return an id (be a constructor for a ViewController) of a ViewController. Then it'll work as expected.
I'll changed the example form choise to be like TTNavigator expect it to be.
Add a mapping, which TTNavigator will use to navigate:
//Prepare your Navigator Map like this
[map from:#"tt://photos/(initWithNumber:)" toViewController:[PhotoVC class]];
Create a TTTableLink (or TTStyledText, or other) with an URL set, which should mach your map:
[TTTableLink itemWithText:#"TTTableLink" URL:#"tt://photos/1"]
Add this to your PhotoVC to be called by TTNavigator on the given URL
-(id) initWithNumber: (NSString*)number {
if (self = [super init]) {
self.title = #"Some Title";
NSLog(#"%#",number);
}
return self;
}
You don't need to overwrite the function didSelectObject, as the TTNavigator will call your ViewController through defined constructor function tt://photos/(initWithNumber:)