Fuente, tamaño y color personalizados de UIAlertController

118

Estoy usando el nuevo UIAlertController para mostrar alertas. Tengo este codigo:

// nil titles break alert interface on iOS 8.0, so we'll be using empty strings
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title message: message preferredStyle: UIAlertControllerStyleAlert];


UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle style: UIAlertActionStyleCancel handler: nil];

[alert addAction: defaultAction];

UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootViewController presentViewController:alert animated:YES completion:nil];

Ahora quiero cambiar el título y la fuente del mensaje, el color, el tamaño, etc. ¿Cuál es la mejor forma de hacer esto?

Editar: debería insertar el código completo. Creé una categoría para UIView que podría mostrar la alerta correcta para la versión de iOS.

@implementation UIView (AlertCompatibility)

+( void )showSimpleAlertWithTitle:( NSString * )title
                          message:( NSString * )message
                cancelButtonTitle:( NSString * )cancelButtonTitle
{
    float iOSVersion = [[UIDevice currentDevice].systemVersion floatValue];
    if (iOSVersion < 8.0f)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle: title
                                                        message: message
                                                       delegate: nil
                                              cancelButtonTitle: cancelButtonTitle
                                              otherButtonTitles: nil];
        [alert show];
    }
    else
    {
        // nil titles break alert interface on iOS 8.0, so we'll be using empty strings
        UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title
                                                                       message: message
                                                                preferredStyle: UIAlertControllerStyleAlert];


        UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle
                                                                style: UIAlertActionStyleCancel
                                                              handler: nil];

        [alert addAction: defaultAction];

        UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
        [rootViewController presentViewController:alert animated:YES completion:nil];
    }
}
Libor Zapletal
fuente
2
DISCLAIMER:Para cualquiera que esté leyendo las siguientes respuestas. Apple rechazará su (s) aplicación (es). Si sueles usar alguna API privada. Y en las siguientes respuestas ESO ES LO QUE ESTÁ SUCEDIENDO ..
Yash Bedi

Respuestas:

98

No estoy seguro de si esto va en contra de las API / propiedades privadas, pero el uso de KVC me funciona en ios8

UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Dont care what goes here, since we're about to change below" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
NSMutableAttributedString *hogan = [[NSMutableAttributedString alloc] initWithString:@"Presenting the great... Hulk Hogan!"];
[hogan addAttribute:NSFontAttributeName
              value:[UIFont systemFontOfSize:50.0]
              range:NSMakeRange(24, 11)];
[alertVC setValue:hogan forKey:@"attributedTitle"];



UIAlertAction *button = [UIAlertAction actionWithTitle:@"Label text" 
                                        style:UIAlertActionStyleDefault
                                        handler:^(UIAlertAction *action){
                                                    //add code to make something happen once tapped
}];
UIImage *accessoryImage = [UIImage imageNamed:@"someImage"];
[button setValue:accessoryImage forKey:@"image"];

Para el registro, también es posible cambiar la fuente de la acción de alerta, utilizando esas API privadas. Nuevamente, es posible que rechacen su aplicación, todavía no he intentado enviar dicho código.

let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)

let action = UIAlertAction(title: "Some title", style: .Default, handler: nil)
let attributedText = NSMutableAttributedString(string: "Some title")

let range = NSRange(location: 0, length: attributedText.length)
attributedText.addAttribute(NSKernAttributeName, value: 1.5, range: range)
attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "ProximaNova-Semibold", size: 20.0)!, range: range)

alert.addAction(action)

presentViewController(alert, animated: true, completion: nil)

// this has to be set after presenting the alert, otherwise the internal property __representer is nil
guard let label = action.valueForKey("__representer")?.valueForKey("label") as? UILabel else { return }
label.attributedText = attributedText

Para Swift 4.2 en XCode 10 en adelante, las últimas 2 líneas son ahora:

