Conditionally modifying NIBs?

  • Hi!

    Given the recent/ongoing discussion about bypassing Interface Builder
    I have one question/issue for which IB does not seem to provide any
    solution. Interface Builder and NIBs are nice and have many
    advantages but I am missing a way to build different versions of nib
    files depending on Project targets/settings. I'm wondering how others
    handle this?

    Details:
    Let's say I have a project which includes a nib N1 which builds a
    target T1.
    Now I want to add a new target T2 which builds a variant of of T1
    that adds some elements to nib N1 and removes some others (N2).

    I could create a copy of nib N1 and modify it of course. But that has
    two major drawbacks:
    1) Whenever any of the parts of nib N1 and N2 change that are
    identical in both nibs I have to remember to make the changes in both.
    2) This solution does not scale very well when dealing with more than
    one variant.

    I remember in the very dim past (when MacApp was still a modern
    framework ;-) that I had text based resource files (.r) to build the
    'View' resources (rough analog to nibs) which included preprocessor
    macros to control which parts/features where active. These would be
    compiled into .rsrc files using the current build settings. This
    mechanism was very flexible when it came to building different
    variants of an application. (I admit though that the source was hard
    to read and edit due to all of the conditional stuff.)

    Is there any way to achieve someting similar in our modern Cocoa/
    Xcode/IB world? How do others handle this problem?

    Thanks!
    Mike
    --
    Mike Fischer        Softwareentwicklung, EDV-Beratung
                                        Schulung, Vertrieb
    Web: <http://homepage.mac.com/mike_fischer/index.html>
    Note:                I read this list in digest mode!
              Send me a private copy for faster responses.
  • On Wed, May 14, 2008 at 1:37 PM, Mike Fischer <mike_fischer...> wrote:
    >
    > Details:
    > Let's say I have a project which includes a nib N1 which builds a target T1.
    > Now I want to add a new target T2 which builds a variant of of T1 that adds
    > some elements to nib N1 and removes some others (N2).

    Given that you don't want to maintain two separate nibs, I would boil
    down the overlap between N1 and N2 into a new nib, N0, that contains
    only those elements that exist in both. Depending on the extent of the
    non-overlapping pieces, they can either be created programmatically
    after N0 is loaded depending on which target is running, or nibs N1
    and N2 can contain the remaining pieces such that they can be loaded
    in and spliced into N0 (adding new views to tab views, etc etc. If you
    design the nib and interface properly to segregate the common and
    target-specific functionality, this should be fairly straightforward.

    --
    - David T. Wilson
    <david.t.wilson...>
  • Am 14.05.2008 um 20:11 schrieb David Wilson:

    > On Wed, May 14, 2008 at 1:37 PM, Mike Fischer
    > <mike_fischer...> wrote:
    >>
    >> Details:
    >> Let's say I have a project which includes a nib N1 which builds a
    >> target T1.
    >> Now I want to add a new target T2 which builds a variant of of T1
    >> that adds
    >> some elements to nib N1 and removes some others (N2).
    >
    > Given that you don't want to maintain two separate nibs, I would boil
    > down the overlap between N1 and N2 into a new nib, N0, that contains
    > only those elements that exist in both. Depending on the extent of the
    > non-overlapping pieces, they can either be created programmatically
    > after N0 is loaded depending on which target is running, or nibs N1
    > and N2 can contain the remaining pieces such that they can be loaded
    > in and spliced into N0 (adding new views to tab views, etc etc. If you
    > design the nib and interface properly to segregate the common and
    > target-specific functionality, this should be fairly straightforward.

    Yes, I had thought about that possibility. If it is just a view or a
    subview (an area in a view) this is probably easy to do. It gets more
    complicated if there are other objects in the nib that need to be
    connected. Not impossible to do though.

    Also it moves the work needed to "do" the target specific
    modification to run-time instead of build-time. Not that this would
    usually be a huge amount of much work, but it is somewhat wasteful.
    In addition to the work special code is also needed for this,
    bloating the app with stuff that should not really be necessary.

    Mike
    --
    Mike Fischer    Softwareentwicklung, EDV-Beratung
                                    Schulung, Vertrieb
    Note:            I read this list in digest mode!
          Send me a private copy for faster responses.
  • On Wed, May 14, 2008 at 6:37 PM, Mike Fischer <mike_fischer...> wrote:

    > I remember in the very dim past (when MacApp was still a modern framework
    > ;-) that I had text based resource files (.r) to build the 'View' resources
    > (rough analog to nibs) which included preprocessor macros to control which
    > parts/features where active. These would be compiled into .rsrc files using
    > the current build settings. This mechanism was very flexible when it came to
    > building different variants of an application. (I admit though that the
    > source was hard to read and edit due to all of the conditional stuff.)
    >
    > Is there any way to achieve someting similar in our modern Cocoa/Xcode/IB
    > world? How do others handle this problem?

    You could use XIB files instead of NIB files, and write a script to
    process them as a build step before they are compiled...

    Hamish
  • Am 15.05.2008 um 00:07 schrieb Hamish Allan:

    > On Wed, May 14, 2008 at 6:37 PM, Mike Fischer
    > <mike_fischer...> wrote:
    >
    >> I remember in the very dim past (when MacApp was still a modern
    >> framework
    >> ;-) that I had text based resource files (.r) to build the 'View'
    >> resources
    >> (rough analog to nibs) which included preprocessor macros to
    >> control which
    >> parts/features where active. These would be compiled into .rsrc
    >> files using
    >> the current build settings. This mechanism was very flexible when
    >> it came to
    >> building different variants of an application. (I admit though
    >> that the
    >> source was hard to read and edit due to all of the conditional
    >> stuff.)
    >>
    >> Is there any way to achieve someting similar in our modern Cocoa/
    >> Xcode/IB
    >> world? How do others handle this problem?
    >
    > You could use XIB files instead of NIB files, and write a script to
    > process them as a build step before they are compiled...

    Sure, that would be fine.

    Do you happen to have the official format description handy?

    The only thing I found was this:
    > XIB files are not human editable
    > XIB files are the result of writing an in-memory object graph to
    > disk, by using a custom serialization protocol. Editing XIB files
    > by hand is not suggested, extremely dangerous, and can lead to
    > corrupted interfaces
    > XIB 3.x and NIB 3.x files are not backward compatible for development
    > There are some features that can only be developed using the XIB
    > 3.x or NIB 3.x formats. Support for these features—such as support
    > for toolbars, and the promotion of cells to first-class citizens—
    > either required underlying changes in AppKit to support, or
    > introduced new content into the document hierarchy that previous
    > versions of Interface Builder can not handle. Interface Builder 3.0
    > includes an automatic compatibility check, performed before saving,
    > which will inform you of items which affect the file format
    > compatibility.

    From <http://developer.apple.com/releasenotes/DeveloperTools/RN-
    InterfaceBuilder/index.html
    >

    (I know this can be hacked, and that while verbose it's only xml. But
    I'd want my apps building in the next Xcode (sub-)release as well.)

    Mike
    --
    Mike Fischer        Softwareentwicklung, EDV-Beratung
                                        Schulung, Vertrieb
    Web: <http://homepage.mac.com/mike_fischer/index.html>
    Note:                I read this list in digest mode!
              Send me a private copy for faster responses.
  • On Wed, May 14, 2008 at 11:25 PM, Mike Fischer <mike_fischer...> wrote:

    > (I know this can be hacked, and that while verbose it's only xml. But I'd
    > want my apps building in the next Xcode (sub-)release as well.)

    Sure, well, you can't eat your cake and have it ;)

    I'd have thought that you could maybe try to automate "Whenever any of
    the parts of nib N1 and N2 change that are identical in both nibs I
    have to remember to make the changes in both."

    You can also use ibtool for verification, so I don't buy that
    "extremely dangerous" stuff, and the bit about backwards compatibility
    is irrelevant.

    Hamish
  • On May 14, 2008, at 4:10 PM, Hamish Allan wrote:

    > On Wed, May 14, 2008 at 11:25 PM, Mike Fischer
    > <mike_fischer...> wrote:
    >
    >> (I know this can be hacked, and that while verbose it's only xml.
    >> But I'd
    >> want my apps building in the next Xcode (sub-)release as well.)
    >
    > Sure, well, you can't eat your cake and have it ;)
    >
    > I'd have thought that you could maybe try to automate "Whenever any of
    > the parts of nib N1 and N2 change that are identical in both nibs I
    > have to remember to make the changes in both."
    >
    > You can also use ibtool for verification

    How so?

    > , so I don't buy that
    > "extremely dangerous" stuff

    Just because a tool doesn't crash reading the file, and everything
    appears to work normally doesn't mean that the file is correct and
    valid.

    As for the original question, you can modify an IB file, to some
    extent, using ibtool --import and ibtool --export. For example, you
    might consider placing all of your views and objects in the XIB/NIB,
    and then using these options to control the isHidden property of
    various views. That won't be easy though, as it isn't an intended
    usage of ibtool. I think the best option here is to make the changes
    in code, and to only use on IB file.

    Good Luck -
    Jon Hess

    > , and the bit about backwards compatibility
    > is irrelevant.
    >
    >
    > Hamish
  • Am 15.05.2008 um 02:20 schrieb Jonathan Hess:

    > As for the original question, you can modify an IB file, to some
    > extent, using ibtool --import and ibtool --export. For example, you
    > might consider placing all of your views and objects in the XIB/
    > NIB, and then using these options to control the isHidden property
    > of various views.

    That's certainly the most interesting idea I've heard so far. So with
    this method I could in theory assemble different nibs into a single
    one at build time?

    > That won't be easy though, as it isn't an intended usage of ibtool.
    > I think the best option here is to make the changes in code, and to
    > only use on IB file.

    I gather that IB is apparently not meant to allow for scripted build
    processes. It seems to be a purely graphical tool operated manually.
    For many purposes this is fine. But once you have a complex nib and
    want to make incremental changes or changes dependent on some build
    setting it becomes very complicated.

    Even worse IMHO a nib can hide many rather important settings making
    it very hard to understand for someone who is not the original author
    for example. This makes nibs very fragile because small mistakes in
    say connecting things can lead to program errors that are hard to
    debug later on.

    > Good Luck -
    > Jon Hess

    Yes thanks! I keep wondering though how companies that make large
    complicated apps in teams are coping with these limitations. I can't
    imagine building something like Photoshop using nibs for everything
    and working on a nib with more than one person. I'd guess one would
    use nibs for simple things and possibly building blocks and do
    everything else at run-time where what happens is clear and self
    documenting.

    Mike
    --
    Mike Fischer    Softwareentwicklung, EDV-Beratung
                                    Schulung, Vertrieb
    Note:            I read this list in digest mode!
          Send me a private copy for faster responses.
  • Am 15.05.2008 um 01:10 schrieb Hamish Allan:

    > On Wed, May 14, 2008 at 11:25 PM, Mike Fischer
    > <mike_fischer...> wrote:
    >
    >> (I know this can be hacked, and that while verbose it's only xml.
    >> But I'd
    >> want my apps building in the next Xcode (sub-)release as well.)
    >
    > Sure, well, you can't eat your cake and have it ;)

    Too bad ;-)

    > I'd have thought that you could maybe try to automate "Whenever any of
    > the parts of nib N1 and N2 change that are identical in both nibs I
    > have to remember to make the changes in both."

    Well yes, it's possible. But I think one would have to be quite
    desperate to choose that path.

    > You can also use ibtool for verification, so I don't buy that
    > "extremely dangerous" stuff, and the bit about backwards compatibility
    > is irrelevant.

    Well, looking at one of these beasts I'm so sure. There is a lot of
    stuff in there that is not obvious and baring heavy experimentation
    I'd guess that many things need to fit together even if they are in
    totally separate places. I could probably change the dimensions of a
    view or the title of a window. But anything more complicated would be
    a very ambitious undertaking. And I'm not even talking about the
    IBDocument.RunnableNib block of data at the end of the XIB.

    Thanks for your thoughts though.

    Mike
    --
    Mike Fischer        Softwareentwicklung, EDV-Beratung
                                        Schulung, Vertrieb
    Web: <http://homepage.mac.com/mike_fischer/index.html>
    Note:                I read this list in digest mode!
              Send me a private copy for faster responses.
  • On May 15, 2008, at 4:25 AM, Mike Fischer wrote:

    > Am 15.05.2008 um 02:20 schrieb Jonathan Hess:
    >
    >> As for the original question, you can modify an IB file, to some
    >> extent, using ibtool --import and ibtool --export. For example, you
    >> might consider placing all of your views and objects in the XIB/
    >> NIB, and then using these options to control the isHidden property
    >> of various views.
    >
    > That's certainly the most interesting idea I've heard so far. So
    > with this method I could in theory assemble different nibs into a
    > single one at build time?
    >
    >
    >> That won't be easy though, as it isn't an intended usage of ibtool.
    >> I think the best option here is to make the changes in code, and to
    >> only use on IB file.
    >
    > I gather that IB is apparently not meant to allow for scripted build
    > processes. It seems to be a purely graphical tool operated manually.
    > For many purposes this is fine. But once you have a complex nib and
    > want to make incremental changes or changes dependent on some build
    > setting it becomes very complicated.

    Yes and No. ibtool isn't meant for arbitrarily modifying NIB's, but it
    is meant to be worked into the build process to do things like
    automatically validate NIB's, or automatically preform incremental
    localizations.

    >
    >
    > Even worse IMHO a nib can hide many rather important settings making
    > it very hard to understand for someone who is not the original
    > author for example. This makes nibs very fragile because small
    > mistakes in say connecting things can lead to program errors that
    > are hard to debug later on.
    >
    >
    >
    >> Good Luck -
    >> Jon Hess
    >
    >
    > Yes thanks! I keep wondering though how companies that make large
    > complicated apps in teams are coping with these limitations. I can't
    > imagine building something like Photoshop using nibs for everything
    > and working on a nib with more than one person. I'd guess one would
    > use nibs for simple things and possibly building blocks and do
    > everything else at run-time where what happens is clear and self
    > documenting.

    Just like small source files that only aggregate related functionality
    help keep source code readable, the best way to keep your NIB files
    maintainable is to keep them small. Take a look at the contents of
    Interface Builder.app in Xcode 3.0, it's filled with hundreds of small
    NIB files. Most controller's go with exactly one view or window, and
    if you can, it's best to keep the NIB files to one top level view or
    window + one main controller (not counting controllers used for
    bindings). If you have a large window with many different sub-
    components, consider breaking the subcomponents out into separate NIB
    files with just top-level views. A good rule of thumb is probably that
    if a piece of UI requires its own custom controller (in the classical
    sense, not the bindings sense), it should probably have it's own NIB.
    If you do this, it usually makes your NIB files relatively easy to
    understand, and greatly reduces the chances of conflict in your SCM
    system.

    Good Luck -
    Jon Hess

    >
    >
    >
    > Mike
    > --
    > Mike Fischer    Softwareentwicklung, EDV-Beratung
    > Schulung, Vertrieb
    > Note:            I read this list in digest mode!
    > Send me a private copy for faster responses.
    >
  • Am 14.05.2008 um 19:37 schrieb Mike Fischer:
    > Given the recent/ongoing discussion about bypassing Interface
    > Builder I have one question/issue for which IB does not seem to
    > provide any solution. Interface Builder and NIBs are nice and have
    > many advantages but I am missing a way to build different versions
    > of nib files depending on Project targets/settings. I'm wondering
    > how others handle this?

    I generally split up the NIB into several NIBs. That way, I can load
    the master NIB containing the window, and then load the sub-NIBs using
    NSViewController depending on which version of the app is built.

    I also have some view classes not unlike Javas GridBag and similar
    that arrange their subviews and, when used as a window's content view,
    can resize the window to fit their contents. Comes in very handy for
    all sorts of dynamic view arrangements, including using bindings to
    show/hide non-applicable parts and having the window magically re-
    layout in response to that. Though in that case I often just embed the
    views in an NSView that have to be shown/hidden together, without
    loading them from separate NIBs.

    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.zathras.de
  • Am 18.05.2008 um 11:14 schrieb Uli Kusterer:

    > Am 14.05.2008 um 19:37 schrieb Mike Fischer:
    >> Given the recent/ongoing discussion about bypassing Interface
    >> Builder I have one question/issue for which IB does not seem to
    >> provide any solution. Interface Builder and NIBs are nice and have
    >> many advantages but I am missing a way to build different versions
    >> of nib files depending on Project targets/settings. I'm wondering
    >> how others handle this?
    >
    >
    > I generally split up the NIB into several NIBs. That way, I can
    > load the master NIB containing the window, and then load the sub-
    > NIBs using NSViewController depending on which version of the app
    > is built.

    Thanks! That is basically the advice I got from Jon Hess and David
    Wilson. It transfers some of the burden to runtime but I guess this
    is generally the best way to get this done. It also seems to have
    other advantages like less complex nibs and better support for
    version control (svn).

    > I also have some view classes not unlike Javas GridBag and similar
    > that arrange their subviews and, when used as a window's content
    > view, can resize the window to fit their contents. Comes in very
    > handy for all sorts of dynamic view arrangements, including using
    > bindings to show/hide non-applicable parts and having the window
    > magically re-layout in response to that. Though in that case I
    > often just embed the views in an NSView that have to be shown/
    > hidden together, without loading them from separate NIBs.

    Yes, I can see how that would help. I guess I'll be keeping that in
    mind when constructing and adding to my personal library of reusable
    classes.

    Mike
    --
    Mike Fischer        Softwareentwicklung, EDV-Beratung
                                        Schulung, Vertrieb
    Web: <http://homepage.mac.com/mike_fischer/index.html>
    Note:                I read this list in digest mode!
              Send me a private copy for faster responses.
previous month may 2008 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Go to today