ios - para - Usar fuentes personalizadas en el constructor de interfaz
fuentes personalizadas css (6)
Swizzle a Font
La solución es, en general, sencilla si agita la clase UIFont. Creo que es mejor elegir una fuente sensata como Helvetica Neue y anularla. Esto le permite volver a colocar todo el proyecto en el estándar tirando de la asignación. Ya había logrado un swizzle para lograr este objetivo cuando me di cuenta de que alguien más también lo hizo, así que lo aplasté un poco. Como NSHipster le dirá que el swizzling puede ser peligroso, en este caso el riesgo es bastante bajo considerando la simplicidad absoluta de la API de UIFont. En mi caso, se hizo para una aplicación Enterprise, por lo que fue aún más bajo riesgo.
UIFont + CustomFont.m Categoría
#import <objc/runtime.h>
static NSString *const kFontMapPlist = @"FontMap";
static NSDictionary *_replacementFontDictionary = nil;
@implementation UIFont (CustomFont)
static void initializeReplacementFonts()
{
static BOOL initialized = NO;
if (initialized)
return;
initialized = YES;
// A Plist with a Dictionary from->to font name mapping
NSURL *replacementFontMapURL = [[NSBundle mainBundle] URLForResource:kFontMapPlist withExtension:@"plist"];
NSDictionary *replacementFontMap = [NSDictionary dictionaryWithContentsOfURL:replacementFontMapURL];
[UIFont setReplacementFontDictionary:replacementFontMap];
}
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
initializeReplacementFonts();
SEL fontWithNameSizeSelector = @selector(fontWithName:size:);
SEL swizzledFontWithNameSizeSelector = @selector(clp_fontWithName:size:);
SwizzleClassMethod([UIFont class], fontWithNameSizeSelector, swizzledFontWithNameSizeSelector);
SEL fontWithDescriptorSizeSelector = @selector(fontWithDescriptor:size:);
SEL swizzledfontWithDescriptorSelector = @selector(clp_fontWithDescriptor:size:);
SwizzleClassMethod([UIFont class], fontWithDescriptorSizeSelector, swizzledfontWithDescriptorSelector);
});
}
void SwizzleClassMethod(Class class, SEL originalSelector, SEL replacementSelector)
{
Class clazz = objc_getMetaClass(class_getName(class));
Method originalMethod = class_getClassMethod(clazz, originalSelector);
Method replacementMethod = class_getClassMethod(clazz, replacementSelector);
// Add method if it doesn''t eixst
BOOL didAddMethod =
class_addMethod(clazz,
originalSelector,
method_getImplementation(replacementMethod),
method_getTypeEncoding(replacementMethod));
if (didAddMethod) {
class_replaceMethod(clazz,
replacementSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, replacementMethod);
}
}
#pragma mark - Swizzled font by descriptor and name calls
+ (UIFont *)clp_fontWithDescriptor:(UIFontDescriptor *)descriptor size:(CGFloat)pointSize
{
NSString *originalFontName = descriptor.fontAttributes[UIFontDescriptorNameAttribute];
NSString *replacementFontName = _replacementFontDictionary[originalFontName];
UIFontDescriptor *replacementFontDescriptor = descriptor;
if (replacementFontName != nil) {
replacementFontDescriptor = [UIFontDescriptor fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: replacementFontName}];
}
return [self clp_fontWithDescriptor:replacementFontDescriptor size:pointSize];
}
+ (UIFont *)clp_fontWithName:(NSString *)fontName size:(CGFloat)fontSize
{
NSString *replacementFontName = _replacementFontDictionary[fontName];
if (replacementFontName == nil) {
replacementFontName = fontName;
}
return [self clp_fontWithName:replacementFontName size:fontSize];
}
#pragma mark - Replacement Dictionary Getter and Setter
+ (NSDictionary *)replacementDictionary
{
return _replacementFontDictionary;
}
+ (void)setReplacementFontDictionary:(NSDictionary *)replacmentFontDictionary
{
if (replacmentFontDictionary == _replacementFontDictionary) {
return;
}
_replacementFontDictionary = replacmentFontDictionary;
// Validate font existence.
for (NSString *originalFontName in [_replacementFontDictionary allKeys]) {
NSString *replacementFontName = [_replacementFontDictionary objectForKey:originalFontName];
UIFont *replacementFont = [UIFont fontWithName:replacementFontName size:10.0f];
if (replacementFont == nil) {
DDLogError(@"WARNING: replacement font ''%@'' is not available.", replacementFontName);
}
}
}
@end
The FontMap.plist
En aras de la simplicidad, pretendemos que tenemos una fuente llamada CustomSans.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>HelveticaNeue-Light</key>
<string>CustomSans-Light</string>
<key>HelveticaNeue-LightItalic</key>
<string>CustomSans-LightItalic</string>
<key>HelveticaNeue-Bold</key>
<string>CustomSans-Bold</string>
<key>HelveticaNeue-BoldItalic</key>
<string>CustomSans-BoldItalic</string>
</dict>
</plist>
He buscado en este sitio, pero acabo de encontrar preguntas sin contestar.
He cargado una fuente personalizada en mi proyecto xcode. Un [UIFont fontWithName:@"Laconic-Light" size:19]
funciona. Pero al creador de interfaces no le gusta la fuente. No puedo usarlo con IB, siempre muestra la fuente predeterminada. ¿Hay alguna manera de decirle a IB que está bien usar la fuente?
Otra solución sería subclase UILabel para cargar su fuente personalizada. A continuación, puede hacer referencia en IB, aunque todavía no puede ver la fuente correcta.
Prefiero hacer esto de una manera un poco más genérica, que le permite dimensionar su texto dentro de Interface Builder, y simplemente reemplazar las fuentes en tiempo de ejecución.
Creo una propiedad IBCollection para cualquier elemento UIKit para establecer una fuente, luego conecto los elementos apropiados de IB.
@property (strong, nonatomic) IBOutletCollection(id) NSArray *lightFontItems;
@property (strong, nonatomic) IBOutletCollection(id) NSArray *regularFontItems;
Entonces, desde mi punto de vista, utilicé un método como este:
[self setFontName:@"Roboto-Light" onItemsInArray:[self lightFontItems]];
[self setFontName:@"Roboto-Regular" onItemsInArray:[self regularFontItems]];
Y el método setLightFontOnItemsInArray:
tiene este aspecto:
+ (void)setFontName:(NSString *)fontName onItemsInArray:(NSArray *)array;
{
[array each:^(id item) {
if (![item respondsToSelector:@selector(setFont:)]) return;
[item performSelector:@selector(setFont:) withObject:[UIFont fontWithName:fontName size:[[item font] pointSize]]];
}];
}
Puede instalar este script http://pitaya.ch/moarfonts/ .
Funciona muy bien para mí con xcode 5.1.1.
También tengo este problema en Xcode 4. En mi programa, hay muchos UILabel
que no tienen IBOutlets
así que lo hago de esa manera;
Primero, subclase el UILabel
a CustomFontLabel
Luego, anule el método " awakeFromNib
"
@implementation CustomFontLabel
- (void)awakeFromNib {
[super awakeFromNib];
self.font = [UIFont fontWithName:@"CustomFontName" size:self.font.pointSize];
}
@end
Finalmente, en Interface Builder> Identity Inspector cambia la clase a CustomFontLabel
.