iOS開發備忘筆記 (3)

Hext123發表於2018-06-14

一、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: 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

相關文章