UIView subviews not showing up - iphone

In my subclass of UIView (which I have instantiated in Interface Builder), has a couple buttons as subviews that I add to my view in the initWithCoder method like so:
theButton = [UIButton buttonWithType:UIButtonTypeCustom];
[theButton setFrame:CGRectMake([UIScreen mainScreen].bounds.size.height-150-10, 289, 150, 21)];
[theButton.titleLabel setTextAlignment:UITextAlignmentRight];
[theButton setOpaque:YES];
[theButton.titleLabel setFont:[UIFont fontWithName:#"MyFont" size:32.0]];
[theButton.titleLabel setTextColor:[UIColor redColor]];
[theButton.titleLabel setText:#"text"];
[self addSubview:theButton];
[theButton addTarget:myTarget action:#selector(pause) forControlEvents:UIControlEventTouchUpInside];
But the button will not draw as it is supposed to. If I set a breakpoint in drawRect:, and po [self subviews] with llvm, I get this output.
$0 = 0x0c93e860 <__NSArrayM 0xc93e860>(
<UIButton: 0xc93d910; frame = (10 289; 150 21); alpha = 0.5; layer = <CALayer: 0xc93d4a0>>,
<UIButton: 0xc93e2d0; frame = (408 289; 150 21); layer = <CALayer: 0xc93e390>>
)
So why isn't my button showing up?
Edit: my superview's recursiveDescription:
<UIView: 0xa46b220; frame = (0 0; 320 568); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0xa46b280>>
| <MyView: 0xa168710; frame = (0 0; 568 320); autoresize = W+H; layer = <CALayer: 0xa1687d0>>
| | <UIButton: 0xa16c160; frame = (10 289; 150 21); alpha = 0.5; layer = <CALayer: 0xa16bcc0>>
| | | <UIButtonLabel: 0xa16c3e0; frame = (0 0; 0 0); clipsToBounds = YES; hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xa16c480>>
| | <UIButton: 0xa16cb00; frame = (408 289; 150 21); layer = <CALayer: 0xa16cbc0>>
| | | <UIButtonLabel: 0xa16c7e0; frame = (0 0; 0 0); clipsToBounds = YES; hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xa16c880>>

Well, my guess is that your button is showing up, but you made it a custom button with no text for the normal state (and because you are not using any background image or color, it seems invisible).
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:#"Text" forState:UIControlStateNormal];

Instead of calling setText on the button's label, try sending setTitle:forState to the button (not its title label) instead:
[theButton setTitle:#"text" forState:UIControlStateNormal]

Related

disable UIAppearance-API happen on RemoteViewControllers

So i am styling all my views using the apprearance api.
F.e. i style my UINavigationBar using:
[[UINavigationBar appearance] setBackgroundImage:navigationBarBgImage forBarMetrics:UIBarMetricsDefault];
i want to use the advantage of the appearance api of styling all my UINavigationBars in one single place (because i have multiple of them), so i don't want to do some subclassing only because of styling reasons.
i also popup some MFMessageComposeViewControllers and a SLComposeViewController to post to imessage or facebook.
my problem here is, if i try to select albums on facebook or select contacts on imessage modalview, this happens:
see the recursive description of the imessage modal view:
$0 = 0x1f1f1320 <UIWindow: 0x1e5c8900; frame = (0 0; 320 568); layer = <UIWindowLayer: 0x1e5c8a00>>
| <UILayoutContainerView: 0x1e592860; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x1e592910>>
| | <UINavigationTransitionView: 0x1f1c88a0; frame = (0 0; 320 568); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x1f1c8960>>
| | | <UIViewControllerWrapperView: 0x1f1ee090; frame = (0 20; 320 548); autoresize = W+H; layer = <CALayer: 0x1f2f9560>>
| | | | <UIView: 0x1f2f3d20; frame = (0 0; 320 548); autoresize = W+H; layer = <CALayer: 0x1f2f3d80>>
| | | | | <_UISizeTrackingView: 0x1f2effd0; frame = (0 0; 320 548); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x1f2f00b0>>
| | | | | | <_UIRemoteView: 0x1f2f01e0; frame = (0 0; 320 568); transform = [0.5, -0, 0, 0.5, -0, 0]; userInteractionEnabled = NO; layer = <CALayerHost: 0x1f2f0330>>
any ideas whats the best to switch back there to default mode?
Your best bet is really to subclass one thing or the other. Otherwise you'll be undoing styles everywhere. I'll do it in one of two ways:
One is to subclass UINavigationController and style the UINavigationBar contained by that class:
UINavigationBar *navigationBarProxy = [UINavigationBar appearanceWhenContainedIn:[MyNavigationController class], nil]; //
[navigationBarProxy setBackgroundImage:navigationBarBackgroundImage forBarMetrics:UIBarMetricsDefault];
// and so on
Another method is to subclass UINavigationBar instead, set the appearance for that class, and instantiate your UINavigationController this way:
UINavigationController *navigationController = [[UINavigationController alloc] initWithNavigationBarClass:[MyNavigationBar class] toolbarClass:nil];
// navigationController now has a navigationBar of your preferred type
Well, possible solution is set navigation bars to theirs original tint color with [UINavigationBar appearanceWhenContainedIn:[SLComposeViewController class]] ...
I hit the same problem and, worse, it was causing my app to crash for any of the XPC/UIRemoteView based controllers, including SLComposeViewController and MFMailComposeViewController.
My solution is to use this:
[[UINavigationBar appearanceWhenContainedIn:[RootViewController class], nil] setBackgroundImage:[UIImage imageNamed:#"navbar.png"] forBarMetrics:UIBarMetricsDefault];
instead of:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navbar.png"] forBarMetrics:UIBarMetricsDefault];
where RootViewController is whatever you've named the UIViewController that contains all of your app's subviews.
It doesn't work for everything (depends on how a controller ends up in the hierarchy) but, hey, it's something.

IOS activityIndicator subview above MKMapView

I have a mapView (_mapView) which in itself is a subView of my viewController , I would like to add an activityIndicator when I am fetching lots of pins, however I cannot get it to appear above the mapView, can anyone suggest why not
UIActivityIndicatorView *activityIndicator = nil;
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] ;
CGRect frame = activityIndicator.frame;
frame.origin = CGPointMake(290, 12);
activityIndicator.frame = frame;
activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
activityIndicator.tag = 2;
[self._mapView addSubview:activityIndicator];
dataMarkers = [[kepnService new] getPlacesByBounds:neCoord.latitude :neCoord.longitude :swCoord.latitude :swCoord.longitude]; // call to webservice
.... other processing code
[activityIndicator removeFromSuperview];
For information my view stack looks like this
subviews (
"<MKMapView: 0x6d6f320; frame = (0 0; 320 460); clipsToBounds = YES; layer = <CALayer: 0x6d99520>>",
"<UIToolbar: 0x6d93f70; frame = (-1 0; 342 44); autoresize = W+TM; layer = <CALayer: 0x6d8bbf0>>",
"<UINavigationBar: 0x6d9a4f0; frame = (0 416; 320 44); autoresize = W+BM; layer = <CALayer: 0x6d9a5b0>>"
)
Seems like you are adding the activity indicator, blocking the main thread and then removing it.
What you should do is:
Add the activity indicator.
Detach a thread or block to the background to perform the processing code.
When done, remove the activity indicator.

Bizarre UIScrollView behavior

I've got myself totally baffled with this scrollview. For some reason, on the third pass of this loop, an extra two UIImageViews get added as subviews. I assume i'm addressing bad memory, or something to that effect, but I can't figure out where it is coming from for the life of me.
Here's the code:
scrollview=[[[UIScrollView alloc] initWithFrame:CGRectMake(x, y+40, 300, 225)] retain];
NSArray *chunks=[lesson.photoString componentsSeparatedByString:#"|"];
ALAssetsLibrary *assetLibrary;
__block CGRect workingFrame = scrollview.bounds;
__block UIImageView *imageview=nil;
workingFrame.origin.x = 0;
NSLog(#"Chunks: %d\n",[chunks count]);
for(NSString *url in chunks) {
//
if(url && [url length])
{
NSURL *asseturl = [NSURL URLWithString:url];
assetLibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetLibrary assetForURL:asseturl
resultBlock:^(ALAsset *myasset)
{
UIView *sub=[[UIView alloc] initWithFrame:workingFrame];
imageview=[[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:[[myasset defaultRepresentation] fullScreenImage]]];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = sub.bounds;
[sub addSubview:imageview];
[imageview release];
UIButton *imgfull=[UIButton buttonWithType:UIButtonTypeCustom];
[imgfull setFrame:sub.bounds];
imgfull.backgroundColor=[UIColor clearColor];
[imgfull addTarget:self action:#selector(imageViewToFullScreen) forControlEvents:UIControlEventTouchUpInside];
[sub addSubview:imgfull];
[imgfull release];
[scrollview addSubview: sub];
[sub release];
NSLog(#"%#",[scrollview subviews]);
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
[scrollview setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
if(scrollview.contentSize.width>300)
[scrollview flashScrollIndicators];
}
failureBlock:^(NSError *myerror){
NSLog(#"Failure - %#",[myerror localizedDescription]);
}
];
}
}
[scrollview setPagingEnabled:YES];
[self.view addSubview:scrollview];
Here's the output:
2011-05-04 11:53:00.331 AppName[24896:207] Chunks: 4
2011-05-04 11:53:00.369 AppName[24896:207] (
"<UIView: 0x6685960; frame = (0 0; 300 225); layer = <CALayer: 0x6685990>>"
)
2011-05-04 11:53:00.394 AppName[24896:207] (
"<UIView: 0x6685960; frame = (0 0; 300 225); layer = <CALayer: 0x6685990>>",
"<UIView: 0x642db00; frame = (300 0; 300 225); layer = <CALayer: 0x6420c80>>"
)
2011-05-04 11:53:00.426 AppName[24896:207] (
"<UIView: 0x6685960; frame = (0 0; 300 225); layer = <CALayer: 0x6685990>>",
"<UIView: 0x642db00; frame = (300 0; 300 225); layer = <CALayer: 0x6420c80>>",
"<UIImageView: 0x666e3d0; frame = (292 1; 7 223); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x666e400>>",
"<UIImageView: 0x6605490; frame = (1 217; 149 7); opaque = NO; autoresize = TM; userInteractionEnabled = NO; animations = { opacity=<CABasicAnimation: 0x6686ff0>; }; layer = <CALayer: 0x6664280>>",
"<UIView: 0x6686c30; frame = (600 0; 300 225); layer = <CALayer: 0x6686c60>>"
)
2011-05-04 11:53:00.439 AppName[24896:207] (
"<UIView: 0x6685960; frame = (0 0; 300 225); layer = <CALayer: 0x6685990>>",
"<UIView: 0x642db00; frame = (300 0; 300 225); layer = <CALayer: 0x6420c80>>",
"<UIImageView: 0x666e3d0; frame = (292 1; 7 223); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x666e400>>",
"<UIView: 0x6686c30; frame = (600 0; 300 225); layer = <CALayer: 0x6686c60>>",
"<UIImageView: 0x6605490; frame = (1 217; 99 7); opaque = NO; autoresize = TM; userInteractionEnabled = NO; animations = { opacity=<CABasicAnimation: 0x6648d60>; }; layer = <CALayer: 0x6664280>>",
"<UIView: 0x6673f90; frame = (900 0; 300 225); layer = <CALayer: 0x6673fc0>>"
)
EDIT: I should also mention that I've NSLog'd sub, and it produces the results I'd expect (1 imageview, 1 button per trip through the loop). I should also mention, that as far as I know I have no imageviews of the dimensions shown from the scrollview logging (99x7 or 7x223) anywhere in my app.
EDIT 2: A bit further information: I switched the add line to [scrollview addSubview:nil]; and I'm still seeing two imageviews being added on the third pass of the loop. Also, scrollview isn't accessed from anywhere else outside the posted code section.
EDIT 3: Figured out out. I'm flashing the scrollbars too early, which is mucking with the order of the subviews within the scrollview.
Are these the scroll view indicators flashing?
If no unusual images actually appear on your scroll view, you can assume those subviews are managed internally by UIScrollView and you should ignore them. Scroll indicators, perhaps.
Actually These extra two images are the uiscrollindicator images that are vertical scroll indicator and horizontal scroll indicator with tag 0 That are added by UIScrollview Automatically , if you add UIIMageViews to the ScrollView make sure to assign tag greater than zero, or use some other technique , so that you can retrieve your UIIMageViews by tag greater than zero..

Where Does A UIAlertView Live While Not Dismissed

Does anyone know in whose subview an active UIAlertView is located or how to find the thread in which it is running?
If you dump the contents of the windows property and all subviews of all views you can see that the UIAlertView is in a separate window that overlays the main window. Here I have a navbar with a viewcontroller and a tableview (I removed its subviews since they're not relevent).
<UIWindow: 0x411fd50; frame = (0 0; 320 480); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4120af0>>
: <UILayoutContainerView: 0x4123310; frame = (0 0; 320 480); autoresize = W+H; layer = <CALayer: 0x411f800>>
: | <UINavigationTransitionView: 0x4123500; frame = (0 0; 320 480); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x41232e0>>
: | : <UIViewControllerWrapperView: 0x4519d30; frame = (0 64; 320 416); autoresize = W+H; layer = <CALayer: 0x4519a40>>
: | : | <UITableView: 0x7808000; frame = (0 0; 320 416); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x45182a0>>
: | <UINavigationBar: 0x45018b0; frame = (0 20; 320 44); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x4500fe0>>
: | : <UINavigationItemView: 0x4522a20; frame = (100 8; 160 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4526310>>
: | : <UINavigationItemButtonView: 0x45230a0; frame = (5 7; 87 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4520260>>
<_UIAlertOverlayWindow: 0x4179b70; frame = (0 0; 320 480); opaque = NO; layer = <CALayer: 0x4188dc0>>
: <UIAlertView: 0x4194bc0; frame = (3.8 161.95; 312.4 177.1); transform = [1.1, 0, 0, 1.1, 0, 0]; opaque = NO; animations = { transform=<CABasicAnimation: 0x4191160>; opacity=<CABasicAnimation: 0x41226f0>; }; layer = <CALayer: 0x4144c30>>
: | <UILabel: 0x4177e70; frame = (12 15; 260 23); text = 'Name of Date'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4179370>>
: | <UILabel: 0x418b100; frame = (12 45; 260 41); text = 'Name of the date that you...'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x4128450>>
: | <UIThreePartButton: 0x41942a0; frame = (11 102; 262 43); opaque = NO; tag = 1; layer = <CALayer: 0x4191f30>>
Here is the code that produces the dump. I found it useful on occasion to see what is going on when something isn't doing what I expect:
void dumpView(UIView* aView, NSString* indent) {
if (aView) {
NSLog(#"%#%#", indent, aView); // dump this view
if (aView.subviews.count > 0) {
NSString* subIndent = [[NSString alloc] initWithFormat:#"%#%#",
indent, ([indent length]/2)%2==0 ? #"| " : #": "];
for (UIView* aSubview in aView.subviews) dumpView( aSubview, subIndent );
[subIndent release];
}
}
}
void dumpWindows() {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
dumpView(window, #"dumpView: ");
}
}
The active UIAlertView lives in a separate window (_UIAlertOverlayWindow). Use .windows property to find it.
The whole UI runs in the main thread.
From the problem that you describe with windows and timing, sounds like you should implement alertView:didDismissWithButtonIndex:. You can trigger your followup code from within that method.
EDIT: if that did not work, I'd try doing a delay to execute the FB stuff after a delay when the window is really guaranteed to be gone.

Removing UITextField from superview does not make it disappear on screen

I have the following code
// Breakpoint here
[label removeFromSuperview];
[label release];
label = nil;
stepping through it with the debugger outputs
(gdb) po [self subviews]
<NSCFArray 0x476af70>(
<UIImageView: 0x47581a0; frame = (0 0; 232 81); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x476b3d0>>,
<UILabel: 0x4758870; frame = (15 11; 202 56); text = 'Test'; clipsToBounds = YES; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x476b590>>
)
(gdb) po label
<UILabel: 0x4758870; frame = (15 11; 202 56); text = 'Test'; clipsToBounds = YES; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x476b590>>
(gdb) n
(gdb) n
(gdb) n
(gdb) po [self subviews]
<NSCFArray 0x478c4e0>(
<UIImageView: 0x47581a0; frame = (0 0; 232 81); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x476b3d0>>
)
Yet it is still visible, it does not disappear. Not even if I do [self setNeedsDisplay] immediately after.
Has anyone else come across this? Is it a bug in the SDK or am I missing something?
It turns out a bug in my code elsewhere was causing multiple identical views to be created on top of each other, leading to this behaviour.