Overriding layoutSubViews: causes "CGAffineTransformInvert: singular matrix" randomly - objective-c

I'm overriding layoutSubViews: in a UIScrollView and from time to time I get "CGAffineTransformInvert: singular matrix" for every subview I reposition. The layout looks totally okay however.
The app does not crash either.
Does anybody know what causes this?

I once had this error cause by mistake was setting a font with size 0 when using
[UIFont fontWithName:size:]
for a UILabel.

In case anyone else is struggling with this (and in case it's not because of setting the label font size to 0), "CGAffineTransformInvert: singular matrix" seems to come up when layoutSubViews: runs on a view (such as UIScrollView or UILabel) that has a frame of size (0,0).
Took me forever to figure out because if your container view (e.g. the scroll view) is not set up to clip subviews, the layout will still look fine.

I was seeing this problem too when I added a UIWebView to my self.view.
The offending code was:
UIWebView *wv = [[UIWebView alloc]init];
and the solution is:
UIWebView *wv = [[UIWebView alloc]initwithFrame:[[UIScreen mainScreen]bounds]];
or any framesize except 0.0.

In my application I got this error as I forget to call the -layoutSubViews of the superClass in the overridden -layoutSubViews method,
so make a call [super layoutSubViews] at any point in your overridden method

Related

MKMapView defaults to 1000x1000 in Xcode8

I'm wondering if anyone else has the issue that MKMapView (Or maybe it relates to many other Views?) does a strange thing where it defaults to 1000x1000 in size the first time I load a screen. When I segue to another screen, and segue back to the map screen, then it actually followed up all my constraints.
This didn't happen with Xcode7 and I wonder if someone knows there's a known bug in Xcode8 or something?
MapKitView get loaded programmatically and is added as a subview within my View that has the constraints.
MKMapView *mapkitView = [[MKMapView alloc] initWithFrame:self.aConstrainedView.frame];
[self.mapkitView setDelegate:self];
[self.mapkitView setShowsUserLocation:YES];
[self.mapkitView setRotateEnabled:NO];
[self.aConstrainedView addSubview:self.mapkitView];
Could this be related to Autoresizing issue in Xcode 8 ?
Your initialiser should use the bounds of its superview, not the frame:
MKMapView *mapkitView = [[MKMapView alloc] initWithFrame:self.aConstrainedView.bounds];
Set a breakpoint on this line and in the debugger use:
(lldb) po self.aConstrainedView.bounds
to ensure the width and height are correct. If you're adding the map view in viewDidLoad, then that's too early. You should override:
- (void)viewDidLayoutSubviews {
dispatch_once(
// Add map view here
);
}
and add your code in there, as that gets called after your subviews have all been laid out according to your constraints.

Why NSView leaves an image on superview on where it was when I move it?

I am working on a small application on Mac that I need to create customed cursor and move it. I used NSImageView to implement it. However when I call setFrameOrigin (the same to setFrame) it will leaves images on the previous place.
Here is my code:
#property (nonatomic, strong) NSImageView *eraserView;
this is the define
_eraserView = [[NSImageView alloc] initWithFrame:CGRectMake(100, 100, 32, 32)];
_eraserView.image = [NSImage imageNamed:#"EraserCursor"];
[self.view addSubview:_eraserView];
[_eraserView setHidden:YES];
here is the initialization. Everything goes well until now but:
- (void)setImageatPoint:(NSPoint)point
{
[_eraserView setFrameOrigin:point];
}
- (void)hidePenImage
{
[_eraserView setHidden:YES];
}
- (void)unhidePenImage: (BOOL)isEraser
{
[_eraserView setHidden:NO];
}
These are methods I use to change the state of the NSImageView. They will be called by another class using delegate when corresponding events of trackpad occurs.
However every time I change the state of the NSImageView, it seems like it is drawn on the superview.
I debugged it and found there was no extra subviews. And when I use setHidden it has no effect on those tracks. I think it somehow did something to the CALayer, but I have no idea how to fix it.
Screenshots would help but in general if you move a view or change the area of the view that is drawn, you need to redraw.
To do this it kind of depends on how your drawing happens. Calling setNeedsDisplay may not be enough if your implementation of drawRect only draws a sub rect of the view bounds. Cocoa only draws what it is told to draw.
You can erase sections of the view that should be empty by drawing (filling) where it should be empty. That means drawing a color ( NSColor clearColor if nothing else) in the area that was previously drawn.

UIProgressView scaling issue

I'm having this odd issue with UIProgressView. This video will explain better than I can with words...
https://vimeo.com/45399884 password: stackoverflow
But basically, I have a UIProgressView that uses iOS5's new setProgress:animated method. I'm animating it but when it animates, the slider part of the control is being scaled from the view's bounds 0,0 to bounds.size.max,bounds.size.max. It animates from left to right properly (with one exception), but scales at the same time. So basically it looks like a diagonal slide.
This is every bit of my progress view code.
progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 11)];
[self.view addSubview:progressView];
[progressView setProgressViewStyle:UIProgressViewStyleBar];
[progressView setProgress:refreshInterval animated:YES];
Any tips or advice is appreciated. Thanks.
The designated initializer for UIProgressView is -initWithProgressViewStyle:. You're not supposed to modify the height of a progress bar, and while the height of the bar-style progress bar is 11, there are probably some effects being initialized in -initWithProgressViewStyle: that you're missing since the default height for the control is 9.
The designated initializer for a UIProgressView appears to be -initWithProgressBarStyle:. Try creating it using that method.

