I understand that in Objective C we can link buttons and actions together using the interface builder, but the connection must be physically stored in the source code somewhere. I just want to know where is the exact location so I can view it in source code. Not that I am going to manipulate it in anyway I just want to know where they are stored.
Thanks!
Actually there is no linkage, which is why people often mess this up. The xib/storyboard has some names. And the code has some names. But only when the nib loads during runtime is an attempt made to match them up. If they don't match (and it is perfectly possible for them not to match), you can crash.
All the objects and relationships are stored inside the interface builder files like xib or storyboard in the XML format. Those files are parsed during the runtime and the corresponding objects are instantiated along with their relationships. So there is no objective-c code you can find in any of your files. It's all in XML.
Related
I'm trying to build a library that will allow for dynamic loading of Localizable.strings files. If the views are being developed programmatically, then it's not a problem, as I could build a separate NSBundle, store the .strings files inside, and use NSLocalizedStringFromTableInBundle.
The problem I'm having lies with Storyboards. I haven't managed to find a way to specify which .strings file to load from (rather than using the default .strings that Apple uses).
Does anyone know of a solution for this? It doesn't even have to follow the same approach, as long as I can dynamically update the strings on a Storyboard. (The strings will be pulled down from an external source via API call upon app launch)
Loading strings from a separate bundle/strings source
In order to overcome the issue I had, I created IBOutlets for each object on the Storyboard's collection of views. Within each view's implementation file, I programmatically set the text/values of each object by using NSLocalizedStringFromTableInBundle, which allows me to specify a custom bundle, which can be populated with strings files.
In the event that a project has both programmatic and storyboard developed views, this approach also allows for the usage of only one Localizable.strings file, rather than mixing Storyboard-generated files, and files used only for programmatic views (if applicable).
Loading strings into an app via API call
Unfortunately, the above approach doesn't allow for strings to be downloaded from an external source via API call. The reason for this being, Apple doesn't allow for any files in the app bundle to be edited after being built.
Because of this, the solution would be to build out a data structure within the app's DocumentsDirectory, and edit this whenever necessary, then force the app to use this file/library in order to get localized strings. Not a pretty solution, but it's the best approach I can think of.
I have the Storyboard, Base language and translated all the app into another language, so far it's working fine.
I would like to know, when I add new elements in the Storyboard that needs to be localized, how do you keep the strings file up to date.
I tried a suggestion, which is to switch this: to Interface Builder Cocoa Storyboard and then back to Localizable Strings, however the results are not good, most of the translation is lost and switched back to the Base language.
Is there a handy tool to regenerate and merge the strings in Storyboard? I tried few scripts but they always ended up wiping everything.
I've modified a skript that i've found here on stackoverflow to be able to also handle the localized strings in storyboards.
The skript only adds new key-value pairs to the .strings file, but keeps the ones that you have already translated.
You can get it from my github, for more details about my localization workflow read my blogpost
I tried to turn a xib project which is downloaded from iOS Developer Library of Apple, into a pure code one for further use, but it didn't work.
I wonder what should I pay attention to when I do this kind of conversion, and I wonder it will help me improve my skill of iOS developing.
Converting the Xib file into pure code part is not a very big task, you just need to be carefully replace the items created via Interface builder by your code part. You can follow this sequence while converting such projects :-
1) Display the elements made via IB with your code.
2) Make sure the delegates and datasources to be connected via code if they were connected via IB.
3) Check for the IBActions, if any to be replaced.
4) Lastly, if you are not using ARC or the Project that is being converted not using ARC then the dealloc part or viewDidUnload method, where we generally make the objects nil and release.
Hope it helps you :)
There are some tool available. For example, http://kosmaczewski.net/projects/nib2objc/
I notice that normal practice is to declare IBAction methods in the header file. I have also noticed that it is not necessary to do so for Interface Builder to recognise the IBAction methods and allow me to link them to controls. So what is the purpose of declaring the IBAction method in the header file?
There is no good reason, unless you have a good reason to expose them to others -or- if you need to open the nibs in Interface Builder.app.
Some people may do it for historical reasons, or out of habit. Prior to Xcode 4, there was a separate app to edit nibs (Interface Builder). Interface Builder was not backed by a compiler in the way you know it in Xc4; It just used a basic objc parser to interpret headers. Over time, it learned to communicate with Xcode. In earlier days, you had to drag and drop headers to sync them ;)
Ruby Motion just came out, and the screencast doesn't seem to say anything about whether or not you can use Interface Builder to build your interfaces and integrate them in your RubyMotion project. Is such a thing possible? Or do I really have code everything by hand, not to mention maintain to different pieces of code for iPhone/iPad?
My rep isn't high enough to create a rubymotion tag, so please help out if appropriate.
I'd just like to point out that RubyMotion 1.3 now support automatic compilation of .xib files that you put into the resources folder. So now the workflow becomes :
Create your .xib file using XCode (no need to create a project, just use File|New...|File) and save it into the resources folder. As there is no support for outlets yet, be careful to set the tag property for each control you want to use in your code (you'll find in the property sheet of each component under the "View" header).
RubyMotion will take care of compiling your .xib file into a .nib file, so enjoy :)
In your UIViewController derived class, load the nib using loadNibNamed:owner:options:, as shown below.
In viewDidLoad, fetch your various components using viewWithTag: and add events handlers using addTarget:action:forControlEvents:,as show below.
As a bonus, next time you want to edit your xib, just do open resources/MyView.xib, it will only launch the good parts of XCode.
class CalculatorViewController < UIViewController
def loadView
views = NSBundle.mainBundle.loadNibNamed "Keyboard", owner:self, options:nil
self.view = views[0]
end
def viewDidLoad
button = view.viewWithTag 1
button.addTarget self, action:'buttonTapped:', forControlEvents:UIControlEventTouchUpInside
end
def buttonTapped(button)
# ...
end
end
Yes you can use Interface Builder in RubyMotion.
.xib files that are located in the resources directory are automatically compiled into .nib files and available to your project.
There is even a way to support outlets if you are so inclined :
https://github.com/yury/ib#readme
http://ianp.org/2012/05/07/rubymotion-and-interface-builder/
But if you really want to use IB then you could still probably use it to lay out your UI and just call
NSBundle.mainBundle.loadNibNamed(MY_NIB_NAME, owner:self, options:nil)
or similar. I don't think that RubyMotion does any name mangling so you can use your ruby classes in IB by explicitly setting them.
You can probably build the interface in IB and call the command-line tools to compile the XIB to a NIB.
However, you aren't going to be able to connect outlets or assign actions because IB can't parse the Ruby source files for the IBOutlet and IBAction tokens. Normally, the NIB loading code makes those connections for you after loading your NIB. You'll have to do that yourself, in code.
Of the two glaring weaknesses in RubyMotion, to me this is the worst. (The other is that lack of code completion will make writing to the Cocoa APIs really tedious.)
Cappuccino had the same problem. They developed a tool called XcodeCapp: https://github.com/cappuccino/cappuccino/tree/master/Tools/XcodeCapp
It creates "dummy" Obj-C files that you can connect your outlets and actions to in IB, automatically parses them in the background and enables you to use IB to layout your Cappuccino UIs.
It should be possible to take a similar approach with RubyMotion (if you really want to use IB).
Johannes
There is someone who has made that:
Here is a tutorial video: https://www.youtube.com/watch?v=cOapNvehbg4
And this is the website https://github.com/yury/ib
Extra-Tipp: To find wrappers for rubymotion check this source
http://rubymotion-wrappers.com/
Hope this helps