guard let label = (action!.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel else { return }
        label.attributedText = attributedText
dupuis2387
fuente
6
Esta funcionando. attributedTitlepor título y attributedMessagepor mensaje. No estoy seguro de si es la mejor solución, pero por ahora es lo suficientemente buena para mí.
Libor Zapletal
2
¿Qué personalización podemos agregar en los botones UIAlertController?
Aanchal Chaurasia
1
¡Gracias! Tengo una pequeña pregunta: se pueden usar fuentes y colores personalizados con el mosaico de atributos y el mensaje en formato UIAlertController. ¿Cómo se puede hacer lo mismo con UIAlertAction?
p0lAris
72
Espero que ninguno de ustedes esté planeando lanzar esto a la tienda de aplicaciones, ya que utiliza API privadas. En serio, no tengo idea de por qué estas respuestas se aceptan en Stackoverflow cuando en realidad no son 'respuestas'. Estos son trucos que puede o no publicar en la tienda de aplicaciones.
TheCodingArt
3
Para el caso de lanzar la aplicación en la tienda de aplicaciones, Apple permite algunos de los usos de la API privada, pero no debe usar las API que pueden dañar o afectar el sistema / privacidad del usuario. Entonces, probablemente esta respuesta puede ser aceptada por muchas personas solo por esto. Y probablemente no afecte a la tienda de aplicaciones. ¿Puede alguien que haya usado esto confirmar que su aplicación no ha sido rechazada?
Mehul Thakkar
66

Puede cambiar el color del botón aplicando un color de tinte a un UIAlertController.

En iOS 9, si el color del tinte de la ventana se configuró en un color personalizado, debe aplicar el color del tinte justo después de presentar la alerta. De lo contrario, el color de tinte se restablecerá al color de tinte de ventana personalizado.

// In your AppDelegate for example:
window?.tintColor = UIColor.redColor()

// Elsewhere in the App:
let alertVC = UIAlertController(title: "Title", message: "message", preferredStyle: .Alert)
alertVC.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
alertVC.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))

// Works on iOS 8, but not on iOS 9
// On iOS 9 the button color will be red
alertVC.view.tintColor = UIColor.greenColor()

self.presentViewController(alert, animated: true, completion: nil)

// Necessary to apply tint on iOS 9
alertVC.view.tintColor = UIColor.greenColor()
Macucula
fuente
20
Para aclarar, configurar el tintColor después de presentar el controlador funciona tanto en iOS 8 como en 9, por lo que no es necesario configurarlo dos veces.
arlomedia
Gracias por agregar una respuesta rápida y una solución para este problema en iOS 9.
peacetype
3
Cuando toco y arrastro el dedo hacia abajo, volverá al color predeterminado. ¿Alguna idea?
msmq
Esta es realmente la única respuesta decente aquí.
TheCodingArt
47

Puede cambiar el color del texto del botón usando este código:

alertC.view.tintColor = your color;

Quizás esto te ayude.

ChintaN -Maddy- Ramani
fuente
@esilver, ¿lograste encontrar una solución que funcione con iOS9?
Ash
1
No lo hice. Creé un informe de error con Apple, # 22391695.
esilver
1
Más información sobre esto. Parece que cuando se desplaza por los elementos de una lista larga, el que toca para desplazarse se vuelve azul ...
Bejil
3
Nada de esto funciona en UIAlertController en iOS9 y 9.1 .. No sé qué están haciendo los chicos de Apple ... Necesito cambiar manualmente el tinte de la ventana cada vez que se llama a un controlador de alerta y volver a cambiarlo en el controlador.
Akhilesh Sharma
Funciona con iOS 9.3, a menos que lo retoques fuera: vuelve al sistema azul
Rémi Belzanti
35

En Xcode 8 Swift 3.0

@IBAction func touchUpInside(_ sender: UIButton) {

    let alertController = UIAlertController(title: "", message: "", preferredStyle: .alert)

    //to change font of title and message.
    let titleFont = [NSFontAttributeName: UIFont(name: "ArialHebrew-Bold", size: 18.0)!]
    let messageFont = [NSFontAttributeName: UIFont(name: "Avenir-Roman", size: 12.0)!]

    let titleAttrString = NSMutableAttributedString(string: "Title Here", attributes: titleFont)
    let messageAttrString = NSMutableAttributedString(string: "Message Here", attributes: messageFont)

    alertController.setValue(titleAttrString, forKey: "attributedTitle")
    alertController.setValue(messageAttrString, forKey: "attributedMessage")

    let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
        print("\(action.title)")
    }

    let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
        print("\(action.title)")
    }

    let action3 = UIAlertAction(title: "Action 3", style: .default) { (action) in
        print("\(action.title)")
    }

    let okAction = UIAlertAction(title: "Ok", style: .default) { (action) in
        print("\(action.title)")
    }

    alertController.addAction(action1)
    alertController.addAction(action2)
    alertController.addAction(action3)
    alertController.addAction(okAction)

    alertController.view.tintColor = UIColor.blue
    alertController.view.backgroundColor = UIColor.black
    alertController.view.layer.cornerRadius = 40

    present(alertController, animated: true, completion: nil)

}

