Changing button titles from different .m files - objective-c

I am writing some code that works in several languages. When the user changes the language I need to change all the screen prompts and button text. When I am in the .m for that screen I simply type:
[[self.tabBarController.viewControllers objectAtIndex:1] setTitle:#"Setup"];
But how to I change the prompts in the other screens without having to go to each .m and make the changes. I am assuming that "self" can be replaced to allow me to do this.

It sounds like you're trying to use localized strings. Something like this might help you find the right path:
http://www.icanlocalize.com/site/tutorials/iphone-applications-localization-guide/
Basically, instead of using strings like #"Setup" you'll use something like this
[[self.tabBarController.viewControllers objectAtIndex:1] setTitle:
NSLocalizedString("setup_button_title", "Title for the setup button")];

Related

NSDocument - how to prevent a document from being marked as updated automatically?

I have a cocoa app that allows the user to enter a query. I'm using an NSWebView with a TextArea HTML object. The problem is, as soon as I type anything into the textarea, my document gets marked as updated. Does anyone know of a way to prevent this?
I've verified that using a NSTextField does not reproduce this behaviour, but I specifically want to go with the HTML/TextArea for styling.
So basically: Can I make it so an NSDocument does not get marked as edited unless I manually call:
[document updateChangeCount: NSChangeDone];
This post on the Apple mailing list seems to match your problem exactly.
The solution suggested is to set a custom undo manager to the webview (sounds like hard work), however a quick-and-dirty hack looks to me like subclassing updateChangeCount and perverting things to your way of thinking.

Sending requests to System Events from Objective-C/C?

Is there any way to convert the following applescript to Objective-C/C?
tell application "System Events" to set visible of process "Safari" to false
I know I could execute this applescript in Objective-C using the NSAppleScript class or calling system("osascript -e '...'"), however isn't there another way?
How does applescript do this?
Alternatively can I hide a window from another application from Objective-C/C?
Update:
I have found out that you can use SBApplication class to do this:
SBApplication *SystemEvents = [SBApplication applicationWithBundleIdentifier:#"com.apple.systemevents"];
/*SystemEventsApplicationProcess*/ id Safari = [[SystemEvents performSelector:#selector(applicationProcesses)] objectWithName:#"Safari"];
[Safari setVisible:NO]; // Doesn't work!
However this doesn't work as setVisible probably doesn't do what I think.
This is the class hierarchy of SystemEventsApplicationProcess:
SystemEventsApplicationProcess : SystemEventsProcess : SystemEventsUIElement : SystemEventsItem : SBObject : NSObject
And here are the methods available for these SystemEventsXXX classes:
SystemEventsApplicationProcess
applicationFile
SystemEventsProcess
setVisible:
visible
unixId
totalPartitionSize
shortName
partitionSpaceUsed
name
id
hasScriptingTerminology
setFrontmost:
frontmost
fileType
file
displayedName
creatorType
Classic
bundleIdentifier
backgroundOnly
architecture
acceptsRemoteEvents
acceptsHighLevelEvents
windows
menuBars
SystemEventsUIElement
select
clickAt:
setValue:
value
title
subrole
setSize:
size
setSelected:
selected
roleDescription
role
setPosition:
position
orientation
name
minimumValue
maximumValue
help
setFocused:
focused
entireContents
enabled
objectDescription
objectClass
accessibilityDescription
windows
valueIndicators
UIElements
toolBars
textFields
textAreas
tables
tabGroups
staticTexts
splitterGroups
splitters
sliders
sheets
scrollBars
scrollAreas
rows
relevanceIndicators
radioGroups
radioButtons
progressIndicators
popUpButtons
popOvers
outlines
menuItems
menuButtons
menuBarItems
menuBars
menus
lists
incrementors
images
growAreas
groups
drawers
comboBoxes
columns
colorWells
checkboxes
buttons
busyIndicators
browsers
attributes
actions
SystemEventsItem
setName:
name
id
removeActionFromUsingActionName:usingActionNumber:
pick
keyUp
keyDown
increment
editActionOfUsingActionName:usingActionNumber:
doScript
doFolderActionFolderActionCode:withItemList:withWindowSize:
decrement
confirm
cancel
attachedScripts
attachActionToUsing:
stop
start
saveAs:in:
moveTo:
exists
duplicateTo:withProperties:
delete
closeSaving:savingIn:
setProperties:
properties
objectClass
SBObject
// ...
NSObject
// ...
You can use NSRunningApplication, which represents (as its name implies) a running application, and has a -hide method.
NSWorkspace will give you a list of all the running apps: [[NSWorkspace sharedWorkspace] runningApplications], which you can filter, or you can get the object representing Safari using its bundle identifier: +[NSRunningApplication runningApplicationsWithBundleIdentifier:] (note that actually returns an array in case there are multiple running instances of the same app).
The code won't work unless you add the scripting bridge framework to your project and a couple other things. Have you done that... I can't tell. This link seems to have a good explanation of what is required if you need instructions.
By the way, "set visible" means hide the application just like if you hid it from the application menu. However if you want to hide an application I'm sure there's an NSWorkspace method.
Last bit of advice... for only a few lines of applescript code NSApplescript would be your best option. If you intend to use lots of applescript script code then the scripting bridge is the better choice, although I myself often just put a compiled script in my project and then use NSApplescript to initiate the handlers from that script. You can also use the ApplescriptObjC language too. You have lots of choices.

Localizing the Cut|Copy|Paste menu on iOS

Im having some issues localizing a danish app ive made. (The language, not the pastry)
I have set the CFBundleDevelopmentRegion to da_DK for danish in my info.plist, but the popup appearing for text input is still in english, even on phones running the danish OS.
How in Jobs name can i change this ?
The test device is a non-jailbroken iPhone 4S running iOS 5.1 with Danish as its iOS setting, and a danish itunes account associated.
I do not use .xibs for designs. all interfaces are programmed as viewcontrollers.
In the Xcode's file tree (Project Navigator) select your project. in the right hand pane select your project again. select Info and add your language.
I created a sample project, this is the result:
You can do this directly in the info.plist. Something like this:
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>de</string>
<string>es</string>
<string>ja</string>
</array>
Try adding/setting the "Localized resources can be mixed" flag in Info.plist to YES.
You must localize your app in Danish to make the standard UI elements appear in that language. This is to avoid having a UI with mixed languages.
If you don't use xibs, you'd usually do this by adding a Localizable.strings file to your project. In Xcode's "Add File" dialog, you can use the "Strings File" template (under "Resources") for this.
To actually localize the strings file, open the file inspector (⌘ ⌥ 1) and click the + button in the "Localization" section. You'll end up with the file being displayed as a group in the project navigator, with a sub-entry for each language.
The strings file has the format:
"Label_Text" = "Smørrebrød";
(don't forget the semicolon)
To use localized strings in your code, you can use the NSLocalizedString macro like this:
myLabel.text = NSLocalizedString(#"Label_Text", nil);
(The second parameter is for a comment. This can be useful if you use the genstrings tool to extract localizable strings from your code and give the resulting file to a professional translator.)
If you use the English strings as keys, you can leave the English version of Localizable.strings empty (but don't delete it).
Having a Localizable.strings file in the language that the user has selected will also cause standard UI elements, such as the editing menu, photo picker, and so forth, to appear in that language.
If you can't get it working the official way, as provided by #vikingosegundo, you can do this with some creative engineering (Creative as in, oh my god that is dangerous). I discovered this method when I accidentally overrode [NSBundle localizedStringForKey:value:tableName:].
1) Add a category to NSBundle with the following methods:
#import <objc/runtime.h>
+ (void) load {
Method original, swizzled;
original = class_getInstanceMethod(self, #selector(localizedStringForKey:value:table:));
swizzled = class_getInstanceMethod(self, #selector(swizzled_localizedStringForKey:value:table:));
method_exchangeImplementations(original, swizzled);
}
- (NSString*) swizzled_localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
NSLog(#"Key: %#. Value: %#", key, value);
return [self swizzled_localizedStringForKey: key value:value table:tableName];
}
2) Where I simply log the key/value, you want to put an if ([key isEqualToString: xxx] ) block. In there, you want to catch (at least some of) the following key values: Cut, Copy[Menu], Select, Select All, Paste, Delete[Menu], Replace..., Define, Speak, Pause. These are the default values that can appear there.
3) When you have caught the value you can look up in a custom table or use hardcoded values. If you look up in a custom table make sure you have a catch in your swizzled method to avoid infinite looping in your custom table.
NB: Why do you need to swizzle? Because this over-rides all Apple text for you app. You will still want the defaults for all the other strings, so you need to swizzle to get the defaults for the strings you aren't interested in.
Good luck.
Paul
Search if your .xib is localized (you'll find it in the inspector on the right panel) if so go to your Project/Target-Settings press the +-Sign and select "Duplicate English to Danish" or something which means the same (I can't check the right item at the moment)
Btw it's called iPhone 4S.

Cocoa/Obj-C Path Control - Can you restrict it to only select directories?

I'm learning to write Mac programs and am looking at the Path Control object. I need to restrict its selections to only directories and not files.
Is there a way to do this? Is there a special keyword to put in the Legal Types box that means "directories"? I tried "Folder" and "Directory" but they don't work.
Thanks,
Scott
I haven't actually tried this, but it seems like you might be able to call -[NSPathCell setAllowedTypes:], specifying public.folder as the only allowed UTI.
In response to a comment asking for more detail on where it is supposed to go: If you have an outlet to an NSPathControl, you could set this programmatically like so:
[[myPath cell] setAllowedTypes: [NSArray arrayWithObject: #"public.folder"]];
Setting Legal Types in Interface Builder to only allow public.folder works for me.

In iOS, how can you programmatically fill out a pdf form field?

I need to take an existing pdf file and programmatically fill in a list of form fields with text and then save the pdf without ever displaying it to the user.
For instance, if the pdf file contains fields named "LastName", and "FirstName" I would like to set the value of "FirstName" to "Louis" and then save the file.
I've been searching for a long time and can't find any guidance on even where to start since the iOS documentation (and most of the questions on here) seem geared towards displaying or creating pdf content instead of modifying it.
EDIT:
My main question is: Is it possible to open a pdf stream (I know how to do this) and copy each existing pdf dictionary item into a new pdf? I have not been able to find a way to write the dictionary items to a pdf.
I doubt that kind of functionality will ever be in the iOS frameworks. The reason most of the related info you can find "seem[s] geared towards displaying or creating pdf content instead of modifying it" is because that's what the vast majority of use cases will want or need for PDF functionality.
You'll need to find a 3rd party library that can open up PDFs, fill out the AcroForm fields, and then stamp out a PDF. I use iText on Java (there is also iTextSharp for C#) but I don't know of anything for Objective-C.
Once you find that library, you'll need to integrate it into your project. There are undoubtedly several related questions/answers here on SO for whatever version of the SDK you're using.
This would be easier to do with a HTML page. If you wish to use a HTML page instead of a .pdf form then thius is how you would go about doing it:
[field1 setText:#"Field 1 Text"];
[field2 setText:#"Field 2 Text"];
NSString *result;
result = [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"$('#field1').val('%#');", field1.text]];
result = [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"$('#pfield2').val('%#');", field2.text]];
result = [webView stringByEvaluatingJavaScriptFromString:#"$('#submitbutton').click();"];
You would need to create two UILabels or UITextFields and call them "field2" and "field2" in your .h file. You can then find the ID of the field you need to replace e.g. #field1 and then put it where I have put "#field1" and again for the second field where I have put "#field2". There also needs to be a UIWebView with the page already loaded. This code is to be used after the UIWebView page has been loaded. Maybe do the following:
-(void)webViewDidFinishLoad:(UIWebView *)webView {
// Insert above code here
}
You probably need a full understanding of Javascript if you want to do this for the whole form, but this should get you started.
Hope that helps you.