一、iOS应用的 UIWindow

各种方式获取的 window:

[UIApplication sharedApplication].delegate.window; //应用的主线窗体, 大部分情况下都是 keyWindow (用 makeKeyAndVisible 设置), 一般提示弹窗什么的都基于它
[UIApplication sharedApplication].keyWindow; //应用当前的活跃窗口, 一般是 delegate.window , 键盘出来后就是键盘所在的窗体
[UIApplication sharedApplication].windows.lastObject; //最后一个window, 一般是最上层的窗体, 可能是主程序视图, 也可能是键盘或者其他小浮窗什么的

自己新建 window:

  1. window 对象释放 窗口即释放, 所以对象要全局保存
  2. window 设置BackgroundColorclearColor, 或者opaque = NO还是点不到下面的window, 除非设置alpha = 0

二、ALAssetRepresentation 取原图的坑:

ALAssetRepresentation 自带的取图片的方法有两个:

  1. fullScreenImage: 返回一个适合全屏显示的图片 (如果是长图大图则会降低分辨率到屏幕分辨率以下)
  2. fullResolutionImage: 返回原图, 注意了! 如果用自带的"编辑"功能处理过图标, 这里是返回被编辑前的图片.

如果我们想拿到处理后的图片, 但是又是原始分辨率的话, 要先用fullResolutionImage拿到原图, 然后再加上编辑的处理效果, 代码示例如下:

#import "ALAssetRepresentation+Category.h"

@implementation ALAssetRepresentation (Category)
/**
 *  原图(或被iOS自带Photos修改过的图片)
 *
 *  @return 返回原图. 如果被iOS自带Photos编辑过, 则返回编辑后的图.
 */
-(UIImage*)originImage{
    
    // 拿到原图
    CGImageRef fullResImage = [self fullResolutionImage];
    
    // 通过 fullResolutionImage 获取到的的高清图实际上并不带上在照片应用中使用“编辑”处理的效果,需要额外在 AlAssetRepresentation -> metadata -> AdjustmentXMP 中获取这些信息
    NSDictionary * imgInfo = [self metadata];
    NSString *adj = imgInfo[@"AdjustmentXMP"];
    if (adj) {
        // 如果有在照片应用中使用“编辑”效果,则需要获取这些编辑后的滤镜,手工叠加到原图中
        NSData *xmlData = [adj dataUsingEncoding:NSUTF8StringEncoding];
        CIImage *image = [CIImage imageWithCGImage:fullResImage];
        NSError *error = nil;
        NSArray *filters = [CIFilter filterArrayFromSerializedXMP:xmlData
                                                 inputImageExtent:[image extent]
                                                            error:&error];
        CIContext *context = [CIContext contextWithOptions:nil];
        if (filters && !error) {
            for (CIFilter *filter in filters) {
                [filter setValue:image forKey:kCIInputImageKey];
                image = [filter outputImage];
            }
            fullResImage = [context createCGImage:image fromRect:[image extent]];
        }
    }
    UIImage *result = [UIImage imageWithCGImage:fullResImage
                                          scale:[self scale]
                                    orientation:(UIImageOrientation)[self orientation]];
    return result;
}
@end

三、iOS 视图中的各种坐标

  1. Frame: 控件相对于父控件的位置, 和控件在父控件中所占的大小
  2. Bounds: 控件内部空间相对于控件自身的位置, 和控件内部空间的大小.

一般来说, Bounds的值都等于{0,0,Frame.宽,Frame.高}, 但是如果手动设置了一个父控件的Bounds的值, 如{0,0,100,100}设置成了{10,10,100,100}, 那子控件的相对位置就从{10,10}开始了, 就算设置了子控件的Frame{0,0,50,50}, 这个子控件也会与父控件左上有个{10,10}的间距

思考:
UIScrollViewcontentOffsetcontentSizecontentInset 属性会不会也跟 Bounds 有关联和影响


四、synchronizeddispatch_once 区别:

写单例方法时, 我们一般有两种方法:

+ (instancetype)shareInstance1{
    static id instance = nil;
    @synchronized (self) {
        if (!instance) {
            instance = [self new];
        }
    }
    return instance;
}
+ (instancetype)shareInstance2{
    static id instance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        instance = [self new];
    });
    return instance;
}

一般来说用第二种性能更好, 推荐使用


五、NSSet

这两个方法有区别的, 别忽略中间的s而用混了

intersectsSet   // 交集,判断当前集合与指定集合是否有交集
intersectSet    // 交集,返回当前集合与指定集合的交集

六、在tableView didSelectRowAtIndexPath里面弹出框alert弹出来很慢

一个框弹出来大概要两三秒

这个貌似是苹果的bug: http://openradar.appspot.com/19285091

在tableView didSelectRowAtIndexPath里面弹出框慢大概找到3个解决办法 (推荐第三种, 不影响本来的样式和功能):

  1. 不要把selectionStyle设成UITableViewCellSelectionStyleNone (但是设置成default点同一个cell依然会慢, 点不同的cell速度正常, 估计点不同的cell背景变色触发了UI更新)
  2. 第一行加上[tableView deselectRowAtIndexPath:indexPath animated:NO];
  3. 在主队列中异步执行:
dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:ac animated:YES completion:nil];
});


相关问题: 如果把 UIAlertController 保存下来, 下次继续在tableView里面弹出来, 则只有灰色背景, 没有弹框界面了, 也关不了了, 如果点击按钮做这个操作就没问题;

七、dismissViewControllerAnimated 后貌似不会调 viewDidDisappear