Initial text and paperclipped-URL for action in UIActivityViewController & UIActivityItemSource? - iphone

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.

Related

iOS 7 UIActivityViewController Email Attachments

I have reviewed a bunch of posts here, numerous online tutorials/sample code and I'm stumped. In my app I have no problem displaying the UIActivityController natively provided by iOS7 with the sharing options appropriate to my app (AirDrop and mail).
The specific problem I'm having is getting my saved document attached to the email message when the user selects the option to share via mail. The message body is being set to the text, but the attachment is MIA. The relevant code is:
// Generate the XML file to be shared for the currently displayed record...
NSURL *url = [self createShareFile];
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:#[#"Data shared from my app.", url] applicationActivities:nil];
// Filter out the sharing methods we're not interested in....
controller.excludedActivityTypes = #[UIActivityTypePostToTwitter, UIActivityTypePostToFacebook,
UIActivityTypePostToWeibo,
UIActivityTypeMessage,
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo];
// Now display the sharing view controller.
[self presentViewController:controller animated:YES completion:nil];
What am I missing? My file is being properly created, the contents is correct and the NSURL object contains the proper path to the file.
Thanks!
Problem solved.....
The code posted in my original post is 100% accurate. The issue ended up being in the way I was constructing the NSURL being returned in my createShareFile method:
Incorrect (original way):
return [NSURL URLWithString:[docFile stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
Correct way:
return [NSURL fileURLWithPath:docFile];
As soon as I fixed that, it started working, even with my custom file type.
I had a similar problem where the mail app was the only one I couldn't add a pdf to. Here is my code in Swift as well as handling iPad popup.
var filesToShare = [Any]()
filesToShare.append(self.myUrl)
let activityViewController = UIActivityViewController(activityItems: filesToShare as [Any], applicationActivities: nil)
present(activityViewController, animated: true)
// for iPad -> where to present on screen
if let popOver = activityViewController.popoverPresentationController {
//action button being my top left icon
popOver.barButtonItem = self.actionButton
}
My issue was as well handling the URL differently

How to call a web service on page load

I am trying to call a web service on page load. Currently I call it on a button click and it works fine. But when I try to do the same on viewDidAppear, it doesn't happen. What i want to achieve is if username and password are saved then it should automatically load the next page. It is filling in the text boxes but not loading the next page.
Here is my code for submit button and ViewDidAppear:
-(IBAction)submitButton{
[apd showCoverView:YES WithActivityIndicator:YES];
PlaceWebService *handler = [[PlaceWebService alloc]init];
[handler setRequestType:Loginparser];
NSString *url = [NSString stringWithFormat:#"http://www.mywebsite.com/api.php?command=auth&cardno=%#&password=%#",username.text,password.text];
[handler sendingLoginRequest:url Respond:self At:#selector(showParsed:)];
}
and for viewDidAppear
-(void)viewDidAppear:(BOOL)animated
{
NSLog(#"Appeared");
[self loginArea];
apd=[[UIApplication sharedApplication]delegate];
NSString *filepath=[self pathOfFile];
if([[NSFileManager defaultManager]fileExistsAtPath:filepath])
{
NSArray *array=[[NSArray alloc]initWithContentsOfFile:filepath];
username.text=[array objectAtIndex:0];
password.text=[array objectAtIndex:1];
[self submitButton];
}
}
What should I do? Please help...
If you want to call the method after loading view and without any event, then you need to that as normal instance method instead of IBAction method.
-(Void)submitButton{
// implementation
}
and then call this method from viewDidAppear.
A couple things could be the problem here.
1)
IBActions usually take a parameter. Declare it as:
- (IBAction) submitButton: (id) sender;
And then call it from your viewDidAppear method as:
[self submitButton: self];
2)
Also make sure UI stuff is happening on the main thread (you didn't specify if the app is multi threaded or not), so maybe:
[self performSelectorOnMainThread: #selector(submitButton:) withObject: self];
And
3)
Set breakpoints to see if your submitButton method (and the lines before it) are actually even called when viewFromAppear: is called.
And Rishi's suggestion is good, too!

Core Data Persistent Store Coordinator NSURL error

I've been working on an app that takes user ratings about mood. I am using Core Data to store this data. Initially, I am trying to store ratings and strings of "accomplishments". I've set up an entity in Core Data called "Day" with attributes date (of type Date), dailyRating (of type Int16), dailyAccomp (of type String), and dailyAccompRating (of type Int16). My app crashes within my app delegate's Core Data persistentStoreCoordinator method at the following stmnt:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"SelfEsteemBldr.sqlite"];
The error that I'm given is
[NSPathStore2 URLByAppendingPathComponent:]: unrecognized selector sent to instance 0x4d6f440.
Maybe a little background about how the error comes about might be helpful.
My Main window has a tab bar controller as the rootViewController. Within the tab for the CD model (LogViewController), I've set up a tableView Controller within a navigation controller. The nav bar has an add button, that pushes a new view that basically has textfields so the user can enter the relevant data. Within that view, there is a nav bar with a Done button. When the user is done, the Done button changes to a Save button. When I tap the Save button, the app crashes. The Save button is a UIButtonItem within ViewDidLoad. Here's the code for the save button:
UIBarButtonItem *newSaveButton =
[[UIBarButtonItem alloc]
initWithTitle:NSLocalizedString(#"Save", nil)
style:UIBarButtonItemStylePlain
target:self
action:#selector(performAddNewDay:)];
self.saveButton = newSaveButton;
[newSaveButton release];
The performAddNewDay method within the UIButtonItem looks like this:
- (void) performAddNewDay:(id)paramSender{
SelfEsteemBldrAppDelegate *delegate = (SelfEsteemBldrAppDelegate *)
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = delegate.managedObjectContext;
NSLog(#"Past init point in PerformAddNewDay");
// Get the values from the text fields
NSInteger dailyRatingAsInteger = [self.textFieldDailyRating.text integerValue];
NSNumber *ddailyRating = [NSNumber numberWithInteger:dailyRatingAsInteger];
NSLog(#"Daily Rating Entered is %#", ddailyRating);
NSString *ddailyAccomplishment = self.textFieldAccomplishment.text;
NSLog(#"Daily Accomplishment Entered is %#", ddailyAccomplishment);
NSInteger dailyAccompRatingAsInteger = [self.textFieldAccomplishmentRating.text integerValue];
NSNumber *ddailyAccompRating = [NSNumber numberWithInteger:dailyAccompRatingAsInteger];
NSLog(#"Daily Accomp Rating Entered is %#", ddailyAccompRating);
// Create a new instance of Day
Day *newDay = [NSEntityDescription
insertNewObjectForEntityForName:#"Day"
inManagedObjectContext:context];
if (newDay != nil){
// Set the properties according to the values we retrieved from the text fields
newDay.dailyAccomp = ddailyAccomplishment;
newDay.dailyRating = ddailyRating;
newDay.dailyAccompRating = ddailyAccompRating;
NSError *savingError = nil;
// Save the new day
if ([context save:&savingError] == YES){
// If successful, simply go back to the previous screen
[self.navigationController popViewControllerAnimated:YES];
} else {
// If we failed to save, display a message
[self
displayAlertWithTitle:NSLocalizedString(#"Saving", nil)
message:NSLocalizedString(#"Failed to save the context", nil)];
}
} else {
// We could not insert a new Day managed object
[self
displayAlertWithTitle:NSLocalizedString(#"New Day", nil)
message:NSLocalizedString(#"Failed To Insert A New Day", nil)];
}
}
I've commented out most of the code to try to find the offending statement, and it seems to be
**NSManagedObjectContext *context = delegate.managedObjectContext;**
That is, if I comment everything below and including this stmnt, app doesn't crash. It doesn't do anything, it just "waits" (as expected). If I uncomment this stmnt, app crashes. SelfEsteemBldrAppDelegate is also imported using the #import "SelfEsteemBldrAppDelegate.h' stmnt.
Again, the error that I'm getting is in the Core Data Stack persistentStoreCoordinator method within SelfEsteemBldrAppDelegate.m. The crash occurs at the following:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"SelfEsteemBldr.sqlite"];
The error that I'm given is
[NSPathStore2 URLByAppendingPathComponent:]: unrecognized selector sent to instance 0x4d6f440
So, after all that, any ideas as to why I might be getting this message, and what I can do to resolve it? From what I understand, I'm not supposed to interact with the Core Data Stack methods, so I don't want to fool around with that code. Any help would be greatly appreciated. Also, if I've left out any info you may need, please let me know. Thanks.
Normally, I faced this problem and encountered that this error comes when managedObjectContext is nil... To solve this i have used below code and worked fine for me..
if (managedObjectContext == nil) {
managedObjectContext = [(iBountyHunterAppDelegate *) [[UIApplication sharedApplication] delegate] managedObjectContext];
}

TTStyledTextLabel

I'm trying to get this control to work with a hypertext link with not much success. I have looked at TTCalaog and tried to replecate but does not work.
I have this working as far as displaying the hypertext link but it does not fire.
TTStyledTextLabel* label = [[[TTStyledTextLabel alloc] initWithFrame:CGRectMake(5, 0, 315, 175)] autorelease];
NSString* labelText = #"This should work";
label.text = [TTStyledText textFromXHTML:labelText lineBreaks:NO URLs:YES];
[self.view addSubview:label];
I thing I am missing the point here perhaps with the placement of the google url? I have seen a post on this forum that makes use of custom-uri://some/url that is then set up in TTURLMap and TTNavigator, but I need to open a url from the hypertext in a webview so I need the url to run a method in my class that creates my webview controller etc.
I have tried to cusomise TTURLMap to work without a TTNavigator but completely pickled?
Any help gratefullt appreciated ;-)
Thanks
I've just found myself a solution to catch the clicked URL on a TTStyledTextLabel. I hope this could help in your case too.
This's what I have done.
1. Create TTNavigator
TTNavigator *navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeNone;
navigator.delegate = self;
2. Create TTNavigatorDelegate
As you assigned self as delegate of the navigator object. Therefore, please remember to add protocol in the header file .h before you continue.
In the implementation, create this method
- (BOOL) navigator:(TTBaseNavigator *)navigator shouldOpenURL:(NSURL *)URL {
// Now you can catch the clicked URL, and can do whatever with it
// For Example: In my case, I take the query of the URL
// If no query is available, let the app open the URL in Safari
// If there's query, get its value and process within the app
NSString *query = URL.query;
if (query == nil) {
return YES;
} else {
// process the query
}
}
I hope this helps! Please vote for me if this helps to solve your issue!
Best Regards,
Thang

understanding TTNavigator

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&param2=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:)