跳过正文
  1. Posts/

记一个实现UIWindow子类的小坑

··1 分钟

2018.7.19

问题描述
#

项目中为了实现一个全局遮罩界面,使用了一个UIWindow的子类MyWindowMyWindow为了实现回调定义了代理MyWindowDelegate。代码大致如下:

@protocol MyWindowDelegate <NSObject>
@end

@interface MyWindow : UIWindow
@property (nonatomic, assign)id<MyWindowDelegate> delegate;
@end

@implementation MyWindow
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.windowLevel = UIWindowLevelNormal;
        self.backgroundColor = [UIColor whiteColor];
        UIViewController *vc = [[ViewController2 alloc] init];
        self.rootViewController = vc;
        self.hidden = NO;
    }
    return self;
}
@end

然后在实现界面横屏时,发现整个UIWindow不响应横竖屏事件。刚开始以为横竖屏设置被关闭了,查了各种资料,发现这种写法是没有问题的。设置UIWindow的rootViewController,然后把所有子view都加到rootViewController,系统会处理横竖屏问题。

问题分析
#

用Runtime把UIWindow的私有变量打出来,就发现问题了。

#import <objc/runtime.h>

- (void)printUIWindowIvars {
    Ivar *ivars = class_copyIvarList([UIWindow class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        NSLog(@"%s", ivar_getName(ivar));
    }
}

我们看看输出,发现有个私有变量_delegate

MyWindow的属性delegate覆盖了父类UIWindow的变量,导致横竖屏切换事件失效。在代理命名的时候一定要注意啊,delegate看来不是一个好的实践,应该加前缀区分避免覆盖父类的实现,特别是这种私有的变量。

相关文章

一个autoreleasepool的使用场景

··1 分钟
2018.7.18 今天在学习大佬博客的时候看到一个问题,下面代码会有什么问题? // largeNumber是一个很大的数 for (int i = 0; i < largeNumber; i++) { NSString *str = [NSString stringWithFormat:@"hello -%04d", i]; str = [str stringByAppendingString:@" - world"]; NSLog(@"%@", str); } 刚开始没看出什么问题,就是普通的循环,每次循环创建一个局部变量NSString。于是写了个Demo验证了下,在观察内存的时候发现了端倪,在循环过程中,内存不断飙升。

UITabbar自定义Badge

··1 分钟
2018.7.10 tabBarItem的Badge默认样式是带数字的,但是产品要求只要一个小红点,不需要数字,这就需要我们自定义Badge了。 用Reveal分析UITabBar,发现每个按钮是一个UITabBarButton,层级如下:

计算文字长度

··2 分钟
2018.7.9 官方文档 方法定义 # - (NSRect)boundingRectWithSize:(NSSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSAttributedStringKey, id> *)attributes context:(NSStringDrawingContext *)context; 参数定义 # size # 绘制的限制size,计算出来的值不会超过这个大小。

UITextField控制输入长度

··1 分钟
2018.7.6 有些时候会有控制输入框文字长度的需求,记录一个简单的思路。 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (string.length == 0) { return YES; } NSInteger limit = 15; // 文本的最大长度 NSString *newStr = [textField.text stringByAppendingString:string]; // 修改之后的新字符串 NSInteger newStrLength = newStr.length; newStrLength -= [textField textInRange:[textField markedTextRange]].length; // 去掉高亮内容,输入中文拼音的情况 if (newStrLength > limit) { // 处理composed character, 比如emoji NSString *tempStr = [newStr substringWithRange:[newStr rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, limit)]]; textField.text = tempStr; return NO; } return YES; } 有两个坑注意下:

property or synthsize

··1 分钟
记录时间:2018.7.5 @property (nonatomic, retain) NSObject *var; 生成var的set、get方法的方法声明 生成var的set、get方法的实现(早期版本编译器不生成) 生成成员变量_var(早期版本编译器不生成) @synthsize var = _var