Salida

Fuente, tamaño y color personalizados de UIAlertController

Ashok R
fuente
Lo siento hermano, esto es una puesta en marcha. Si es necesario en la función, le informaré ...
iOS
24

Una traducción rápida de la respuesta @ dupuis2387. Resolvió la sintaxis para establecer el UIAlertControllercolor y la fuente del título a través de KVC usando la attributedTitletecla.

let message = "Some message goes here."
let alertController = UIAlertController(
    title: "", // This gets overridden below.
    message: message,
    preferredStyle: .Alert
)
let okAction = UIAlertAction(title: "OK", style: .Cancel) { _ -> Void in
}
alertController.addAction(okAction)

let fontAwesomeHeart = "\u{f004}"
let fontAwesomeFont = UIFont(name: "FontAwesome", size: 17)!
let customTitle:NSString = "I \(fontAwesomeHeart) Swift" // Use NSString, which lets you call rangeOfString()
let systemBoldAttributes:[String : AnyObject] = [ 
    // setting the attributed title wipes out the default bold font,
    // so we need to reconstruct it.
    NSFontAttributeName : UIFont.boldSystemFontOfSize(17)
]
let attributedString = NSMutableAttributedString(string: customTitle as String, attributes:systemBoldAttributes)
let fontAwesomeAttributes = [
    NSFontAttributeName: fontAwesomeFont,
    NSForegroundColorAttributeName : UIColor.redColor()
]
let matchRange = customTitle.rangeOfString(fontAwesomeHeart)
attributedString.addAttributes(fontAwesomeAttributes, range: matchRange)
alertController.setValue(attributedString, forKey: "attributedTitle")

self.presentViewController(alertController, animated: true, completion: nil)

ingrese la descripción de la imagen aquí

Robert Chen
fuente
3
¿Qué pasa con el botón "Aceptar"? ¿Podemos personalizarlo?
Hassan Taleb
@HassanTaleb No he encontrado una buena manera de personalizar el botón. Puede configurar tintColoren el viewo via appearanceWhenContainedIn, pero el tinte desaparece tan pronto como lo toca. Sin embargo, sigo buscando respuestas.
Robert Chen
@AbdulMomen عبدالمؤمن ¿Qué mensaje de error está viendo? El fragmento de código asume que FontAwesome ya está configurado.
Robert Chen
1
@RobertChen para resolver el problema solo pon el tinte después:, self.presentViewController(alertController, animated: true, completion: nil)¿podemos cambiar la fuente del botón "OK"?
Hassan Taleb
4
¿No se considera una api privada?
Jinghan Wang
13

Utilice el UIAppearanceprotocolo. Ejemplo para configurar una fuente: cree una categoría para extender UILabel:

@interface UILabel (FontAppearance)
@property (nonatomic, copy) UIFont * appearanceFont UI_APPEARANCE_SELECTOR;
@end


@implementation UILabel (FontAppearance)

-(void)setAppearanceFont:(UIFont *)font {
    if (font)
        [self setFont:font];
}

-(UIFont *)appearanceFont {
    return self.font;
}

@end

Y su uso:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:[UIFont boldSystemFontOfSize:10]]; //for example

Probado y funcionando con estilo UIAlertControllerStyleActionSheet, pero supongo que también funcionará UIAlertControllerStyleAlert.

PD Mejor comprobar la disponibilidad de clases en lugar de la versión de iOS:

if ([UIAlertController class]) {
    // UIAlertController code (iOS 8)
} else {
    // UIAlertView code (pre iOS 8)
}
Iván
fuente
Está funcionando, pero de esta manera no puedo tener un tamaño diferente para el mensaje y el título.
Libor Zapletal
Esto funciona, pero cuando se hace clic en una acción, ¿la fuente vuelve al tamaño original? ¿Te pasa esto a ti?
Larry
Tengo el mismo problema @Larry y no he encontrado la forma de solucionarlo ... ¿tú?
alasker
12

Utilice el UIAppearanceprotocolo. Haz más trucos appearanceFontpara cambiar la fuenteUIAlertAction .

Crea una categoría para UILabel

UILabel + FontAppearance.h

@interface UILabel (FontAppearance)

@property (nonatomic, copy) UIFont * appearanceFont UI_APPEARANCE_SELECTOR;

@end

UILabel + FontAppearance.m

