Question

I have an NSScrollView, whose documentView is a huge NSView, made of many many sub-NSImageViews, who act as tiles in a map. (The entire map is the NSView, and since it is way bigger than the screen size, its embedded in a scrollview).

I'm able to display the map with correct tile positions, and scroll around with the bars/gestures. However.. when I enable magnification to be able to zoom, the following happens: enter image description here Somehow I'm assuming auto-layout adds the tile borders below, and I don't know how to disable them. These are surely borders, since I have checked thousands of times that my tiles and subviews are the same size.. so where does this come from? I have quite some experience with iOS development, but am completely lost with NSScrollView (Where are my delegate methods?). How do I disable this behavior of the scroll view?

Here's my subview code:

- (void)setupSubViews
{
  NSLog(@"--------Creating subviews!-------");
    //first we create the subviews..
    //This is the key part, we traverse from top Left, and since OS X coordinates start at bottom left, we need to invert the rows!
    for (int i=0; i< NUMBER_OF_COLUMNS; i++) {
        for (int j=NUMBER_OF_ROWS-1; j>=0; j--) {
            CGRect frame = CGRectMake(i*256, j*256, 256, 256);
            NSImageView *newView = [[NSImageView alloc] initWithFrame:frame];
            newView.focusRingType = NSFocusRingTypeNone; //I gave this focusRing a try, it didn't work :(

            [self addSubview:newView];
        }
    }

}

And this is where I connect the subviews to the actual images..

-(void)updateMap:(id)tilesPassed{

    if (downloadFinished) {
        NSLog(@"--------DRAW RECT-------------");
        NSImageView *subView;
        NSInteger idx = 0;

        for (int i =0; i<[self.subviews count]; i++) {
            subView = [self.subviews objectAtIndex:i];
            [subView setAllowsCutCopyPaste:NO];
            [subView setImageFrameStyle:NSImageFrameNone]; //This doesnt work either :(

            MapTile *tile = [tilesArray objectAtIndex:idx];
            subView.image = tile.image;

            idx++;
        }
    }
}
Was it helpful?

Solution

You probably don't want to use subviews for this. There is a CALayer subclass for exactly this purpose: CATiledLayer: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CATiledLayer_class/Introduction/Introduction.html

With it you can even load different image tiles based on how far you are zoomed in, just like Google Maps. It will render without borders and the performance will be WAY better than using lots of subviews. Subviews are expensive, layers are (generally) cheap.

Update: This example will get you up and running: http://bill.dudney.net/roller/objc/entry/catiledlayer_example

OTHER TIPS

As a quick work around without using CATiledLayer you can stitch all images as one image and add it to main view

Below is the sample code to stitch 2 images:

UIImage *bottomImage = [UIImage imageNamed:@"bottom.png"]; //first image
UIImage *image       = [UIImage imageNamed:@"top.png"]; //foreground image

CGSize newSize = CGSizeMake(209, 260); //size of image view
UIGraphicsBeginImageContext( newSize );

// drawing 1st image
[bottomImage drawInRect:CGRectMake(0,0,newSize.width/2,newSize.height/2)];

// drawing the 2nd image after the 1st
[image drawInRect:CGRectMake(0,newSize.height/2,newSize.width/2,newSize.height/2)] ;

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

and directly add this newImage formed by stitching all your tiled images to the main view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top