How to dynamically reposition UIButton as subview of UIImageView when rotating

I'm working on an iPad app that lets you control different things in a prototype of an intelligent house. For example it lets you turn lights on and off. For this, I have made a UIImageView that shows the floor plan of the house and added UIButtons as subviews for each lamp that can be toggled.
As you can see the buttons are placed perfectly on the floor plan using the setFrame method of each UIButton. However, when I rotate the iPad to portrait orientation, the following happens:
The buttons obviously still have the same origin, however it is not relative to the repositioning of the image.
The floor plan image has the following settings for struts and springs:
and has its content mode set to Aspect Fit.
My question is
how do I dynamically reposition each UIButton, such that it has the same relative position. I figure I have to handle this in the {did/should}AutorotateToInterfaceOrientation delegate method.
It should be noted that the UIImageView is zoomable and to handle this I have implemented the scrollViewDidZoom delegate method as follows:
for (UIView *button in _floorPlanImage.subviews) {
CGRect oldFrame = button.frame;
[button.layer setAnchorPoint:CGPointMake(0.5, 1)];
button.frame = oldFrame;
button.transform = CGAffineTransformMakeScale(1.0/scrollView.zoomScale, 1.0/scrollView.zoomScale);
}
Thank you in advance!
I find the best way to layout subviews is in the - (void) layoutSubviews method. You will have to subclass your UIImageView and override the method.
This method will automatically get called whenever your frame changes and also gets called the first time your view gets presented.
If you put all your layout code in this method, it prevents layout fragmentation and repetition, keeps your view code in your views, and most things just work by default.

Draw an NSView into an NSGraphicsContext?

I have a CGContext, which I can turn into an NSGraphicsContext.
I have an NSWindow with a clipRect for the context.
I want to put a scrollview into the context and then some other view into the scrollview so I can put an image into it... However, I can't figure out how to attach the scrollview into the context.
Eventually the view will probably be coming from a nib, but I don't see how that would matter.
I've seen this thread, (http://lists.apple.com/archives/quartz-dev/2006/Nov/msg00010.html) But they seem to leave off the step of how to attach the view into the context, unless there's something obvious I'm missing.
EDIT:
The reason I'm in this situation is that I'm writing a Mozilla Plugin. The browser gives me a CGContext (Quartz) and a WindowRef (QuickDraw). I can turn the CGContext into an NSGraphicsContext, and I can turn the windowRef into an NSWindow. From another data structure I also have the clipping rectangle...
I'm trying to draw an image into that context, with scrollbars as needed, and buttons and other UI elements... so I need (want) an NSView...
You can't put a view into a graphics context. A view goes either into another view, or as the content view of a window.
You can draw a view into a context by setting that context as the current context and telling the view to draw. You might do this as a means of rendering the view to an image, but otherwise, I can't think of a reason to do it. (Edit: OK, being a Netscape plug-in is probably a good reason.)
Normally, a view gets its own graphics context in NSView's implementation of the lockFocus method, which is called for you by display, which is called for you by displayIfNeeded (only if the view needs display, obviously), which is called for you as part of the event loop.
You don't need to create a context for a view except in very rare circumstances, such as the export-to-an-image case I mentioned. Normally, you let the view take care of that itself.
A partial solution?
What I have done currently is create a nib with a button in an IKImageView inside an NSScrollView. I load this in my plugin.
Then, since I have the NSWindow, I can get the contentView of the window. Then, I add the scrollview as subview of contentView.
It appears, but there seems to be some coordinate confusion about where the origin is. (top vs bottom) and since I'm mucking with the contentview of the WHOLE WINDOW, I'm doing some stuff very globally that perhaps I should be doing more locally. Like, the view never disappears, even when you close the tab, or go to another tab. (it does close when you close the window of course)
So, does this sound like a reasonable way of doing this? it feels a bit ... kludgy...
For future generations (and me when I forget how I did this and Google leads me back to my own question) Here's how I'm doing this:
I have a NIB with all my views, I load this on start-up.
on SetWindow, I set the clip rect and actually do the attaching:
NP_CGContext* npContext = (NP_CGContext*) window->window;
NSWindow* browserWindow = [[[NSWindow alloc] initWithWindowRef:npContext->window] autorelease];
NSView* cView = [browserWindow contentView];
NSView* hitView = [cView hitTest:NSMakePoint(window->x + 1, clip.origin.y + 1)];
if (hitView == nil || ![[hitView className] isEqualToString:#"ChildView"])
{
return;
}
superView = [hitView retain];
[superView addSubview: topView];
[superView setNextResponder: topView];
[topView setNextResponder: nil];
[browserWindow makeFirstResponder: topView];
To make sure I only addSubView once, I have a flag...
And then in handleEvent, I actually draw, Because I'm using an IKImageView, I can use the undocumented method: [imageView setImage: image]; which takes an NSImage.
So far this seems to be working for me. Hopefully this helps someone else.