一行代码实现UITextView的placeHolder

一行代码实现UITextView的placeHolder
读书无用论的去死.jpg

前言

通过Category一行代码实现UITextView的placeHolder。搭配使用一行代码限制并统计UITextView输入字数效果更佳。

实现效果

一行代码实现UITextView的placeHolder
ZWPlaceHolder+LimitCouner.gif

导入头文件

#import "UITextView+ZWPlaceHolder.h"
  • storyboard(xib)一行调用代码
    self.firstTextView.zw_placeHolder = @"向厂家反馈同业相关活动、产品信息、用于市场分析。";
  • 代码创建UITextView调用
      CGRect rect = CGRectMake(5, 230, [UIScreen mainScreen].bounds.size.width-10, 80);
      UITextView *textView = [[UITextView alloc] initWithFrame:rect];
      textView.layer.borderWidth = 1;
      textView.font = [UIFont systemFontOfSize:14];
      textView.layer.borderColor = [UIColor lightGrayColor].CGColor;
      textView.zw_placeHolder = @"向厂家反馈同业相关活动、产品信息、用于市场分析。";
      [self.view addSubview:textView];
  • 调整placeHolder的字体大小
    • placeholder的字体大小会跟随UITextView字体大小而变化,可以通过调整UITextView的font来调整PlaceHolder字体大小
      textView.font = [UIFont systemFontOfSize:14];
  • 调整placeHolder的字体颜色
    textView.zw_placeHolderColor = [UIColor redColor];

    一行代码实现UITextView的placeHolder
    调整placeHolder字体颜色.png

    实现源码解析

  • 在UITextView的category中通过runtime添加属性zw_placeHolder,当给zw_placeHolder赋值时,去创建一个UILabel添加到UITextView上,然后监听UITextView中text的改变来选择是否显示placeHolder。
  • 核心代码
#pragma mark - update
- (void)updatePlaceHolder{
    if (self.text.length) {
        [self.zw_placeHolderLabel removeFromSuperview];
        return;
    }
    self.zw_placeHolderLabel.font = self.font?self.font:self.cacutDefaultFont;
    self.zw_placeHolderLabel.textAlignment = self.textAlignment;
    self.zw_placeHolderLabel.text = self.zw_placeHolder;
    [self insertSubview:self.zw_placeHolderLabel atIndex:0];
}
#pragma mark - lazzing
-(UILabel *)zw_placeHolderLabel{
    UILabel *placeHolderLab = objc_getAssociatedObject(self, @selector(zw_placeHolderLabel));
    if (!placeHolderLab) {
        placeHolderLab = [[UILabel alloc] init];
        placeHolderLab.numberOfLines = 0;
        placeHolderLab.textColor = [UIColor lightGrayColor];
        objc_setAssociatedObject(self, @selector(zw_placeHolderLabel), placeHolderLab, OBJC_ASSOCIATION_RETAIN);
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceHolder) name:UITextViewTextDidChangeNotification object:self];
    }
    return placeHolderLab;
}
  • 如何避免placeHolder被光标遮挡。
    UITextView的光标默认边距是5.0。
    // Default value: 5.0  The layout padding at the beginning and end of the line fragment rects insetting the layout width available for the contents.  This value is utilized by NSLayoutManager for determining the layout width.
    @property(NS_NONATOMIC_IOSONLY) CGFloat lineFragmentPadding;
    • 所以计算自定义placeHolder的位置需要加上这个边距
  • 关于UITextView的textContainerInset导致文字偏移
    • UITextView可以通过设置textContainerInset来让文字输入区域偏移。
      CGFloat x = lineFragmentPadding + textContainerInset.left + self.layer.borderWidth;

      placeHolder的x坐标 = 光标偏移量+text偏移量+border边框宽度。
      其他坐标同理算得。

如何使用

  • cocoapods导入(搜索不到请更新本地仓库)
    pod   'ZWPlaceHolder'
  • 直接将文件拖入工程中,引入头文件即可
    #import "UITextView+ ZWPlaceHolder.h"

搭配使用

源码

  • 源码放在GitHub上,欢迎指正,记得star哦!

-原文链接-

12、iOS系统内存机制

内存机制特点

  • 有限的可用空间
  • 低内存警告
  • 没有内存交换机制
    就是在内存紧张的时候不会把暂时不用的内存置换到硬盘上,PC机有这个机制
  • 使用虚拟内存机制
    内存分页5kB为一个Page,并不是所有Page都会被映射到内存上,Page有三种状态
    • Nonresident 表明该Page没有映射到内存上
    • Resident and clean 当时readonly文件加载到内存中的Page是clean memory,如framework、可执行文件、通过mmap(内存映射)方式读取的文件都是Resident and clean,就是内存紧张的时候会被unload出去,而需要的时候又load回来
    • Resident and dirty 非clean的page都是dirty,这种内存只有在进程被杀死的时候才能被收回。
      malloc申请的内存如果没用过就是Nonresident状态,用了就是 dirty状态
      mmap进来的文件用了哪哪就是clean状态其他地方是Nonresident状态

-原文链接-