@implementation UILabel (FontAppearance)

- (void)setAppearanceFont:(UIFont *)font
{
    if (self.tag == 1001) {
        return;
    }

    BOOL isBold = (self.font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold);
    const CGFloat* colors = CGColorGetComponents(self.textColor.CGColor);

    if (self.font.pointSize == 14) {
        // set font for UIAlertController title
        self.font = [UIFont systemFontOfSize:11];
    } else if (self.font.pointSize == 13) {
        // set font for UIAlertController message
        self.font = [UIFont systemFontOfSize:11];
    } else if (isBold) {
        // set font for UIAlertAction with UIAlertActionStyleCancel
        self.font = [UIFont systemFontOfSize:12];
    } else if ((*colors) == 1) {
        // set font for UIAlertAction with UIAlertActionStyleDestructive
        self.font = [UIFont systemFontOfSize:13];
    } else {
        // set font for UIAlertAction with UIAlertActionStyleDefault
        self.font = [UIFont systemFontOfSize:14];
    }
    self.tag = 1001;
}

- (UIFont *)appearanceFont
{
    return self.font;
}

@end

Uso:

añadir

[[UILabel appearanceWhenContainedIn:UIAlertController.class, nil] setAppearanceFont:nil];

en AppDelegate.mhacer que funcione para todos UIAlertController.

usuario3480295
fuente
El título en iOS 8.3 es de 13 puntos y en negrita, así que cambié la condición aif (self.font.pointSize == 13 && isBold) {
Andrew Raphael
Mencionaste cambiar la fuente para UIAlertAction. Pero por lo que puedo decir, UIAlertActionno usa un UILabel. Utiliza un NSString. github.com/nst/iOS-Runtime-Headers/blob/… No sé cómo se puede personalizar la fuente para un archivoNSString .
peacetype
UIAlertAction no es una clase de vista en absoluto. Es una clase abstracta que describe la acción. Luego, la vista en sí se genera dentro de UIAlertController. Por lo tanto, establece la apariencia contenida en UIAlertController.
mangerlahn
12

Swift 5 y 5.1 . Cree un archivo separado y coloque allí el código de personalización UIAlertController

import Foundation
import  UIKit

extension UIAlertController {

  //Set background color of UIAlertController
  func setBackgroudColor(color: UIColor) {
    if let bgView = self.view.subviews.first,
      let groupView = bgView.subviews.first,
      let contentView = groupView.subviews.first {
      contentView.backgroundColor = color
    }
  }

  //Set title font and title color
  func setTitle(font: UIFont?, color: UIColor?) {
    guard let title = self.title else { return }
    let attributeString = NSMutableAttributedString(string: title)//1
    if let titleFont = font {
      attributeString.addAttributes([NSAttributedString.Key.font : titleFont],//2
        range: NSMakeRange(0, title.utf8.count))
    }
    if let titleColor = color {
      attributeString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor],//3
        range: NSMakeRange(0, title.utf8.count))
    }
    self.setValue(attributeString, forKey: "attributedTitle")//4
  }

  //Set message font and message color
  func setMessage(font: UIFont?, color: UIColor?) {
    guard let title = self.message else {
      return
    }
    let attributedString = NSMutableAttributedString(string: title)
    if let titleFont = font {
      attributedString.addAttributes([NSAttributedString.Key.font : titleFont], range: NSMakeRange(0, title.utf8.count))
    }
    if let titleColor = color {
      attributedString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor], range: NSMakeRange(0, title.utf8.count))
    }
    self.setValue(attributedString, forKey: "attributedMessage")//4
  }

  //Set tint color of UIAlertController
  func setTint(color: UIColor) {
    self.view.tintColor = color
  }
}

Ahora en cualquier acción Mostrar alerta

  func tapShowAlert(sender: UIButton) {
    let alertController = UIAlertController(title: "Alert!!", message: "This is custom alert message", preferredStyle: .alert)
    // Change font and color of title
    alertController.setTitle(font: UIFont.boldSystemFont(ofSize: 26), color: UIColor.yellow)
    // Change font and color of message
    alertController.setMessage(font: UIFont(name: "AvenirNextCondensed-HeavyItalic", size: 18), color: UIColor.red)
    // Change background color of UIAlertController
    alertController.setBackgroudColor(color: UIColor.black)
    let actnOk = UIAlertAction(title: "Ok", style: .default, handler: nil)
    let actnCancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
    alertController.addAction(actnOk)
    alertController.addAction(actnCancel)
    self.present(alertController, animated: true, completion: nil)
  }

