Inconsistent state of NSSplitView - objective-c

I am playing around with NSSplitView - quite successfully for now but here is my Problem:
My SplitView looks like this:
Test project here: https://www.dropbox.com/s/amz863l11nvkdir/TestNSSplitView.zip
I've implemented - (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize to stick the left and the right subview at the same size as before while resizing.
If I open the Window which contains the NSSplitView this message comes up in the console:
<NSSplitView: 0x107de1520>: the delegate <BRSchematicWindowController: 0x10ac11050> was sent -splitView:resizeSubviewsWithOldSize: and left the subview frames in an inconsistent state:
Split view bounds: {{0, 0}, {1068, 600}}
Subview frame: {{0, 0}, {182, 600}}
Subview frame: {{183, 0}, {640, 600}}
Subview frame: {{824, 0}, {243, 600}}
The outer edges of the subview frames are supposed to line up with the split view's bounds' edges. NSSplitView is working around the problem, perhaps at the cost of more redrawing. (This message is only logged once per NSSplitView.)
What is wrong here? I didn't get it even after reading this message...
PS: In the right splitView there is another NSSplitView this isn't the failure. I get this message even without this additional NSSplitView.

If you're targeting OS X 10.6+, then it's much easier to use NSSplitView's splitView:shouldAdjustSizeOfSubview: to control sizing.
One way to use this method would be to add the following IBOutlets to your .h file:
#property (nonatomic, weak) IBOutlet NSView *leftView;
#property (nonatomic, weak) IBOutlet NSView *centerView;
#property (nonatomic, weak) IBOutlet NSView *rightView;
Then implement splitView:shouldAdjustSizeOfSubview: in your .m file like this:
- (BOOL)splitView:(NSSplitView *)aSplitView
shouldAdjustSizeOfSubview:(NSView *)subview {
return (subview == _centerView);
// or return !(subview == _leftView || subview == _rightView);
}
By implementing that, you basically say "only adjust the size of center subview when resizing".
You can comment out the entire splitView:resizeSubviewsWithOldSize: method for the time being unless you need to customize the default behavior in some way.
Note that if you have multiple split views that have this controller object set to be their delegate, you may want to check to see which split view is being passed in the aSplitView parameter and do different things accordingly.

Related

UILabel setting x,y coordintes not working

I'm new to x-code and I am trying to set the x,y position of a UILabel but I can't figure out why it is not working.
.h
#interface ViewController:UIViewController{
IBOutlet UILabel *badgeslabel;
}
#property (nonatomic,retain)IBOutlet UILabel *badgeslabel;
#end
.m
#implementation ViewController
#synthesize badgeslabel;
-(void)setBadge{
[badgeslabel setAlpha:.5];
[badgeslabel setCenter:CGPointMake(160,30)];
}
The setAlpha works, but the setCenter don't. Also, when I put the code in an IBAction the setCenter works but I don't know why.
I'm on xcode 5.0
Any help is appreciated, thank you.
As stated by Joel, if you have autolayout enabled then XCode won't allow you to manually set the x & y values of UIViews within a view controller because they are using constraints, attempting to do this will most likely break any constraints you have setup or XCode has added automatically and distort the position of any other UIViews you have in your View Controller.
If you don't want to use autolayout then simply disable it by going to the File inspector in interface builder (click your storyboard file), and untick "Use Auto Layout". This will revert to the old "Spring & Struts" way of laying out and allow you to set the position of your UIViews in code.

MKMapView and viewDidLoad/viewWillAppear/viewDidAppear using Storyboards

I have a ViewController with a MapView, the controller is initialized by a segue specified in the storyboard. The MapView is connected (via Storyboard) to a property in the controller.
.h file
#interface DetailViewController : UIViewController <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *locationMapView;
I am using a method to center the MapView to a specific region:
- (void)centerMapView
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(geoPoint.latitude, geoPoint.longitude), 1000, 1000);
[self.locationMapView setRegion:region animated:NO];
NSLog(#"size height: %f",self.locationMapView.frame.size.height);
NSLog(#"size width: %f",self.locationMapView.frame.size.width);
}
Calling this method from viewDidLoad/viewWillAppear does nothing for the first time, but centers it correctly for the second time the View is loaded.
The Log output is always:
size height: 0.000000
size width: 0.000000
When called in viewDidAppear the MapView is centered and the output size is correct:
size height: 400.000000
size width: 320.000000
I guess the size values mean that the view is not yet initialized in viewDidLoad/viewWill appear, this might be unrelated to the my problem with setting the region.
I am wondering, if it is really not possible to set the region of the MapView in viewDidLoad/viewWillAppear so the user does not see a changing of the region.
Any advice?
The view size issue probably is unrelated to your problem with setting the region.
The key question: when is DetailViewController's geoPoint property set, relative to when its view gets loaded? If viewDidLoad runs before you set that property (presumably from prepareForSegue:sender: in another view controller), geoPoint will be nil (zero) when you try to center the map, so it won't center it correctly. (And it works the second time because the instance of DetailViewController already exists and has its geoPoint from the previous time.)
You might consider calling your centerMapView method from a custom setter for your geoPoint property -- that way you're guaranteed that it'll happen once the view controller has the appropriate data, which will still be before it appears so there won't be a visible map transition.

Embed ImageView in ScrollView with Auto Layout on iOS 6

I am trying to make very simple element with new iOS 6 SDK with auto layout.
I have an ImageView and Embed it in ScrollView. (everything build with Interface Builder). The .png file is set and imageView mode is set to "Top Left".
Implementation:
#import "ImaginariumViewController.h"
#interface ImaginariumViewController ()
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
#implementation ImaginariumViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = self.imageView.image.size;
self.imageView.frame =
CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
}
#end
When I run the app, the image is not scrolled. Doing all the same with auto layout turned off (with struts and springs), I have working scrolling.
I guess the problem is with constraints. Could anybody help me, please?
I just encountered the same issue in a tutorial that I was updating. I attempted programmatically deleting constraints, cursing, and banging my head against the wall - no luck.
About 5 minutes ago, however, I tried something that had fixed another issue I encountered, and, ta da! UIScrollView is working again! The solution was to move the old code that sets the UIScrollView contentSize property into an implementation of viewDidAppear, rather than viewDidLoad:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.theScroller.contentSize=CGSizeMake(200.0,2000.0);
}
I hope this helps someone else encountering some of the headaches that have appeared with Auto Layout.
Autolayout can be very confusing at first. You actually don't want to set the contentSize of the scrollview anywhere. With a pure autolayout approach the scrollview sets its own content size. See the section on autolayout and UIScrollView in the iOS 6 release notes:
The constraints on the subviews of the scroll view must result in a
size to fill, which is then interpreted as the content size of the
scroll view. (This should not be confused with the
intrinsicContentSize method used for Auto Layout.)
Note that this means that the constraints on the subviews of the scrollview must set explicit widths and heights and not use widths that vary based on aspects of the scrollview.
The second error here is that you set the frame of the UIImageView to the size of the image. With autolayout this is also unnecessary. The UIImageView actually has an intrinsicContentSize which is the size of the underlying image. (To change this you should set constraints for width and height with a high priority) That means that with auto layout to place an image in a scrollview and have it scroll the correct code should be the following:
** nothing at all!!! **
But theres still something you need to watch out for that could cause you to have an image that appears not to scroll and the hint is in the aforelinked release notes:
Note that you can make a subview of the scroll view appear to float
(not scroll) over the other scrolling content by creating constraints
between the view and a view outside the scroll view’s subtree, such as
the scroll view’s superview.
i.e. if you set constraints in interface builder and constrain the image view to a view above the scrollview in the hierarchy it will affect how the view appears to scroll. Mad!
Happy Coding...

