22

I am having an application on iTunes store which displays some UILabel and UIWebView on UIAlertView. According to session video, addSubView for UIAlertView will not work. They have talked about ContentView. But in the GM Seeds SDK, I could not find that property and there seems to be no other way.

The only thing I can do is to create a custom subclass of UIView and make it work like UIAertView. Can you suggest any other simple solution?

Thanks for the help.

nhgrif
  • 61,578
  • 25
  • 134
  • 173
Apurv
  • 17,116
  • 8
  • 51
  • 67

6 Answers6

103

You can really change accessoryView to customContentView in iOS7 (and it seems that in iOS8 as well) UIAlertView

[alertView setValue:customContentView forKey:@"accessoryView"];

Try this code:

UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"TEST" message:@"subview" delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 40)];
[av setValue:v forKey:@"accessoryView"];
v.backgroundColor = [UIColor yellowColor];
[av show];

Remember that you need set custom accessoryView before the call [alertView show]

enter image description here

malex
  • 9,874
  • 3
  • 56
  • 77
  • 4
    Check for IOS version for back compatibility otherwise [av setValue:v forKey:@"accessoryView"]; would crash the app – Ilker Baltaci Feb 17 '14 at 14:11
  • 2
    This question and the answer is for iOS 7 only. But anyway thanks for remark. – malex Feb 17 '14 at 15:13
  • Does anyone no if this will get rejected by apple? – palme Mar 19 '14 at 13:28
  • Very likely to be rejected by Apple, thus downvoting. – DarthMike May 21 '14 at 11:21
  • 1
    @DarthMike I think that it is more honestly to down vote only after certain reject... – malex May 21 '14 at 11:53
  • 8
    I use this in production apps. However, in iOS8 this no longer works. – Gereon Jun 12 '14 at 10:00
  • @Gereon Have you tried to dig into the problem? Does accessoryView still exist? – malex Jun 12 '14 at 10:07
  • @malex not yet, just discovered it today. I'll post here when I find a solution. – Gereon Jun 12 '14 at 12:23
  • @malex I don't think there is a way to do something like this. I will switch all my customized UIAlertViews over to [SDCAlertView](https://github.com/Scott90/SDCAlertView) – Gereon Jun 15 '14 at 22:04
  • It actually works in iOS 8 here. At least setting the accessoryView. But getting it back will crash. Not sure if I'd rely on that behaviour - it's a hack, and it has always been... – Eiko Sep 11 '14 at 17:59
  • 1
    Well, it works in iOS 8, but it's not centering your view. You have to do it by yourself. And yes, as Eiko said it crashes if you try to get the view by calling `valueForKey:`. But if you have for example a progress bar in the view, you can have a global variable for it and it'll work just fine. – Randex Sep 14 '14 at 11:09
  • for me it works on iOS8, but I can't change the place of my view. Any solution?? thanks – Frade Nov 04 '14 at 18:55
  • Crash when calling `[alertView valueForKey:ALERT_EDIT];` on IOS8 – Gank May 21 '15 at 06:53
  • @Gank, what is ALERT_EDIT? – malex May 21 '15 at 07:16
  • @malex @"accessoryView" – Gank May 21 '15 at 08:57
  • Gank have you found why it crash on ios 8? – kalpesh Jul 12 '16 at 12:45
  • Don't want to crash the party, but this breaks the interface. It's not compliant. If a user has larger or smaller text set in Accessibility Settings, the text of the alert view is affected, and becomes covered over. – user4806509 Aug 05 '17 at 22:16
  • and in `Swift`? – Amg91 Feb 02 '19 at 00:31
10

AddSubview is not possible from iOS 7.

The only way is to create a custom UIView subclass which can act as UIAlertView. I could find out few components on Github.

The linked one Custom Alert seems to work well. By putting proper version check one can identify to go for native UIAlertView or CustomAlertView.

Apurv
  • 17,116
  • 8
  • 51
  • 67
3

Adding a subview to an UIAlertView is different in iOS7 from earlier iOS versions. Try something like this:

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    [myAlertView setValue:myCustomView forKey:@"accessoryView"]; //works only in iOS7
} else {
    myAlertView.message = @"\n"; //or just add \n to the end of the message (it's a workaround to create space inside the alert view
    [myAlertView addSubview:myCustomView];
}

[myAlertView show]; //show the alert AFTER CUSTOMIZATION  
Andra Todorescu
  • 628
  • 10
  • 27
-1

Think you will get help also if you use it :)

syncProgressBarView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
syncProgressBarView.frame =CGRectMake(20, 55, 250, 20);
[syncProgressBarView setProgress:0.0f animated:NO];
syncProgressBarView.backgroundColor =[UIColor clearColor];
[progressView addSubview:syncProgressBarView];

Making a new view for sub-viewing UIProgressView

progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, DeviceWidth, 100)];
[[UIApplication sharedApplication].keyWindow addSubview:progressView];
progressView.backgroundColor = [UIColor clearColor];
progressView.center = [UIApplication sharedApplication].keyWindow.center;
syncProgressBarView.frame = CGRectMake(progressView.frame.size.width/2 - 250/2, progressView.frame.size.height/2 - 10, 250, 20);
[[UIApplication sharedApplication].keyWindow bringSubviewToFront:[progressView superview]];

One more thing you have to do...

dispatch_async(dispatch_get_main_queue(), ^{
                [self updateProgressBar];
            });
Emon
  • 452
  • 3
  • 11
  • 21
-2

The custom alert view on github linked in the accepted answer is great. However, you cannot launch this directly from the viewdidload method. The enclosing UIView is attached to the app's first window, so you have to wait a split second. I added this code to viewdidload which I found as a closed issue.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
      // Open the dialog here
   });
leenyburger
  • 1,198
  • 1
  • 11
  • 23
-9

A solution is to subclass UIAlertView and detect the "_UIModalItemAlertContentView" view. My AlertView had a UITextField, so I used it to detect the content view :

- (void)show
{
    [ super show ];
    UIView *contentView=nil;
    if([[[UIDevice currentDevice] systemVersion] floatValue ] < 7.0f)
    {
        contentView=self;
    } else {
        UIView *rootView=[self textFieldAtIndex:0];
        while((rootView=[rootView superview])!=nil)
        {
            if([ NSStringFromClass([rootView class]) isEqualToString:@"_UIModalItemAlertContentView"])
            {
                contentView=rootView;
                break;
            }
        }
    }

    if(contentView!=nil)
    {
        [ contentView addSubview: ... ];
    }
}
Guizmo
  • 1
  • 1
  • 10
    **NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO** you should never subclass `UIAlertView` see the section `"Subclassing notes"` (https://developer.apple.com/library/ios/documentation/uikit/reference/UIAlertView_Class/UIAlertView/UIAlertView.html) - `"The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified."` this will get your app rejected from the app store -1 – Popeye Jan 23 '14 at 12:12