share excel file from one application to another application - ios

I have added export UTI in shareDocument Application
Another application which will import excel file
Now while sharing from shareDocument Application i don't see my application name in the list. So whats wrong here if somebody can share.

Firstly need to add Document Type. Here its for xls and xlsx format document
Now you need specify Import UTI or Export UTI
For more reference check How do I get my application to show up in the “Open in...” menu on iOS for a specific document type?
For All System-DeclaredUniformTypeIdentifiers
Note : To get exact UTI for specific file format :
NSArray *extensionArray = [NSArray arrayWithObjects:#"doc", #"docx", #"ppt", #"pptx", #"xls", #"xlsx",#"mp3",#"mp4",#"rft",#"rtf",#"pages",#"key",#"numbers",nil];
for (int i=0; i<[extensionArray count]; i++) {
NSString *fileExtension = [extensionArray objectAtIndex:i];
NSString *utiString = (__bridge NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(__bridge CFStringRef)fileExtension,NULL);
NSLog(#"Extension: %# UTI:%#",fileExtension,utiString);
}

Related

Adding general and specific localizable files for targets in Xcode

I have two targets in my project: target1 and target2. Each of them uses their localizable.strings resource for localization. But their localizable.strings files are same for 90%.
I want to realize such behavior:
Create general localizable file with common strings
Create localizable files for each target with their special strings that are different (e.x. app_name)
Application should search the string in target's localizable.strings file at first and if this string is not exists, search it in common file
I tried to add localizable.string files for each target and then created common localizable.string file(with membership for target1 and target2), but application uses only common file :(
Does anybody know how to fix it?
Thank you for help!
Maybe you can create a pre-build script to concat the specific strings inside global strings.
Or an other solution, you can create a function to search first in global and after in a specific file (this is an example, not tested) :
- (NSString*) localizedString:(NSString*) key {
//search in global file
NSString *transcription = NSLocalizedString(key, "");
if ([transcription isEqualToString:key]) {
//search in specific file
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"specific_file" ofType:#"strings"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
return [dict objectForKey:key];
}
return transcription;
}
With thanks to lafalex, here is code for swift 2:
if let path = NSBundle.mainBundle().pathForResource("specific_file", ofType: "strings"),
let dict : NSDictionary = NSDictionary(contentsOfFile: path) {
if let localizedString = dict.objectForKey(key) as? String {
return localizedString
}
}

Create custom metaData on a PDF with iOS

I'm working on a project and I need to create and set my own metadata on a PDF (in order to set a GUID directly into the file).
I am currently able to set classic metadata (e.g creator, keywords...etc) but I can't figure out how to add a custom field.
Here's how I set the metadata:
CFMutableDictionaryRef auxInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, NULL, NULL);
CFDictionaryAddValue(auxInfo, kCGPDFContextCreator, CFSTR("John doo"));
CFDictionaryAddValue(auxInfo, kCGPDFContextAuthor, CFSTR("foo bar"));
CFDictionaryRef auxillaryInformation = CFDictionaryCreateCopy(kCFAllocatorDefault, auxInfo);
CFRelease(auxInfo);
// create a context to draw into
CGContextRef graphicContext = CGPDFContextCreate(PDFDataConsumer, &mediaRect, auxillaryInformation);
CFRelease(auxillaryInformation);
CGDataConsumerRelease(PDFDataConsumer);
I tried to replace the kCGPDFContextThing by a custom name but then when I read the metadata, it doesn't appear at all.
For reading the meta I used that
CGPDFDictionaryRef dict = CGPDFDocumentGetInfo(*pdfDoc);
CGPDFDictionaryGetString(dict, "Creator", &objectValue);
I also try that to add a meta :
NSString* str= #"Hello World";
NSData* data=[str dataUsingEncoding:NSUTF8StringEncoding];
CFDataRef cfdata = CFDataCreate(NULL, [data bytes], [data length]);
CGPDFContextAddDocumentMetadata(graphicContext, cfdata);
But it doesn't seems to work neither, and I'm not sure I understand correctly what's done there.
I am also using PDFNet SDK to help the editing, but it doesn't seems to provide any help about metadata so I'm using quartz.
Any help or advice or anything would be welcome, quite lost and I am not an iOS expert at all !!!
You can do low-level editing of a PDF in PDFNet. Briefly:
Create a new custom entry (on the document's root):
Obj* cust_dict = [[myPDFDoc GetRoot] PutDict:#"_MyCustomData" ];
[cust_dict PutText:#"_myGUID" value:#"123-4567-890"];
Read the custom entry:
Obj* dict = [[myPDFDoc GetRoot] FindObj:#"_MyCustomData"];
DictIterator* itr = [dict Get:#"_myGUID"];
Obj* strObj = [itr Value];
NSString* str = [strObj GetAsPDFText];
NSLog(#"guid is %#", str);
Delete a custom entry:
[[myPDFDoc GetRoot] EraseDictElementWithKey:#"_MyCustomData"];
You could also place metadata on a page's root, or in a more standard location, as outlined here: https://groups.google.com/d/msg/pdfnet-sdk/gtPjLZVbRSQ/Tv5DTb9pRXkJ
For more specific information about adding XMP metadata (as your tag implies you're interested in), try searching XMP on the PDFNet support forum: https://groups.google.com/forum/#!searchin/pdfnet-sdk/XMP
I'm not sure how you would do this with Quartz.
Disclosure: I work for PDFTron, maker of PDFNet.

How to perform Localization using sqlite stored data-iOS App?

In my app i am doing localization to support mutiple languages. For that i am creating .string file and using the following method:
-(NSString*) languageSelectedStringForKey:(NSString*)key;
I am using the Key_value concept for this. its working fine. But My question is:
Let say i have a sqlite database which has all the different languages string which needs to be localized.
For eg: for spanish
"Username" = "nombre de usuario";
"Password" = "contraseña";
"Submit" = "presentar";
for french
"Username" = "nom d'utilisateur";
"Password" = "mot de passe";
"Submit" = "soumettre";
all this is insert in a sqlite database.
How can we perform localization with the app that way?
Since you seem to have all strings traduction within one db, you need to have an intermediate data structure that will act as a bridge between the db and your method to localize the string.
You could make use of a dictionary for e.g to store the key string identifier and as a value an array that contain all the languages traduction. You will need to feed this data structure once then.
Note that the recommended way is to use .strings files for localisation so you need to provide us good raison why you can't take this approach.
If those are titles/texts for UIButtons and UILabels use the following syntax in your viewController:
NSString *buttonString = NSLocalizedStringFromTable(#"viewController-title-button-username", #"Localizable", nil);
self.username_label.text = buttonString;
And in your Localizable.strings file you do(you must add localization to your project and set this file to be localized to spanish):
"viewController-title-button-username" = "nombre de usuario";
"tabbar-item1" = "item1 in spanish";
"tabbar-item2" = "item2 in spanish";
"tabbar-item3" = "item3 in spanish";
And the same for the Localizable.strings you have set to be the french:
"viewController-title-button-username" = "nom d'utilisateur";
"tabbar-item1" = "item1 in french";
"tabbar-item2" = "item2 in french";
"tabbar-item3" = "item3 in french";
For your tabbar name, put this in your viewDidLoad for each viewController you have. Just change 1, 2, 3 etc.:
NSString *name = NSLocalizedStringFromTable(#"tabbar-item1", #"Main", nil);
self.title = name;
On the other hand if you are getting either an .xml or retrieving using REST you can do the following:
//Get the name of what you want eg. spanish-data or french-data
NSString *name = NSLocalizedStringFromTable(#"xml-locations-string", #"Main", nil);
//What to add at the end
NSString *append = #".xml";
//Merge strings to what you want to retrieve: spanish-data.xml
NSMutableString *file = [NSMutableString stringWithFormat:#"%#%#", name, append];
//From which URL
NSString *urlString = #"http://www.myDomain.com/ProjectName/";
//Create full URL http://www.myDomain.com/ProjectName/spanish-data.xml
NSString *fileUrl = [NSString stringWithFormat:#"%#%#", urlString, file];
NSURL *url = [NSURL URLWithString:fileUrl];
The data you get back will now be the localized version. And you can use that to set table data or whatever you need.
This is the super simple and therefor not optimized way of doing it. Works for REST as well, you just need to reconstruct to fit your project.

Localizing with different element count

I'd like to give my users a warm welcome, when they are opening my application. So I want to have different sentences to show them randomly. The count of messages differs in each language.
What is the preferred way to solve this problem?
My ideas:
Save the count also in the strings file -> Don't like this idea, because this must be maintained
"welcomeCount" = "5";
"welcomeN" = "Hi....";
Seperating the messages -> Don't like this idea, because you have to mind this
"welcomeMessages" = "Hey there...|MessageN";
Anyone out there with an idea to solve this issue in a elegant manner?
You can store the welcome messages in localized property lists.
In Xcode, go to File -> New -> File ...
Choose the Resource -> Property List template and for example "Welcome.plist" as file name.
Select Welcome.plist in Xcode and change the type of the root object from Dictionary to Array.
Select Welcome.plist, to go the File Inspector and click on "Make Localized ...". Then select the localizations that you want for the Welcome.plist., for example English and German.
Now you have a Welcome.plist for each language which you can edit separately.
To add strings, click on the "+" symbol in the property list.
In your program, you can load the list easily with
NSString *path = [[NSBundle mainBundle] pathForResource:#"Welcome" ofType:#"plist"];
NSArray *messages = [NSArray arrayWithContentsOfFile:path];
This loads the "right" properly list, depending on the user's language, into the array messages. You can choose a random message with
int idx = arc4random_uniform([messages count]);
NSString *msg = [messages objectAtIndex:idx];
To minimize maintenance, you can use a binary search to find out how many variations are available. Say you have the following in your Localizable.strings:
"Welcome_0" = "Hello";
"Welcome_1" = "Hi";
"Welcome_2" = "What up";
"Welcome_3" = "Howdy";
You can find the count using:
int lower = 0, upper = 10;
while (lower < upper - 1) {
int mid = (lower + upper) / 2;
NSString *key = [NSString stringWithFormat:#"Welcome_%i", mid];
BOOL isAvailable = ![key isEqualToString:NSLocalizedString(key, #"")];
if (isAvailable) lower = mid;
else upper = mid;
}
Finally select you random message using:
NSString *key = [NSString stringWithFormat:#"Welcome_%i", rand() % upper];
NSString *welcome = NSLocalizedString(key, #"");

NSFileManager:enumeratorAtURL: returns a different form of URL to NSFileManager:URLForDirectory

If I fetch my sandbox's Application Support directory using NSFileManager:URLForDirectory then I get back the following URL:
file://localhost/var/mobile/Applications/EA80DE91-394C-4EAB-B269-1081C859BB0F/Library/Application%20Support/
However if I use NSFileManager:enumeratorAtURL to search the directory I get back URLs of the form:
file://localhost/private/var/mobile/Applications/EA80DE91-394C-4EAB-B269-1081C859BB0F/Library/Application%20Support/
This is causing me problems because I'm doing URL search/replace manipulations and the difference causes a mismatch. I've run into this sort of difference elsewhere previously and my solution then was to use the path of the urls (using NSURL:path) instead of the raw URLs, however that won't work in this situation as the paths produced are:
/var/mobile/Applications/EA80DE91-394C-4EAB-B269-1081C859BB0F/Library/Application Support
/private/var/mobile/Applications/EA80DE91-394C-4EAB-B269-1081C859BB0F/Library/Application Support/
What I am trying to do is this: I can have any number of files in my Application Support directory with the same name but different locations, and I need to extract the path relative to the Application Support directory. i.e. if I have the following
/Application Support/abc/file.dat
/ApplicationSupport/abc/def/file.dat
I want to be able to extract "abc" and "abc/def". I was doing this using the following code:
NSArray *keys = [NSArray arrayWithObject:NSURLIsRegularFileKey];
NSDirectoryEnumerator *dirEnumerator = [self.fileManager enumeratorAtURL:[MyManager appSupportDirectory]
includingPropertiesForKeys:keys
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:nil];
for (NSURL *url in dirEnumerator)
{
if ( NSOrderedSame == [[url lastPathComponent] caseInsensitiveCompare:kFilename])
{
NSString *appSupportPath = [[MyManager appSupportDirectory] path];
NSString *pathToFile = [url path];
pathToFile = [pathToFile URLByDeletingLastPathComponent];
NSString *subPath = [pathToFile stringByReplacingOccurrencesOfString:appSupportPath withString:#""];
(MyManager:appSupportDirectory calls NSFileManager:URLForDirectory: using NSApplicationSupportDirectory)
This works fine on the simulator where enumeratorAtURL: and URLFOrDirectory: return identical paths, but due to their differences on hardware it fails.
Is there a way to get enumeratorAtURL: and URLForDirectory: to return identical paths, or if not is there an alternative elegant way of extracting the subpaths to what I am currently doing?
var is symlinked to /private/var/
calling [url URLByResolvingSymlinksInPath] fixes it.
see What does the /private prefix on an iOS file path indicate? for more discussion.
I had to switch to doing this instead:
NSDirectoryEnumerator *dirEnum = [self.fileManager enumeratorAtPath: [NSHomeDirectory() stringByAppendingPathComponent:#"/Library/Application Support/"]];

Resources