Resultado

ingrese la descripción de la imagen aquí

Gurjinder Singh
fuente
1
¿Estamos accediendo a alguna API privada por aquí? ¿Ha lanzado alguna aplicación con estas muchas propiedades de alerta personalizadas?
Yash Bedi
@YashBedi está usando API privadas y Apple podría rechazar su aplicación por uso de "API no públicas". No, no he lanzado ninguna aplicación.
Gurjinder Singh
Esto se menciona en el sitio de desarrolladores de Apple -> Importante La clase UIAlertController está diseñada para usarse tal cual y no admite subclases. La jerarquía de vistas de esta clase es privada y no debe modificarse.
Gurjinder Singh
Entendido Jefe Gracias.
Yash Bedi
@Darkglow Por favor, mencione el error. Puedo compilar con éxito el mismo código con swift 5.1
Gurjinder Singh
10

Lo estoy usando.

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor blueColor]];

Agregue una línea (AppDelegate) y funciona para todos los UIAlertController.

Lucas Torquato
fuente
3
Como esto ahora está en desuso, use [[UIView looksWhenContainedInInstancesOfClasses: @ [[UIAlertController class]]] setTintColor: newColor]; en su lugar
Peter Johnson
8

Rápido 4

Ejemplo de fuente personalizada en el título. Lo mismo ocurre con otros componentes, como mensajes o acciones.

    let titleAttributed = NSMutableAttributedString(
            string: Constant.Strings.cancelAbsence, 
            attributes: [NSAttributedStringKey.font:UIFont(name:"FONT_NAME",size: FONT_SIZE)]
    )

    let alertController = UIAlertController(
        title: "",
        message: "",
        preferredStyle: UIAlertControllerStyle.YOUR_STYLE
    )

    alertController.setValue(titleAttributed, forKey : "attributedTitle")
    present(alertController, animated: true, completion: nil)
AnthonyR
fuente
5

Aquí hay una extensión para Swift 4.1 y Xcode 9.4.1:

extension UIAlertController{

func addColorInTitleAndMessage(color:UIColor,titleFontSize:CGFloat = 18, messageFontSize:CGFloat = 13){

    let attributesTitle = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: titleFontSize)]
    let attributesMessage = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: UIFont.systemFont(ofSize: messageFontSize)]
    let attributedTitleText = NSAttributedString(string: self.title ?? "", attributes: attributesTitle)
    let attributedMessageText = NSAttributedString(string: self.message ?? "", attributes: attributesMessage)

    self.setValue(attributedTitleText, forKey: "attributedTitle")
    self.setValue(attributedMessageText, forKey: "attributedMessage")

}}
Vassilis A. Alexiou
fuente
4

Acabo de completar un reemplazo para UIAlertController. Esta es la única forma sensata de hacerlo, creo:


Antiguo

Aquí está mi método en Swift, que combina mucha información de las respuestas aquí

func changeAlert(alert: UIAlertController, backgroundColor: UIColor, textColor: UIColor, buttonColor: UIColor?) {
    let view = alert.view.firstSubview().firstSubview()
    view.backgroundColor = backgroundColor
    view.layer.cornerRadius = 10.0

    // set color to UILabel font
    setSubviewLabelsToTextColor(textColor, view: view)

    // set font to alert via KVC, otherwise it'll get overwritten
    let titleAttributed = NSMutableAttributedString(
        string: alert.title!,
        attributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize(17)])
    alert.setValue(titleAttributed, forKey: "attributedTitle")


    let messageAttributed = NSMutableAttributedString(
        string: alert.message!,
        attributes: [NSFontAttributeName:UIFont.systemFontOfSize(13)])
    alert.setValue(messageAttributed, forKey: "attributedMessage")


    // set the buttons to non-blue, if we have buttons
    if let buttonColor = buttonColor {
        alert.view.tintColor = buttonColor
    }
}

func setSubviewLabelsToTextColor(textColor: UIColor, view:UIView) {
    for subview in view.subviews {
        if let label = subview as? UILabel {
            label.textColor = textColor
        } else {
            setSubviewLabelsToTextColor(textColor, view: subview)
        }
    }
}

Esto funciona perfectamente en algunas situaciones y en otras es un fracaso total (los colores de tinte no se muestran como se esperaba).

Dan Rosenstark
fuente
4

