Archive

Monthly Archives: December 2013

I have an NSWindowController that swaps between various NSViews using animations.

@interface MyWindowController : NSWindowController
{
    IBOutlet NSWindow*  window;
    IBOutlet NSView*    view;
	NSViewController*	myCurrentViewController;	// the current view controller
    FirstViewController *fvc;
    SecondlViewController *svc;    
    CATransition *transition;
}
- (IBAction)changeToFirstView:(id)sender;
- (IBAction)changeToSecondView:(id)sender;
@end


@implementation MyWindowController

- (void)awakeFromNib
{
    transition = [CATransition animation];
    [transition setType:kCATransitionPush];
    [transition setSubtype:kCATransitionFromLeft];
    NSDictionary *ani = [NSDictionary dictionaryWithObject:transition
                                                    forKey:@"subviews"];
    [view setAnimations:ani];
    [view setWantsLayer:YES];   //  turns on Core Animation

    fvc = [[FirstViewController alloc] initWithNibName:@“FirstView" bundle:nil];
    [view addSubview:[fvc view]];
    myCurrentViewController = fvc;
}

- (IBAction)changeToFirstView:(id)sender;
{
        fvc = [[FirstViewController alloc] initWithNibName:@“FirstView" bundle:nil];
        [[view animator] replaceSubview:[myCurrentViewController view] with:[fvc view]];
        myCurrentViewController = fvc;
}

- (IBAction)changeToSecondView:(id)sender;
{
        svc = [[SecondViewController alloc] initWithNibName:@“SecondView" bundle:nil];
        [[view animator] replaceSubview:[myCurrentViewController view] with:[svc view]];
        myCurrentViewController = svc;
}

However, when the secondView was swapped in for the first time, parts of the firstView remained visible within secondView. These parts were NSTextViews. After playing around for a while I discovered that switching off the drawBackground option for the NSTextViews in Interface Builder stopped the views leaking through to secondView. It also meant that the boxes were no longer distinguishable from the rest of the background in the view. I think the correct solution is to use setNeedsDisplay to force view to redraw its contents when the subviews are swapped. The issue may be related to the use of CoreAnimation in the swapping of the subviews. So I have added a line

    [view setNeedsDisplay:YES];

within the changeToFirstView and changeToSecondView methods.

Dynamic libraries are explained in https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html

There are advantages to using dynamic libraries in applications but extra effort is also required in order for the application to be able to locate and use the library when needed.

Firstly, the install names of the libraries need to be changed so that the target system knows where to find them. Secondly, the dynamic libraries need to be copied into the applications package directory. Finally, it seems that with OS X 10.9 Apple now requires third party libraries to be signed by developers separately. Steps 2 and 3 are accomplished via a script which is placed in the build phases section of Xcode. I needed to add a number of dynamic libraries to an application. One of these was libpari-gmp.dylib and I will use this here as an example.

The first step above is accomplished using the install_name_tool to change the dynamic library install name and dependency names so that the target system knows where to find them. I used otool to find the current install name of the file and dependencies:

otool -L libpari-gmp.dylib

This showed that libpari-gmp.dylib has libgmp.10.dylib as a dependency. The following command line instructions will then change the install names to the same location as the application binary (given by “@executable_path”):

install_name_tool -id @executable_path/libpari-gmp.dylib libpari-gmp.dylib

install_name_tool -change “/path/to/dependency/file/libgmp.10.dylib” @executable_path/libgmp.10.dylib libpari-gmp.dylib

The script that accomplishes steps 2 and 3 above looks like this:

Step 2.

###  Copy the library and dependencies from wherever they are located to the appropriate part of the application package (@executable_path above also known as “”$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/“).

cp -f “/path/to/library/libpari-gmp.dylib” “$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libpari-gmp.dylib”;

cp -f “/path/to/library/libgmp.10.dylib” “$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libgmp.10.dylib”

Step 3.

#  Sign the dynamic library as now required by Apple (see http://furbo.org/2013/10/17/code-signing-and-mavericks/ for a good explanation of the change).

LOCATION=”$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/”

IDENTITY=“Put you code signing identity here”

codesign –verbose –force –sign “$IDENTITY” “$LOCATION/libpari-gmp.dylib”

codesign –verbose –force –sign “$IDENTITY” “$LOCATION/libgmp.10.dylib

In fact step 1 can be performed after step 2 and this is what I did for the dynamic library libiconv.2.dylib. The script for ,ibiconv2.dylib is

cp -f “/opt/local/lib/libiconv.2.dylib” “$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libiconv.2.dylib”

install_name_tool -id @executable_path/libiconv.2.dylib “$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libiconv.2.dylib”;