• iOS字体适配


    最近项目中,UI要求字体适配屏幕,根据屏幕大小来决定字体大小,因为在大屏手机上字体确实显得小了。因为之前没做过,所以今天抽空研究了一下,还是有一些值得记录的内容

    1. 通过代码设置的字体适配
      代码设置字体,因为已经写过很多地方,不可能一个一个的改,所以使用了method swizzle的方法,用自定义方法替换系统设置字体的方法

      //UIFont+Custom.m
      + (void)load {
          static dispatch_once_t fontToken;
          dispatch_once(&fontToken, ^{
              [self exchangeClassMethod:@selector(systemFontOfSize:) withMethod:@selector(adapterSystemFontOfSize:)];
              [self exchangeClassMethod:@selector(systemFontOfSize:weight:) withMethod:@selector(adapterSystemFontOfSize:weight:)];
              [self exchangeClassMethod:@selector(fontWithName:size:) withMethod:@selector(adapterFontWithName:size:)];
          });
      }
      
      + (UIFont *)adapterSystemFontOfSize:(CGFloat)size {
          CGFloat adapterSize = [self getAdapterFontSize:size];
          return [self adapterSystemFontOfSize:adapterSize];
      }
      
      + (UIFont *)adapterSystemFontOfSize:(CGFloat)size weight:(UIFontWeight)weight {
          CGFloat adapterSize = [self getAdapterFontSize:size];
          return [self adapterSystemFontOfSize:adapterSize weight:weight];
      }
      
      + (UIFont *)adapterFontWithName:(NSString *)name size:(CGFloat)size {
          CGFloat adapterSize = [self getAdapterFontSize:size];
          return [self adapterFontWithName:name size:adapterSize];
      }
      
      //获取适配后的字体大小
      + (CGFloat)getAdapterFontSize:(CGFloat)size {
          CGFloat adapterSize = size;
          if (IS_NOTCH_SCREEN) {
              adapterSize = size + 2;
          } else if (IS_BIG_SCREEN) {
              adapterSize = size + 1;
          } else {
              adapterSize = size;
          }
      //    NSLog(@"size %f, adapter %f", size, adapterSize);
          return adapterSize;
      }
      
    2. 通过xib/storyboard设置的字体适配
      xib/storyboard里面设置的字体都是固定大小的,想要适配不同的屏幕,可以通过两种方式:1.手动设置字体大小,因为上面我们已经替换了uifont的方法,所以在设置的时候就会适配。2.重写awakefromnib方法,在初始化完成后设置自动字体大小。因为已经写了很多页面,不好一个一个修改,所以这里用第二种方法实现

      //UILabel+Custom.m
      + (void)load {
          static dispatch_once_t fontToken;
          dispatch_once(&fontToken, ^{
              [self exchangeInstanceMethod:@selector(awakeFromNib) withMethod:@selector(awakeFromNibAndSetFont)];
          });
      }
      
      - (void)awakeFromNibAndSetFont {
          CGFloat adapterSize = [UIFont getAdapterFontSize:self.font.pointSize];
          self.font = [UIFont fontWithDescriptor:self.font.fontDescriptor size:adapterSize];
          [self awakeFromNibAndSetFont];
      }
      

      同理需要对其他的可以设置字体的空间添加分类,替换awakefromnib方法。我这里使用了UILabel和UITextField两个分类

    3. 遇到的问题及解决
      因为之前写的都是交换实例方法,没写过类方法的交换,所以我直接按着实例方法来写,发现交换不了

      + (void)exchangeClassMethod:(SEL)originSelector withMethod:(SEL)newSelector {
          Class class = self;
          Method originMethod = class_getClassMethod(class, originSelector);
          Method newMethod = class_getClassMethod(class, newSelector);
      
          BOOL addSuccess = class_addMethod(class, originSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
          if (addSuccess) {
              class_replaceMethod(class, newSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
          } else {
              method_exchangeImplementations(originMethod, newMethod);
          }
      }
      

      原来是因为添加方法的时候,添加到了类上,而类方法是在元类里面的,所以导致添加成功但是替换之后没效果。在添加方法的时候改成添加到元类上即可。 因为用到的地方比较多所以对方法替换进行了简单的封装,并添加到NSObject的分类中

      //NSObject+Custom.m
      + (void)exchangeClassMethod:(SEL)originSelector withMethod:(SEL)newSelector {
          Class class = self;
          Method originMethod = class_getClassMethod(class, originSelector);
          Method newMethod = class_getClassMethod(class, newSelector);
      
          //类方法需要添加到类对象的父类-元类上
          BOOL addSuccess = class_addMethod(object_getClass(class), originSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
          if (addSuccess) {
              class_replaceMethod(class, newSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
          } else {
              method_exchangeImplementations(originMethod, newMethod);
          }
      }
      
      + (void)exchangeInstanceMethod:(SEL)originSelector withMethod:(SEL)newSelector {
          Class class = self;
          Method originMethod = class_getInstanceMethod(class, originSelector);
          Method newMethod = class_getInstanceMethod(class, newSelector);
      
          BOOL addSuccess = class_addMethod(class, originSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
          if (addSuccess) {
              class_replaceMethod(class, newSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
          } else {
              method_exchangeImplementations(originMethod, newMethod);
          }
      }
      
    4. 参考链接

  • 相关阅读:
    FILE 创建
    jfreechart折线图 demo
    Win7下Maven的安装与配置
    IntelliJ IDEA 14.x 与 Tomcat 集成,创建并运行Java Web项目
    Java中print、printf、println
    添加SSH密钥到GitHub
    GitHub学习资料
    Windows下Git的安装及配置
    【转】我害怕阅读的人
    安装MongoDB
  • 原文地址:https://www.cnblogs.com/shenyuiOS/p/14232014.html
Copyright © 2020-2023  润新知