Default view (as UIScrollView) of UIViewController - Can't set its content offset

According to my project, I changed the default view that tied to one UIViewController from UIView to UIScrollView as it has to be changed its offset and content size. The way I change from UIView to UIScrollView was by Interface Builder > Custom Class
If I want to change its offset and content size programmatically within The Controller, It can't be done in usual way unless I cast it
[((UIScrollView *)self.view) setContentSize:CGSizeMake(1024, 2000)];
[((UIScrollView *)self.view) setContentOffset:CGPointMake(0, 150)];
But with other UIScrollView within the app, changing their offset and content size can be done like any other,
// Assume that sv is scroll view object
[sv setContentSize:CGSizeMake(1027, 2000)];
[sv setContentOffset:CGPointMake(0, 150)];
When I print that scroll view object, it shown as a UIScrollView
NSLog(#"%#", self.view);
NSLog(#"%#", [self.view class]);
-> <UIScrollView: 0x6d3d3f0; frame = (0 0; 1024 768); autoresize = RM+BM; layer = <CALayer: 0x6d52ce0>; contentOffset: {0, 0}>
-> UIScrollView
Anyone know what I did missing or forgot to do rather than change the view's custom class?
Best and Thank you,
Tar
P.S. Besides the extra code needed, everything works fine. But, I can't take the chance of possible bug in the future. This client is super crazy, no error will be accepted
An alternative to this (that would avoid the need for casting) would be to set the UIViewController custom class back to UIView in interface builder. Then, insert a new UIScrollView as a subview (simply drag and drop in Interface Builder), connecting the UIScrollView to the UIViewController subclass via an IBOutlet that looks something like:
#property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
(When you connect the outlet that property declaration should be generated for you by XCode).
Then, in your UIViewController subclass, you can do something like:
[[self scrollView] setContentSize:CGSizeMake(1024, 2000)];
[[self scrollView] setContentOffset:CGPointMake(0, 150)];
I'm not sure what the best solution is but a quick workaround is to create a method that casts the view in the UIViewController. That is:
- (UIScrollView *)scrollView {
return (UIScrollView *)self.view;
}
Then, instead of referring to the view in the ViewController as self.view, refer to it as self.scrollView.

Two UIViews in one .xib file?

i made a second uiview in mei .xib file. the first view is landscape and i get it by following code
ItemController *newItem;
newItem = [[ItemController alloc] init];
newItem.view.....
how can i "activate" the second view, so i can use it with
newItem.view2...
is that possible? the second view is portait mode, so it should be hidden and when turning the ipad the first view should be hidden and the second gets visible.
thanks
If I understand your question correctly, you can use the method willRotateToInterfaceOrientation:duration: in UIViewController.
You can declare two UIView variables and set connections to them using IB:
IBOutlet UIView *view1;
IBOutlet UIView *view2;
Then, in willRotateToInterfaceOrientation:duration: you can swap the views. Assuming that your ItemController is a subclass of UIViewController, you could have something like this:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[self setView:view1];
}
else {
[self setView:view2];
}
}
When the user rotates the iPad this method will get called automatically.
NOTE: make sure you set shouldAutorotateToInterfaceOrientation: to return YES, and you may have to check the orientation to set the view property to the correct view initially.
EDIT: My answer is assuming that you have two views with distinct layouts/elements and not two views that are essentially the same thing sized for different orientations. If the latter is the case, there is probably a better way to do it using only one view.
The approach you are taking will lead you to a trouble situation when you have some IBActions to associate with click of buttons or change the label text (which is on xib) etc.
The best approach is to change the frame height width and positions when the orientation changes. Although this is difficult in beginning but it will save you from lots of troubles.
For assistance check Rotate UIViewController to counteract changes in UIInterfaceOrientation
Hope this helps.
Thanks,
Madhup