Puede utilizar una biblioteca externa como PMAlertController sin usar una solución alternativa, donde puede sustituir el UIAlertController no personalizable de Apple con una alerta súper personalizable.

Compatible con Xcode 8, Swift 3 y Objective-C

Ejemplo de PMAlertController


caracteristicas:

  • [x] Vista de encabezado
  • [x] Imagen de encabezado (opcional)
  • [x] Título
  • [x] Mensaje de descripción
  • [x] Personalizaciones: fuentes, colores, dimensiones y más
  • [x] 1, 2 botones (horizontalmente) o 3+ botones (verticalmente)
  • [x] Cierre cuando se presiona un botón
  • [x] Compatibilidad con campos de texto
  • [x] Implementación similar a UIAlertController
  • [x] Cocoapods
  • [x] Cartago
  • [x] Animación con UIKit Dynamics
  • [x] Compatibilidad con Objective-C
  • [x] Compatibilidad con Swift 2.3 y Swift 3
Paolo Musolino
fuente
¿PMAlertController permite el ajuste de palabras cuando el texto es largo en los botones de acción?
zeeple
@zeeple considera que el botón de acción es una subclase de UIButton. Algo así actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrappingfunciona bien.
Paolo Musolino
3

Existe un problema al establecer el color del tinte en la vista después de la presentación; incluso si lo hace en el bloque de finalización de presentViewController: animated: deployment :, provoca un efecto de parpadeo en el color de los títulos de los botones. Esto es descuidado, poco profesional y completamente inaceptable.

Otras soluciones presentadas dependen de que la jerarquía de vistas permanezca estática, algo que Apple detesta hacer. Espere que esas soluciones fallen en futuras versiones de iOS.

La única forma segura de resolver este problema y hacerlo en todas partes es agregando una categoría a UIAlertController y ampliando viewWillAppear.

El encabezado:

//
//  UIAlertController+iOS9TintFix.h
//
//  Created by Flor, Daniel J on 11/2/15.
//

#import <UIKit/UIKit.h>

@interface UIAlertController (iOS9TintFix)

+ (void)tintFix;

- (void)swizzledViewWillAppear:(BOOL)animated;

@end

La implementación:

//
//  UIAlertController+iOS9TintFix.m
//
//  Created by Flor, Daniel J on 11/2/15.
//

#import "UIAlertController+iOS9TintFix.h"
#import <objc/runtime.h>

@implementation UIAlertController (iOS9TintFix)

+ (void)tintFix {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method method  = class_getInstanceMethod(self, @selector(viewWillAppear:));
        Method swizzle = class_getInstanceMethod(self, @selector(swizzledViewWillAppear:));
        method_exchangeImplementations(method, swizzle);});
}

- (void)swizzledViewWillAppear:(BOOL)animated {
    [self swizzledViewWillAppear:animated];
    for (UIView *view in self.view.subviews) {
        if (view.tintColor == self.view.tintColor) {
            //only do those that match the main view, so we don't strip the red-tint from destructive buttons.
            self.view.tintColor = [UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0];
            [view setNeedsDisplay];
        }
    }
}

@end

Agregue un .pch (encabezado precompilado) a su proyecto e incluya la categoría:

#import "UIAlertController+iOS9TintFix.h"

Asegúrese de registrar su pch en el proyecto correctamente, e incluirá los métodos de categoría en cada clase que use UIAlertController.

Luego, en el método didFinishLaunchingWithOptions de los delegados de su aplicación, importe su categoría y llame

[UIAlertController tintFix];

y se propagará automáticamente a cada instancia de UIAlertController dentro de su aplicación, ya sea que la inicie su código o el de cualquier otra persona.

Esta solución funciona tanto para iOS 8.X como para iOS 9.X y carece del parpadeo del enfoque posterior a la presentación del cambio de tinte. También es completamente agnóstico con respecto a la jerarquía de vistas de las subvistas de UIAlertController.

¡Feliz piratería!

