UIButton上的iOS NSAttributedString

我使用的是iOS 6 ,所以属性string应该很容易使用,对吧? 那么…不是那么多。

我想做的事:

使用UIButton的自定义子类(它不会做任何自定义titleLabel ),我想有一个多行,归因的标题是:

  1. 所有大写(我意识到这不是属性的一部分)在第一行
  2. 在第一行粘贴
  3. 在第一行加下划线
  4. 第二行的“正常”重量
  5. 第二行没有下划线
  6. 以两条线为中心

到目前为止,我已经能够获得#1至5(至less,我以为我做了,但是目前的testing正在产生多行文本的错误),但是当我试图做某件事(任何事情!文字要居中,我的应用程序不断崩溃。 当我试图让所有6个项目(通过各种方法)工作,我得到以下崩溃/错误:

 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSAttributedString invalid for autoresizing, it must have a single spanning paragraph style (or none) with a non-wrapping lineBreakMode.' 

根据我所尝试的,似乎我可以有以下选项之一,但不能同时使用这两个选项:

  1. 多线,居中的标签
  2. 归属标签

如果必须的话 ,我可以和其中一个人住在一起,但我不能相信我不能有一个相当直接的概念。

有人可以告诉我我错了什么吗?

这是我正在尝试的代码的最后一个迭代:

 NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; [style setAlignment:NSTextAlignmentCenter]; [style setLineBreakMode:NSLineBreakByWordWrapping]; UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f]; UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f]; NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle), NSFontAttributeName:font1}; NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone), NSFontAttributeName:font2}; NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init]; [attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]]; [attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2" attributes:dict2]]; [[self buttonToStyle] setAttributedTitle:attString forState:UIControlStateNormal]; [[[self buttonToStyle] titleLabel] setNumberOfLines:0]; [[[self buttonToStyle] titleLabel] setLineBreakMode:NSLineBreakByWordWrapping]; 

它看起来像你忘记了在你的代码中使用你设置的“样式”对象..你刚刚实例化它。 你应该修改你的代码如下所示:

 NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; [style setAlignment:NSTextAlignmentCenter]; [style setLineBreakMode:NSLineBreakByWordWrapping]; UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f]; UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f]; NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle), NSFontAttributeName:font1, NSParagraphStyleAttributeName:style}; // Added line NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone), NSFontAttributeName:font2, NSParagraphStyleAttributeName:style}; // Added line NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init]; [attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]]; [attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2" attributes:dict2]]; [self.resolveButton setAttributedTitle:attString forState:UIControlStateNormal]; [[self.resolveButton titleLabel] setNumberOfLines:0]; [[self.resolveButton titleLabel] setLineBreakMode:NSLineBreakByWordWrapping]; 

请注意,我只添加了定义NSParagraphStyleAttributeName的行。其他一切都是一样的..这就是我得到的button:

在这里输入图像说明

这里是在Swift 3.0中

 let style = NSMutableParagraphStyle() style.alignment = .center style.lineBreakMode = .byWordWrapping guard let font1 = UIFont(name: "HelveticaNeue-Medium", size: 20), let font2 = UIFont(name: "HelveticaNeue-Light", size: 20) else { return } let dict1:[String:Any] = [ NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue, NSFontAttributeName:font1, NSParagraphStyleAttributeName:style ] let dict2:[String:Any] = [ NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue, NSFontAttributeName:font2, NSParagraphStyleAttributeName:style ] let attString = NSMutableAttributedString() attString.append(NSAttributedString(string: "LINE 1", attributes: dict1)) attString.append(NSAttributedString(string: "line 2", attributes: dict2)) button.setAttributedTitle(attString, for: .normal) button.titleLabel?.numberOfLines = 0 button.titleLabel?.lineBreakMode = .byWordWrapping 

使用Swift 4,您可以使用下面的UIButton子类实现来解决您的问题:

 import UIKit class CustomButton: UIButton { required init(title: String, subtitle: String) { super.init(frame: CGRect.zero) let style = NSMutableParagraphStyle() style.alignment = NSTextAlignment.center style.lineBreakMode = NSLineBreakMode.byWordWrapping let titleAttributes: [NSAttributedStringKey : Any] = [ NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue, NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.largeTitle), NSAttributedStringKey.paragraphStyle : style ] let subtitleAttributes = [ NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body), NSAttributedStringKey.paragraphStyle : style ] let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes) attributedString.append(NSAttributedString(string: "\n")) attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes)) setAttributedTitle(attributedString, for: UIControlState.normal) titleLabel?.numberOfLines = 0 titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

用法:

 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let button = CustomButton(title: "Title", subtitle: "Subtitle") button.translatesAutoresizingMaskIntoConstraints = false view.addSubview(button) let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor) let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) } } 

作为替代scheme,如果您确实需要systemtypes的button,则可以使用以下代码:

 import UIKit extension UIButton { static func customSystemButton(title: String, subtitle: String) -> UIButton { let style = NSMutableParagraphStyle() style.alignment = NSTextAlignment.center style.lineBreakMode = NSLineBreakMode.byWordWrapping let titleAttributes: [NSAttributedStringKey : Any] = [ NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue, NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.largeTitle), NSAttributedStringKey.paragraphStyle : style ] let subtitleAttributes = [ NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body), NSAttributedStringKey.paragraphStyle : style ] let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes) attributedString.append(NSAttributedString(string: "\n")) attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes)) let button = UIButton(type: UIButtonType.system) button.setAttributedTitle(attributedString, for: UIControlState.normal) button.titleLabel?.numberOfLines = 0 button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping return button } } 

用法:

 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let button = UIButton.customSystemButton(title: "Title", subtitle: "Subtitle") button.translatesAutoresizingMaskIntoConstraints = false view.addSubview(button) let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor) let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor) NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) } } 

下面的两个屏幕截图显示了UIButton子类(左侧)和systemtypesbutton(右侧)的结果显示:

在这里输入图像说明