I have a tableView where the user can add contacts to. These contacts get saved to a mysql database and then returned to the user. Thing is, he has to update it manually in order to get the updated xml. But I wanna do it when he adds a contact so it gets shown right away. I tried various things and always ended up with either an error or he parsed the database more than once in the tableview. I thought of deleting all contacts and pasting all of them again and then update it, but this also didn't really work.
Here is how I do it at the moment:
To parse the XML:
- (void) doXMLParsing
{
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"Key22"] == nil) {
} else {
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.tabelle count]];
self.tableView.scrollEnabled = YES;
tabelle = [[NSMutableArray alloc] init];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *fileName = [prefs stringForKey:#"Key22"];
NSString *urlString = [NSString stringWithFormat: #"http://www.---.com/%#.xml", fileName];
NSURL *url = [NSURL URLWithString: urlString];
DataFileToObjectParser *myParser = [[DataFileToObjectParser alloc] parseXMLAtUrl:url toObject:#"Telefonbuch" parseError:nil];
for(int i = 0; i < [[myParser items] count]; i++) {
Telefonbuch *new = [[Telefonbuch alloc] init];
new = (Telefonbuch *) [[myParser items] objectAtIndex:i];
[tabelle addObject:new];
[self.tableView reloadData];
}
[XMLActivity stopAnimating];
}
}
In the viewDidLoad:
XMLActivity = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(140.0f, 290.0f, 40.0f, 40.0f)];
[XMLActivity setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:XMLActivity];
[XMLActivity startAnimating];
[self performSelector:#selector(doXMLParsing)
withObject:nil
afterDelay:0];
return;
tabelle = [[NSMutableArray alloc] init];
Everything works fine right now. I just want to reparse the XML after a new contact is added so it will get displayed right away.
Have you tried calling [reloadData][1] on your UITableView?
If this does not answer, could you explain what happens exactly when you parse xml a second time?
The solution was as obvious as simple, and I still wasted way too many time on this.
Here is the solution:
Just put
[self doXMLParsing];
at the end when you added a contact to the database.
Related
I am writing a app that needs to save and restore nsmutablearrays to populate a table view. The array will save but won't overwrite once i reset everything. i find that the values are combining together and is giving me unreliable averages... code is below. also i have various view controllers that have this lap function...
// code that adds items to table view and saves a version of the array to nsmutablearray
NSUserDefaults *prefs = [[NSUserDefaults alloc]
initWithSuiteName:#"group.com.DJ.TSTML"];
[tableItems3 insertObject:TimeString2 atIndex:0];
// time string is the time as a nsstring
[tableItems4 addObject:[NSNumber numberWithFloat:seconds2]];
[tableview reloadData];
[prefs setObject:self.tableItems4 forKey:#"SavedArray3"];
[prefs setObject:self.tableItems3 forKey:#"SavedArray4"];
// this is saving to insurer defaults
NSString *newString = [NSString stringWithFormat:#"%lu", (unsigned long)tableItems3.count];
[Commentcount setText:newString];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSNumber *average = [tableItems4 valueForKeyPath:#"#avg.self"];
Average.text = [formatter stringFromNumber:average];
NSLog(#"Sucess");
[prefs synchronize];
} }
Restoring the array :
NSUserDefaults *prefs = [[NSUserDefaults alloc]
initWithSuiteName:#"group.com.DJ.TSTML"];
// code used to erase current values in the table view and restore from NSUserDefaults
tableItems3 = [[NSMutableArray alloc] init];
tableItems4 = [[NSMutableArray alloc] init];
[tableview reloadData];
NSMutableArray *RestoreArray1 = [[prefs objectForKey:#"SavedArray4"]mutableCopy];
NSMutableArray *RestoreArray2 = [[prefs objectForKey:#"SavedArray3"]mutableCopy];
[tableItems3 addObjectsFromArray:RestoreArray1];
[tableItems4 addObjectsFromArray:RestoreArray2];
if (tableItems3 == nil) {
tableItems3 = [[NSMutableArray alloc] init];
tableItems4 = [[NSMutableArray alloc] init];
}
[tableview reloadData];
NSLog(#"%#",tableItems4);
}
}
Thank you in advance for any help!
My issue to be clear is that every time i save to nsuserdefaults instead of overwriting the previous array it just keeps the old array and combines with the new one
Ok so i answered my own question. As someone brought up it was combining because i was retrieving without overwriting it first. the following code is what worked...
NSString *Clearstring = [prefs objectForKey:#"Clear?"];
// i created a nsstring that when the method for restarting would change accordingly.
// so when someone would navigate to this view controller this would fire.
// if clear is yes i would prevent the code that controled the restore function from restoring and prepare
// it if it was needed to be restored again.
if ([Clearstring isEqualToString:#"Yes"]) {
tableItems3 = [[NSMutableArray alloc] init];
tableItems4 = [[NSMutableArray alloc] init];
[prefs setObject:self.tableItems4 forKey:#"SavedArray3"];
[prefs setObject:self.tableItems3 forKey:#"SavedArray4"];
[prefs setObject:#"NO" forKey:#"Clear?"];
[tableview reloadData];
}
else{
tableItems3 = [[NSMutableArray alloc] init];
tableItems4 = [[NSMutableArray alloc] init];
[tableview reloadData];
NSMutableArray *RestoreArray1 = [[prefs objectForKey:#"SavedArray4"]mutableCopy];
NSMutableArray *RestoreArray2 = [[prefs objectForKey:#"SavedArray3"]mutableCopy];
[tableItems3 removeAllObjects];
[tableItems4 removeAllObjects];
[tableItems3 addObjectsFromArray:RestoreArray1];
[tableItems4 addObjectsFromArray:RestoreArray2];
if (tableItems3 == nil) {
tableItems3 = [[NSMutableArray alloc] init];
tableItems4 = [[NSMutableArray alloc] init];
}
[tableview reloadData];
NSLog(#"%#",tableItems4);
}
}
Ok, I'm a bit out of my league but here goes... I'm working on making some updates to an iPhone app for a client (it hasn't been updated since 2013...just to put into context how old the programming is). While making simple updates to the app, I noticed the twitter feed section kept crashing. I checked the debug and came up with this error.
[_NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array
I know the array is empty... I'm just not sure why. Here's the code where I think it is filling the array
- (void)loadData {
NSURL *tutorialsUrl = [NSURL URLWithString:#"https://twitter.com/EdwinOrange/lists/kentucky-general-assembly"];
NSData *tutorialsHtmlData = [NSData dataWithContentsOfURL:tutorialsUrl];
TFHpple *tutorialsParser = [TFHpple hppleWithHTMLData:tutorialsHtmlData];
NSString *tutorialsXpathQueryString = #"//p[#class='TweetTextSize js-tweet-text tweet-text']";
NSArray *tutorialsNodes = [tutorialsParser searchWithXPathQuery:tutorialsXpathQueryString];
NSMutableArray *newTutorials = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in tutorialsNodes) {
NSString *strResponse = #"";
for (int l=0; l<[[element children] count]; l++)
{
strResponse =[strResponse stringByAppendingString:[[[element children] objectAtIndex:l] content]];
NSArray *_children = [[[element children] objectAtIndex:l] children];
NSLog(#"count = %d",[_children count]);
for (int k=0; k<[_children count]; k++)
{
NSLog(#"%#",[[_children objectAtIndex:k] children]);
NSArray *_internalChildren = [[_children objectAtIndex:k] children];
for (int j=0; j<[_internalChildren count]; j++)
{
NSLog(#"%#",[[_internalChildren objectAtIndex:j] content]);
strResponse = [strResponse stringByAppendingFormat:#"%#",[[_internalChildren objectAtIndex:j] content]];
}
}
}
Tutorial *tutorial = [[Tutorial alloc] init];
[newTutorials addObject:tutorial];
tutorial.title = strResponse;
NSLog(#"strResponse = %#",strResponse);
NSLog(#"Data---%#",tutorial.title);
}
_data = newTutorials;
delegateObj.arrDetailContent = [_data mutableCopy];
}
It might also we worth it to note the Log does not return any information for the above code. I added an exception breakpoint which breaks at this line (because the _data array is empty)
Tutorial *data = [_data objectAtIndex:indexPath.row];
This may also help to track down the problem (this is at the top of the TwitterController.m)
#pragma mark - Calling Twitter feeds
-(void)getAndParseTwitterFeeds
{
[self loadAtData];
[self loadNames];
[self loadData];
[self loadImages];
[self loadHours];
[self loadLink];
[self loadImages];
[self loadHours];
}
-(void)getFeeds
{
[self getAndParseTwitterFeeds];
}
-(void)getFeedsLocally
{
_link = delegateObj.arrTwitterLink;
_objects = delegateObj.arrObjects;
_members = delegateObj.arrMemberName;
_data = delegateObj.arrDetailContent;
arrProfileImages = delegateObj.arrImages;
_hours = delegateObj.arrHour;
[self updateTableViewWithTheData];
}
Hope that is enough explanation... I'm really hoping someone can help me figure out why the array is not being filled. Thanks!!!!
EDIT: I'm starting to wonder now if the HTML parser is having trouble with images in tweets. This code is from around 2013 which pre-dates twitter's inline images. Could this be causing the array to return empty?
Also of note the arrays _link, _members, _hours, etc. are all being populated correctly and have identical coding up until the "NSString *strResponse" section for loadData.
I have a table on my ios app that shows last tweets, however after updating my app to 64bit architecture I'm getting four times the following error: multiple methods named 'objectAtIndex:' found with mismatched result, parameter type or attributes error.
This is the relevant part of the code:
-(void)tableView:(UITableView*)tableView didHoldRowAtIndexPath:(NSIndexPath*)indexPath {
if ([NXCatchall isiPad]) {
NSDictionary *tweet = [twitterHandler getTweetForArrayIndex:indexPath.row];
NSDictionary *urls = [[tweet objectForKey:#"entities"] objectForKey:#"urls"];
urlDict = [NSMutableDictionary dictionary];
for (int i=0; i<urls.count; i++) {
NSString *displayName = [[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[[urls valueForKey:#"expanded_url"]objectAtIndex:i]];
[urlDict setValue:url forKey:displayName];
}
if (urlDict.count != 0) {
UIActionSheet *actionSheet = [[UIActionSheet alloc] init];
[actionSheet setTitle:#"Open in Safari"];
[actionSheet setDelegate:self];
for (int i=0; i<urlDict.count; i++) {
// NSString *key = [[dict allKeys] objectAtIndex:i];
//Yes it's ugly, it works at runtime. Deal with it.
[actionSheet addButtonWithTitle:[[urlDict valueForKey:(NSString*)
[[urlDict allKeys]objectAtIndex:i]]absoluteString]];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"heldTweetWithInfo" object:self userInfo:[NSDictionary dictionaryWithObject:actionSheet forKey:#"actionSheet"]];
}
}
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *tweet = [twitterHandler getTweetForArrayIndex:indexPath.row];
if ([NXCatchall isiPad]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"selectedTweetNotification" object:self userInfo:tweet];
}
NSDictionary *urls = [[tweet objectForKey:#"entities"] objectForKey:#"urls"];
urlDict = [NSMutableDictionary dictionary];
for (int i=0; i<urls.count; i++) {
NSString *displayName = [[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[[urls valueForKey:#"expanded_url"]objectAtIndex:i]];
[urlDict setValue:url forKey:displayName];
}
Affected lines start with NSString & NSURL
Try casting it into NSArray. My guess is that some other class declares objectAtIndex.
NSString *displayName = [(NSArray *)[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[(NSArray *)[urls valueForKey:#"expanded_url"]objectAtIndex:i]];
This question already has answers here:
populating a tableview with data using JSON and AFNetworking NSDictionary
(1 answer)
JSON data is not loading in slow internet connection? [closed]
(1 answer)
Closed 8 years ago.
I'm building an article reading app.I'm parsing JSON data using NSData in UITableView.
I'm facing an issue that is data is not load in slow internet speed(2g or 3g)means UI is empty.I want to implement NSUrlConnection
but i'm new in iOS development unable to implement NSUrlConnection in my code.
this is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL myBool = [self isNetworkAvailable];
if (myBool)
{
#try {
// for table cell seperator line color
self.tableView.separatorColor = [UIColor colorWithRed:190/255.0 green:190/255.0 blue:190/255.0 alpha:1.0];
UIBarButtonItem *backbutton1 = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStyleBordered target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backbutton1];
_Title1 = [[NSMutableArray alloc] init];
_Author1 = [[NSMutableArray alloc] init];
_Images1 = [[NSMutableArray alloc] init];
_Details1 = [[NSMutableArray alloc] init];
_link1 = [[NSMutableArray alloc] init];
_Date1 = [[NSMutableArray alloc] init];
NSData* data = [NSData dataWithContentsOfURL:ysURL];
NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if(ys_avatars){
for (int j=0;j<ys_avatars.count;j++)
{
if( ys_avatars[j][#"title"]==[NSNull null] ){
[_Title1 addObject: #""];
}
else{
[_Title1 addObject:ys_avatars[j][#"title"]];
}
if( ys_avatars[j][#"author"]==[NSNull null] ){
[_Author1 addObject: #""];
}
[_Author1 addObject: ys_avatars[j][#"author"]];
if( ys_avatars[j][#"featured_img"]==[NSNull null] ){
[_Images1 addObject: #""];
}
else{
[_Images1 addObject: ys_avatars[j][#"featured_img"]];
}
if( ys_avatars[j][#"content"]==[NSNull null] ){
[_Details1 addObject: #""];
}else{
[_Details1 addObject:ys_avatars[j][#"content"]];
}
if( ys_avatars[j][#"permalink"]==[NSNull null] ){
[_link1 addObject: #""];
}
else{
[_link1 addObject:ys_avatars[j][#"permalink"]];
}
if( ys_avatars[j][#"date"]==[NSNull null] ){
[_Date1 addObject: #""];
}
else{
NSString *newStr=[ys_avatars[j][#"date"] substringToIndex:[ys_avatars[j][#"date"] length]-3];
[_Date1 addObject:newStr];
}
}
}
else
{
NSLog(#"asd");
}
}
#catch (NSException *exception) {
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Cellidentifier1 = #"ysTableViewCell";
ysTableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:Cellidentifier1 forIndexPath:indexPath];
long row = [indexPath row];
cell1.TitleLabel1.text = _Title1[row];
cell1.AuthorLabel1.text = _Author1[row];
NSString *StoryUrl = [_Images1[indexPath.row] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
if(StoryUrl) {
NSArray *subStringsUrl = [yourStoryUrl componentsSeparatedByString:#"/"];
NSString *stripedName = [subStringsUrl lastObject];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* filePath =[documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:#"%#",stripedName]];
if(filePath) {
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
if(image) {
ysTableViewCell *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];
if(updateCell)
updateCell.ThumbImage1.image=image;
cell1.ThumbImage1.image=image;
} else {
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(taskQ, ^{
NSURL *Imageurl = [NSURL URLWithString:yourStoryUrl];
NSData *data = [NSData dataWithContentsOfURL:Imageurl];
UIImage *images1 = [[UIImage alloc] initWithData:data];
NSData *imageData = UIImagePNGRepresentation(images1);
if (![imageData writeToFile:filePath atomically:NO])
{
NSLog((#"Failed to cache image data to disk"));
}
else
{
NSLog(#"the cachedImagedPath is %#",filePath);
}
dispatch_sync(dispatch_get_main_queue(), ^{
ysTableViewCell *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];
if(updateCell)
updateCell.ThumbImage1.image=images1;
cell1.ThumbImage1.image=images1;
});
});
}
return cell1;
}
Help is appreciated.
Thanks in advance.
This looks really messy, and i suggest you change your whole design.
A basic and cleaner way (but probably not the best/cleanest way) :
Create class to handle outside-of-view related work (JSON parsing here)
Call that class in viewDidLoad to start parsing
Call a method that refreshes your table view with the newly parsed data when the parsing is done (in the JSON class).
That way, the table view will load your placeholders first and then reload itself when it has the data.
In my opinion, a better way would be to populate it before loading it so there is no wait time.
Can you find what you need yourself, or code it alone? or do you need help? If so, with what?
EDIT : You could/should also use the AFNetworking framework that will make your life 10 times easier with JSON/Internet related code.
I usually create a class that handles the load of my data, whether from a URL or local store. You could use AFNetworking, but there is a ton of extra stuff you might not need. The basics of using NSUrlConnection is really easy.
Try this tutorial, it will help you to understand how Apple's implementation works before you add a third party library that masks it for you.
NSUrlConnection Tutorial
In my project I'm using WSAssetPickerController.
Despite the toolbar not working (not a huge issue), everything is working fine.
I have added a share button in the view controller, but I can't seem to get the UIDocumentInteractionController to get called, I tried copying the same method I'm using for files saved in the apps folder (which works fine). But here it's not.
How the irrelevant Downloads page works:
NSString *fileName = [directoryContents objectAtIndex:indexPath.row];
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Downloads"];
path = [path stringByAppendingPathComponent:fileName];
documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
[documentController setDelegate:self];
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
How the images get loaded:
#pragma mark - Fetching Code
- (void)fetchAssets
{
// TODO: Listen to ALAssetsLibrary changes in order to update the library if it changes.
// (e.g. if user closes, opens Photos and deletes/takes a photo, we'll get out of range/other error when they come back.
// IDEA: Perhaps the best solution, since this is a modal controller, is to close the modal controller.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.assetsGroup enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (!result || index == NSNotFound) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
self.navigationItem.title = [NSString stringWithFormat:#"%#", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName]];
});
return;
}
WSAssetWrapper *assetWrapper = [[WSAssetWrapper alloc] initWithAsset:result];
dispatch_async(dispatch_get_main_queue(), ^{
[self.fetchedAssets addObject:assetWrapper];
});
}];
});
[self.tableView performSelector:#selector(reloadData) withObject:nil afterDelay:0.5];
}
How I load and call the button:
- (void)viewDidLoad
{
self.navigationItem.title = #"Loading";
UIBarButtonItem *shareButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction
target:self
action:#selector(shareAction:)];
self.navigationItem.rightBarButtonItem = shareButton;
self.navigationItem.rightBarButtonItem.enabled = NO;
// TableView configuration.
self.tableView.contentInset = TABLEVIEW_INSETS;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.allowsSelection = NO;
// Fetch the assets.
[self fetchAssets];
}
Should and did select fetched assets
#pragma mark - WSAssetsTableViewCellDelegate Methods
- (BOOL)assetsTableViewCell:(WSAssetsTableViewCell *)cell shouldSelectAssetAtColumn:(NSUInteger)column
{
BOOL shouldSelectAsset = (self.assetPickerState.selectionLimit == 0 ||
(self.assetPickerState.selectedCount < self.assetPickerState.selectionLimit));
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;
WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
if ((shouldSelectAsset == NO) && (assetWrapper.isSelected == NO))
self.assetPickerState.state = WSAssetPickerStateSelectionLimitReached;
else
self.assetPickerState.state = WSAssetPickerStatePickingAssets;
return shouldSelectAsset;
}
- (void)assetsTableViewCell:(WSAssetsTableViewCell *)cell didSelectAsset:(BOOL)selected atColumn:(NSUInteger)column
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Calculate the index of the corresponding asset.
NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;
WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
assetWrapper.selected = selected;
// Update the state object's selectedAssets.
[self.assetPickerState changeSelectionState:selected forAsset:assetWrapper.asset];
// Update navigation bar with selected count and limit variables
dispatch_async(dispatch_get_main_queue(), ^{
if (self.assetPickerState.selectionLimit) {
self.navigationItem.title = [NSString stringWithFormat:#"%# (%lu/%ld)", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName], (unsigned long)self.assetPickerState.selectedCount, (long)self.assetPickerState.selectionLimit];
}
});
if (self.assetPickerState.selectedCount == 0) {
self.navigationItem.rightBarButtonItem.enabled = NO;
}
else {
self.navigationItem.rightBarButtonItem.enabled = YES;
}
}
Work needed to below with example from the download code I have used before.
-(void)shareAction:(id)sender {
//Launch UIDocumentInteractionController for selected images
documentController =[[UIDocumentInteractionController alloc]init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath://Code needed here??//]];
documentController.delegate=self;
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}
What would be the best practice to do this?
Thanks.
UPDATE 8/4:
-(void)shareAction:(id)sender {
//Launch UIDocumentInteractionController for selected images
if (self.assetPickerState.selectedCount >= 1) {
documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:#"public.image"]];
[documentController setDelegate:self];
[documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
}
}
Returns: Unable to get data for URL: The operation couldn’t be completed. (Cocoa error 260.)
Your interactionControllerWithURL: doesn't seem to be a problem but I have observed that -presentOpenInMenuFromRect: does not show if there are no apps that can open the file.
If your purpose is to share the file, and generally that doesn't mean open the file in the conventional sense, then instead of:
-presentOpenInMenuFromRect:inView:animated:
use
-presentOptionsMenuFromRect:inView:animated:
The former is an OpenInMenu and latter is an OptionsMenu.
For the tiny difference, check my related answer or check Apple doc directly
Example:
//this seems fine
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
//do this
[documentController presentOptionsMenuFromRect:CGRectZero
inView:self.view
animated:YES];
Also..., just before you present the documentInteractionController, it's good practice to specify the file's UTI so the documentInteractionController can populate itself with the appropriate options that can be performed & the list of all apps that can handle this file:
Example:
//assuming the file is a PDF
[documentController setUTI:#"com.adobe.pdf"];
//or... same thing but a more standardized way would be
[documentController setUTI:(NSString *)kUTTypePDF];
//but for this second style you'll need to add the `MobileCoreServices` framework
//to your project bundle and specify the following in your .h or .m
//#import <MobileCoreServices/MobileCoreServices.h>
Extra: Apple's Uniform Type Identifiers Reference