ObiDan
fuente
Esta solución funciona, sobre todo. Sin embargo, al girar el dispositivo, los tintes vuelven a la forma en que estaban, antes del swizzling.
Dhiraj Gupta
Dhiraj, acabo de probar esto nuevamente en una configuración de proyecto explícitamente para explorar sus hallazgos, y no estoy de acuerdo. El tinte no vuelve a ser como estaba al rotar.
ObiDan
Funcional verificado en xcode 6.4 y xcode 7.0. Ejecución de simuladores de todas las variaciones de 8.X y 9.0. Si se solicita, pondré el proyecto en github.
ObiDan
Bueno, podrías seguir adelante y poner un proyecto, pero esto es lo que estaba viendo que me estaba pasando. Tampoco funcionaba en iPad. Sobre la base de su idea método swizzling, sin embargo, yo era capaz de hacer que funcione por viewDidLayoutSubviews Swizzling, sin embargo.
Dhiraj Gupta
Si pones un proyecto, entonces podría enviar una solicitud de extracción con el swizzle viewDidLayoutSubviews, que es lo que acabo de usar y enviar en la última versión de mi aplicación a la App Store y puedes echar un vistazo, ¿tal vez?
Dhiraj Gupta
3

Encuentre esta categoría. Puedo cambiar la FUENTE y el color de UIAlertAction y UIAlertController.

Utilizar:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:yourDesireFont]];  
Arpan Dixit
fuente
5
Por favor, pegue el código aquí o utilice un servicio que no requiera que las personas
inicien
3

En Swift 4.1 y Xcode 10

//Displaying alert with multiple actions and custom font ans size
let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)

let titFont = [NSAttributedStringKey.font: UIFont(name: "ArialHebrew-Bold", size: 15.0)!]
let msgFont = [NSAttributedStringKey.font: UIFont(name: "Avenir-Roman", size: 13.0)!]

let titAttrString = NSMutableAttributedString(string: "Title Here", attributes: titFont)
let msgAttrString = NSMutableAttributedString(string: "Message Here", attributes: msgFont)

alert.setValue(titAttrString, forKey: "attributedTitle")
alert.setValue(msgAttrString, forKey: "attributedMessage")

let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
    print("\(String(describing: action.title))")
}

let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
    print("\(String(describing: action.title))")
}

let okAction = UIAlertAction(title: "Ok", style: .default) { (action) in
    print("\(String(describing: action.title))")
}
alert.addAction(action1)
alert.addAction(action2)
alert.addAction(okAction)

alert.view.tintColor = UIColor.blue
alert.view.layer.cornerRadius = 40
// //If required background colour 
// alert.view.backgroundColor = UIColor.white

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})
iOS
fuente
su respuesta necesita una actualización, self.present(alertController, animated: true)o self.present(alert, animated: true).
Yash Bedi
@Yash Bedi, gracias, actualicé mi respuesta, compruébalo una vez.
iOS
2

Solución / Hack para iOS9

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Test Error" message:@"This is a test" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"Alert View Displayed");
 [[[[UIApplication sharedApplication] delegate] window] setTintColor:[UIColor whiteColor]];
    }];

    [alertController addAction:cancelAction];
    [[[[UIApplication sharedApplication] delegate] window] setTintColor:[UIColor blackColor]];
    [self presentViewController:alertController animated:YES completion:^{
        NSLog(@"View Controller Displayed");
    }];
Akhilesh Sharma
fuente
Intenté esto. Tenga en cuenta que está revirtiendo la configuración de tinte de ventana una vez que se presenta el controlador de alerta. Veo que el color vuelve a cambiar a la derecha en el controlador de alerta. Creo que la reversión debe realizarse una vez que se haya aprovechado cualquier acción.
Germán
Gracias @ Germán por señalar eso .. Hicimos los cambios en el código. Estoy manejando la reversión en AlertAction a partir de ahora ... Pero sí, estoy de acuerdo en que también se puede manejar en el controlador dimiss
Akhilesh Sharma
1

Trabajo para Urban Outfitters. Tenemos un pod de código abierto URBNAlert, que usamos en todas nuestras aplicaciones. Se basa en UIAlertController, pero es altamente personalizable.

La fuente está aquí: https://github.com/urbn/URBNAlert

O simplemente instálelo por la vaina colocando URBNAlert en su Podfile

Aquí hay un código de muestra:

URBNAlertViewController *uac = [[URBNAlertViewController alloc] initWithTitle:@"The Title of my message can be up to 2 lines long. It wraps and centers." message:@"And the message that is a bunch of text. And the message that is a bunch of text. And the message that is a bunch of text."];

// You can customize style elements per alert as well. These will override the global style just for this alert.
uac.alertStyler.blurTintColor = [[UIColor orangeColor] colorWithAlphaComponent:0.4];
uac.alertStyler.backgroundColor = [UIColor orangeColor];
uac.alertStyler.textFieldEdgeInsets = UIEdgeInsetsMake(0.0, 15.0, 0.0, 15.0);
uac.alertStyler.titleColor = [UIColor purpleColor];
uac.alertStyler.titleFont = [UIFont fontWithName:@"Chalkduster" size:30];
uac.alertStyler.messageColor = [UIColor blackColor];
uac.alertStyler.alertMinWidth = @150;
uac.alertStyler.alertMaxWidth = @200;
// many more styling options available 

[uac addAction:[URBNAlertAction actionWithTitle:@"Ok" actionType:URBNAlertActionTypeNormal actionCompleted:^(URBNAlertAction *action) {
      // Do something
}]];

[uac addAction:[URBNAlertAction actionWithTitle:@"Cancel" actionType:URBNAlertActionTypeCancel actionCompleted:^(URBNAlertAction *action) {
      // Do something
}]];

[uac show];
RyanG
fuente
¿Es compatible con el estilo ActionSheet?
Danpe
@Danpe no lo hace, es puramente solo para Alertas .. Dicho esto .. si es algo que desea crear un problema en el repositorio. Eso es algo para lo que hemos discutido agregar soporte antes
RyanG
1

Para cambiar el color de un botón como CANCELAR al color rojo, puede usar esta propiedad de estilo llamada UIAlertActionStyle.destructive:

let prompt = UIAlertController.init(title: "Reset Password", message: "Enter Your E-mail :", preferredStyle: .alert)
        let okAction = UIAlertAction.init(title: "Submit", style: .default) { (action) in
              //your code
}

let cancelAction = UIAlertAction.init(title: "Cancel", style: UIAlertActionStyle.destructive) { (action) in
                //your code
        }
        prompt.addTextField(configurationHandler: nil)
        prompt.addAction(okAction)
        prompt.addAction(cancelAction)
        present(prompt, animated: true, completion: nil);
Kazim Ahmad
fuente
1

Para iOS 9.0 y superior, use este código en el delegado de la aplicación

[[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];
iOS
fuente
1

Swift 5.0

let titleAttrString = NSMutableAttributedString(string: "This is a title", attributes: [NSAttributedString.Key.font: UIFont(name: "CustomFontName", size: 17) as Any])
let messageAttrString = NSMutableAttributedString(string: "This is a message", attributes: [NSAttributedString.Key.font: UIFont(name: "CustomFontName", size: 13) as Any])

alertController.setValue(titleAttrString, forKey: "attributedTitle")
alertController.setValue(messageAttrString, forKey: "attributedMessage")
Hiren Panchal
fuente
0

Un poco torpe, pero esto me funciona en este momento para establecer colores de fondo y texto. Lo encontré aquí .

UIView * firstView = alertController.view.subviews.firstObject;
    UIView * nextView = firstView.subviews.firstObject;
    nextView.backgroundColor = [UIColor blackColor];
TheGeezer
fuente
Funciona para el color de fondo, pero nunca cambia el color del tinte, esto es lo que me confunde un poco
Akhilesh Sharma
0

He creado un método objetivo-C

-(void)customAlertTitle:(NSString*)title message:(NSString*)message{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];

UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 270, 50)];
titleLabel.text = title;
titleLabel.font = [UIFont boldSystemFontOfSize:20];
titleLabel.numberOfLines = 2;
titleLabel.textColor = [UIColor redColor];
titleLabel.textAlignment = NSTextAlignmentCenter;

[subView addSubview:titleLabel];

UILabel *messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 30, 270, 50)];
messageLabel.text = message;
messageLabel.font = [UIFont systemFontOfSize:18];
messageLabel.numberOfLines = 2;
messageLabel.textColor = [UIColor redColor];
messageLabel.textAlignment = NSTextAlignmentCenter;

[subView addSubview:messageLabel];

[alertView setValue:subView forKey:@"accessoryView"];
[alertView show];
}

El código funciona perfectamente en Xcode 8.3.1. Puede personalizar según los requisitos.

Alok
fuente
0

Solo uso este tipo de demanda, aparentemente y el sistema, los detalles son ligeramente diferentes, por lo que estamos ... OC se dio cuenta de la encapsulación de la ventana emergente Alert and Sheet.

A menudo se encuentran en el desarrollo diario la necesidad de agregar una figura a Alert o cambiar un botón de color, como "simple" demanda, hoy trae un sistema de componentes muy similar y puede satisfacer plenamente la demanda de componentes de embalaje personalizados.

Github: https://github.com/ReverseScale/RSCustomAlertView

Tim
fuente