天天看點

多年iOS開發經驗總結

1、禁止手機睡眠

2、隐藏某行cell

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 如果是你需要隐藏的那一行,傳回高度為0
    if(indexPath.row == YouWantToHideRow)
        return ; 
    return ;
}

// 然後再你需要隐藏cell的時候調用
[self.tableView beginUpdates];
[self.tableView endUpdates];
           

3、禁用button高亮

button.adjustsImageWhenHighlighted = NO;
或者在建立的時候
 UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
           

4、tableview遇到這種報錯failed to obtain a cell from its dataSource

是因為你的cell被調用的早了。先循環使用了cell,後又建立cell。順序錯了

可能原因:1、xib的cell沒有注冊 2、記憶體中已經有這個cell的緩存了(也就是說通過你的cellId找到的cell并不是你想要的類型),這時候需要改下cell的辨別

5、cocoa pods報這個錯誤:unable to access 'https://github.com/facebook/pop.git/': Operation timed out after 0 milliseconds with 0 out of 0 bytes received

解決辦法:原因可能是網絡問題,網絡請求逾時了,隻需要重試就行了

6、cocoa pods 出現ERROR: While executing gem ... (Errno::EPERM)

解決辦法:

https://segmentfault.com/q/1010000002926243

7、動畫切換window的根控制器

// options是動畫選項
[UIView transitionWithView:[UIApplication sharedApplication].keyWindow duration:f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        BOOL oldState = [UIView areAnimationsEnabled];
        [UIView setAnimationsEnabled:NO];
        [UIApplication sharedApplication].keyWindow.rootViewController = [RootViewController new];
        [UIView setAnimationsEnabled:oldState];
    } completion:^(BOOL finished) {

    }];
           

8、去除數組中重複的對象

9、編譯的時候遇到 no such file or directory: /users/apple/XXX

是因為編譯的時候,在此路徑下找不到這個檔案,解決這個問題,首先是是要檢查缺少的檔案是不是在工程中,如果不在工程中,需要從本地拖進去,如果發現已經存在工程中了,或者拖進去還是報錯,這時候需要去build phases中搜尋這個檔案,這時候很可能會搜出現兩個相同的檔案,這時候,有一個路徑是正确的,删除另外一個即可。如果删除了還是不行,需要把兩個都删掉,然後重新往工程裡拖進這個檔案即可
多年iOS開發經驗總結

build phases

10、iOS8系統中,tableView最好實作下-tableView: heightForRowAtIndexPath:這個代理方法,要不然在iOS8中可能就會出現顯示不全或者無法響應事件的問題

11、iOS8中實作側滑功能的時候這個方法必須實作,要不然在iOS8中無法側滑

// 必須寫的方法,和editActionsForRowAtIndexPath配對使用,裡面什麼不寫也行
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

}
           

12、三個通知

NSSystemTimeZoneDidChangeNotification監聽修改時間界面的兩個按鈕狀态變化

UIApplicationSignificantTimeChangeNotification 監聽使用者改變時間 (隻要點選自動設定按鈕就會調用) NSSystemClockDidChangeNotification 監聽使用者修改時間(時間不同才會調用)

13、SDWebImage本地緩存有時候會害人。如果之前緩存過一張圖檔,即使下次伺服器換了這張圖檔,但是圖檔url沒換,用sdwebimage下載下傳下來的還是以前那張,是以遇到這種問題,不要先去怼伺服器,清空下緩存再試就好了。

14、上線前注意:

1)、删掉代碼中所有的測試代碼

2)、如果背景有稽核模式,提醒背景開啟此模式

3)、主流程再跑一跑

4)、全局搜尋waring,檢查所有标記waring的地方

15、跳進app權限設定

// 跳進app設定
            if (UIApplicationOpenSettingsURLString != NULL) {
                NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                [[UIApplication sharedApplication] openURL:url];
            }
        }
           

16、給一個view截圖

UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, );
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
           

17、開發中如果要動态修改tableView的tableHeaderView或者tableFooterView的高度,需要給tableView重新設定,而不是直接更改高度。正确的做法是重新設定一下tableView.tableFooterView = 更改過高度的view。為什麼?其實在iOS8以上直接改高度是沒有問題的,在iOS8中出現了contentSize不準确的問題,這是解決辦法。

18、注意對象為nil的時候,調用此對象分類的方法不會執行

19、collectionView的内容小于其寬高的時候是不能滾動的,設定可以滾動:

collectionView.alwaysBounceHorizontal = YES;
collectionView.alwaysBounceVertical = YES;
           

20、設定navigationBar上的title顔色和大小

[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor youColor], NSFontAttributeName : [UIFont systemFontOfSize:]}]
           

21、顔色轉圖檔

+ (UIImage *)cl_imageWithColor:(UIColor *)color {
  CGRect rect = CGRectMake(f, f, f, f);
  UIGraphicsBeginImageContext(rect.size);
  CGContextRef context = UIGraphicsGetCurrentContext();

  CGContextSetFillColorWithColor(context, [color CGColor]);
  CGContextFillRect(context, rect);

  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return image;
}
           

22、view設定圓角

#define ViewBorderRadius(View, Radius, Width, Color)\
\
[View.layer setCornerRadius:(Radius)];\
[View.layer setMasksToBounds:YES];\
[View.layer setBorderWidth:(Width)];\
[View.layer setBorderColor:[Color CGColor]] // view圓角
           

23、強/弱引用

#define WeakSelf(type)  weak typeof(type) weak##type = type; // weak
#define StrongSelf(type)  strong typeof(type) type = weak##type; // strong
           

24、由角度轉換弧度

#define DegreesToRadian(x) (M_PI * (x) / )
           

25、由弧度轉換角度

#define RadianToDegrees(radian) (radian*180.)/(M_PI)
           

26、擷取圖檔資源

27、擷取temp

28、擷取沙盒 Document

29、擷取沙盒 Cache

30、GCD代碼隻執行一次

#define kDISPATCH_ONCE_BLOCK(onceBlock) static dispatch_once_t onceToken; dispatch_once(&onceToken, onceBlock);
           

31、自定義NSLog

#ifdef DEBUG
#define NSLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define NSLog(...)
#endif                

32、Font

#define FontL(s)             [UIFont systemFontOfSize:s weight:UIFontWeightLight]
#define FontR(s)             [UIFont systemFontOfSize:s weight:UIFontWeightRegular]
#define FontB(s)             [UIFont systemFontOfSize:s weight:UIFontWeightBold]
#define FontT(s)             [UIFont systemFontOfSize:s weight:UIFontWeightThin]
#define Font(s)              FontL(s)
           

33、FORMAT

#define FORMAT(f, ...)      [NSString stringWithFormat:f, ## __VA_ARGS__]
           

34、在主線程上運作

35、開啟異步線程

36、通知

#define NOTIF_ADD(n, f)     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(f) name:n object:nil]
#define NOTIF_POST(n, o)    [[NSNotificationCenter defaultCenter] postNotificationName:n object:o]
#define NOTIF_REMV()        [[NSNotificationCenter defaultCenter] removeObserver:self]
           

37、随機顔色

+ (UIColor *)RandomColor {
    NSInteger aRedValue = arc4random() % ;
    NSInteger aGreenValue = arc4random() % ;
    NSInteger aBlueValue = arc4random() % ;
    UIColor *randColor = [UIColor colorWithRed:aRedValue / f green:aGreenValue / f blue:aBlueValue / f alpha:f];
    return randColor;
}
           

38、擷取window

+(UIWindow*)getWindow {
    UIWindow* win = nil; //[UIApplication sharedApplication].keyWindow;
    for (id item in [UIApplication sharedApplication].windows) {
        if ([item class] == [UIWindow class]) {
            if (!((UIWindow*)item).hidden) {
                win = item;
                break;
            }
        }
    }
    return win;
}
           

39、修改textField的placeholder的字型顔色、大小

[textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
[textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];                

40、統一收起鍵盤

41、控制螢幕旋轉,在控制器中寫

/** 是否支援自動轉屏 */
- (BOOL)shouldAutorotate {
    return YES;
}

/** 支援哪些螢幕方向 */
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

/** 預設的螢幕方向(目前ViewController必須是通過模态出來的UIViewController(模态帶導航的無效)方式展現出來的,才會調用這個方法) */
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
           

42、擷取app緩存大小

- (CGFloat)getCachSize {

    NSUInteger imageCacheSize = [[SDImageCache sharedImageCache] getSize];
    //擷取自定義緩存大小
    //用枚舉器周遊 一個檔案夾的内容
    //1.擷取 檔案夾枚舉器
    NSString *myCachePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
    NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:myCachePath];
    __block NSUInteger count = ;
    //2.周遊
    for (NSString *fileName in enumerator) {
        NSString *path = [myCachePath stringByAppendingPathComponent:fileName];
        NSDictionary *fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
        count += fileDict.fileSize;//自定義所有緩存大小
    }
    // 得到是位元組  轉化為M
    CGFloat totalSize = ((CGFloat)imageCacheSize+count)//;
    return totalSize;
}
           

43、清理app緩存

- (void)handleClearView {
    //删除兩部分
    //1.删除 sd 圖檔緩存
    //先清除記憶體中的圖檔緩存
    [[SDImageCache sharedImageCache] clearMemory];
    //清除磁盤的緩存
    [[SDImageCache sharedImageCache] clearDisk];
    //2.删除自己緩存
    NSString *myCachePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
    [[NSFileManager defaultManager] removeItemAtPath:myCachePath error:nil];
}
           

44、模型轉字典

static NSSet *classes;

- (NSMutableDictionary *)getParameterDictionary {

    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    Class c = self.class;

    while (c) {
        unsigned count;
        objc_property_t *properties = class_copyPropertyList([c class], &count);

        for (int i = ; i < count; i++) {
            NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
            dict[key] = [self valueForKey:key];
        }
        free(properties);

        // 獲得父類
        c = class_getSuperclass(c);

        if ([self isClassFromFoundation:c]) break;
    }
    return dict;
}

- (BOOL)isClassFromFoundation:(Class)c
{
    if (c == [NSObject class] || c == [NSManagedObject class]) return YES;

    __block BOOL result = NO;
    [[self foundationClasses] enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) {
        if ([c isSubclassOfClass:foundationClass]) {
            result = YES;
            *stop = YES;
        }
    }];
    return result;
}

- (NSSet *)foundationClasses
{
    if (classes == nil) {
        // 集合中沒有NSObject,因為幾乎所有的類都是繼承自NSObject,具體是不是NSObject需要特殊判斷
        classes = [NSSet setWithObjects:
                              [NSURL class],
                              [NSDate class],
                              [NSValue class],
                              [NSData class],
                              [NSError class],
                              [NSArray class],
                              [NSDictionary class],
                              [NSString class],
                              [NSAttributedString class], nil];
    }
    return classes;
}
           

45、交換兩個方法實作

Class aClass = [self class]; 

        SEL originalSelector = @selector(viewWillAppear:); 
        SEL swizzledSelector = @selector(xxx_viewWillAppear:); 

        Method originalMethod = class_getInstanceMethod(aClass, originalSelector); 
        Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector); 

        BOOL didAddMethod = 
            class_addMethod(aClass, 
                originalSelector, 
                method_getImplementation(swizzledMethod), 
                method_getTypeEncoding(swizzledMethod)); 

        if (didAddMethod) { 
            class_replaceMethod(aClass, 
                swizzledSelector, 
                method_getImplementation(originalMethod), 
                method_getTypeEncoding(originalMethod)); 
        } else { 
            method_exchangeImplementations(originalMethod, swizzledMethod); 
        }
           

46、列印百分号和引号

NSLog(@"%%");
    NSLog(@"\"");
           

47、幾個常用權限判斷

if ([CLLocationManager authorizationStatus] ==kCLAuthorizationStatusDenied) {
        NSLog(@"沒有定位權限");
    }
    AVAuthorizationStatus statusVideo = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (statusVideo == AVAuthorizationStatusDenied) {
        NSLog(@"沒有攝像頭權限");
    }
    //是否有麥克風權限
    AVAuthorizationStatus statusAudio = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    if (statusAudio == AVAuthorizationStatusDenied) {
        NSLog(@"沒有錄音權限");
    }
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        if (status == PHAuthorizationStatusDenied) {
            NSLog(@"沒有相冊權限");
        }
    }];
           

48、擷取手機型号

+ (NSString *)getDeviceInfo {
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
    if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G";
    if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
    if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
    if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c";
    if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c";
    if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s";
    if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s";
    if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
    if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
    if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";
    if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";
    // 日行兩款手機型号均為日本獨占,可能使用索尼FeliCa支付方案而不是蘋果支付
    if ([platform isEqualToString:@"iPhone9,1"])    return @"國行、日版、港行iPhone 7";
    if ([platform isEqualToString:@"iPhone9,2"])    return @"港行、國行iPhone 7 Plus";
    if ([platform isEqualToString:@"iPhone9,3"])    return @"美版、台版iPhone 7";
    if ([platform isEqualToString:@"iPhone9,4"])    return @"美版、台版iPhone 7 Plus";
    if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE";
    if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPad1,1"]) return @"iPad 1G";
    if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2";
    if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2";
    if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2";
    if ([platform isEqualToString:@"iPad2,4"]) return @"iPad 2";
    if ([platform isEqualToString:@"iPad2,5"]) return @"iPad Mini 1G";
    if ([platform isEqualToString:@"iPad2,6"]) return @"iPad Mini 1G";
    if ([platform isEqualToString:@"iPad2,7"]) return @"iPad Mini 1G";
    if ([platform isEqualToString:@"iPad3,1"]) return @"iPad 3";
    if ([platform isEqualToString:@"iPad3,2"]) return @"iPad 3";
    if ([platform isEqualToString:@"iPad3,3"]) return @"iPad 3";
    if ([platform isEqualToString:@"iPad3,4"]) return @"iPad 4";
    if ([platform isEqualToString:@"iPad3,5"]) return @"iPad 4";
    if ([platform isEqualToString:@"iPad3,6"]) return @"iPad 4";
    if ([platform isEqualToString:@"iPad4,1"]) return @"iPad Air";
    if ([platform isEqualToString:@"iPad4,2"]) return @"iPad Air";
    if ([platform isEqualToString:@"iPad4,3"]) return @"iPad Air";
    if ([platform isEqualToString:@"iPad4,4"]) return @"iPad Mini 2G";
    if ([platform isEqualToString:@"iPad4,5"]) return @"iPad Mini 2G";
    if ([platform isEqualToString:@"iPad4,6"]) return @"iPad Mini 2G";
    if ([platform isEqualToString:@"i386"]) return @"iPhone Simulator";
    if ([platform isEqualToString:@"x86_64"]) return @"iPhone Simulator";
    return platform;
}
           

49、長按複制功能

- (void)viewDidLoad
{
    [self.view addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pasteBoard:)]];
}
- (void)pasteBoard:(UILongPressGestureRecognizer *)longPress {
    if (longPress.state == UIGestureRecognizerStateBegan) {
        UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
        pasteboard.string = @"需要複制的文本";
    }
}
           

50、cocoapods更新

在終端執行 sudo gem install -n / usr / local / bin cocoapods --pre

51、設定啟動頁後,依然顯示之前的

删除app,手機重新開機,重新安裝

52、判斷圖檔類型

//通過圖檔Data資料第一個位元組 來擷取圖檔擴充名
- (NSString *)contentTypeForImageData:(NSData *)data
{
    uint8_t c;
    [data getBytes:&c length:];
    switch (c)
    {
        case :
            return @"jpeg";

        case :
            return @"png";

        case :
            return @"gif";

        case :
        case :
            return @"tiff";

        case :
        if ([data length] < ) {
            return nil;
        }

        NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(, )] encoding:NSASCIIStringEncoding];
        if ([testString hasPrefix:@"RIFF"]
            && [testString hasSuffix:@"WEBP"])
        {
            return @"webp";
        }

        return nil;
    }

    return nil;
}
           

53、擷取手機和app資訊

NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];  
 CFShow(infoDictionary);  
// app名稱  
 NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"];  
 // app版本  
 NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];  
 // app build版本  
 NSString *app_build = [infoDictionary objectForKey:@"CFBundleVersion"];  



    //手機序列号  
    NSString* identifierNumber = [[UIDevice currentDevice] uniqueIdentifier];  
    NSLog(@"手機序列号: %@",identifierNumber);  
    //手機别名: 使用者定義的名稱  
    NSString* userPhoneName = [[UIDevice currentDevice] name];  
    NSLog(@"手機别名: %@", userPhoneName);  
    //裝置名稱  
    NSString* deviceName = [[UIDevice currentDevice] systemName];  
    NSLog(@"裝置名稱: %@",deviceName );  
    //手機系統版本  
    NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];  
    NSLog(@"手機系統版本: %@", phoneVersion);  
    //手機型号  
    NSString* phoneModel = [[UIDevice currentDevice] model];  
    NSLog(@"手機型号: %@",phoneModel );  
    //地方型号  (國際化區域名稱)  
    NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];  
    NSLog(@"國際化區域名稱: %@",localPhoneModel );  

    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];  
    // 目前應用名稱  
    NSString *appCurName = [infoDictionary objectForKey:@"CFBundleDisplayName"];  
    NSLog(@"目前應用名稱:%@",appCurName);  
    // 目前應用軟體版本  比如:1.0.1  
    NSString *appCurVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];  
    NSLog(@"目前應用軟體版本:%@",appCurVersion);  
    // 目前應用版本号碼   int類型  
    NSString *appCurVersionNum = [infoDictionary objectForKey:@"CFBundleVersion"];  
    NSLog(@"目前應用版本号碼:%@",appCurVersionNum);
           

54、擷取一個類的所有屬性

id LenderClass = objc_getClass("Lender");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount);
for (i = ; i < outCount; i++) {
    objc_property_t property = properties[i];
    fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
           

55、image圓角

- (UIImage *)circleImage
{
    // NO代表透明
    UIGraphicsBeginImageContextWithOptions(self.size, NO, );
    // 獲得上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 添加一個圓
    CGRect rect = CGRectMake(, , self.size.width, self.size.height);
    // 方形變圓形
    CGContextAddEllipseInRect(ctx, rect);
    // 裁剪
    CGContextClip(ctx);
    // 将圖檔畫上去
    [self drawInRect:rect];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
           

56、image拉伸

+ (UIImage *)resizableImage:(NSString *)imageName
{
    UIImage *image = [UIImage imageNamed:imageName];
    CGFloat imageW = image.size.width;
    CGFloat imageH = image.size.height;
    return [image resizableImageWithCapInsets:UIEdgeInsetsMake(imageH * , imageW * , imageH * , imageW * ) resizingMode:UIImageResizingModeStretch];
}
           

57、JSON字元串轉字典

+ (NSDictionary *)parseJSONStringToNSDictionary:(NSString *)JSONString {
    NSData *JSONData = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableLeaves error:nil];
    return responseJSON;
}
           

58、身份證号驗證

- (BOOL)validateIdentityCard {
    BOOL flag;
    if (self.length <= ) {
        flag = NO;
        return flag;
    }
    NSString *regex2 = @"^(\\d{14}|\\d{17})(\\d|[xX])$";
    NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
    return [identityCardPredicate evaluateWithObject:self];
}
           

59、擷取裝置mac位址

+ (NSString *)macAddress {
    int                 mib[];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[] = CTL_NET;
    mib[] = AF_ROUTE;
    mib[] = ;
    mib[] = AF_LINK;
    mib[] = NET_RT_IFLIST;

    if((mib[] = if_nametoindex("en0")) == ) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if(sysctl(mib, , NULL, &len, NULL, ) < ) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. Rrror!\n");
        return NULL;
    }

    if(sysctl(mib, , buf, &len, NULL, ) < ) {
        printf("Error: sysctl, take 2");
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + );
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
                           *ptr, *(ptr+), *(ptr+), *(ptr+), *(ptr+), *(ptr+)];
    free(buf);

    return outstring;
}                

60、導入自定義字型庫

1、找到你想用的字型的 ttf 格式,拖入工程

2、在工程的plist中增加一行數組,“Fonts provided by application”

3、為這個key添加一個item,value為你剛才導入的ttf檔案名

4、直接使用即可:label.font = [UIFont fontWithName:@"你剛才導入的ttf檔案名" size:20.0];

61、拿到目前正在顯示的控制器,不管是push進去的,還是present進去的都能拿到

- (UIViewController *)getVisibleViewControllerFrom:(UIViewController*)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self getVisibleViewControllerFrom:[((UINavigationController*) vc) visibleViewController]];
    }else if ([vc isKindOfClass:[UITabBarController class]]){
        return [self getVisibleViewControllerFrom:[((UITabBarController*) vc) selectedViewController]];
    } else {
        if (vc.presentedViewController) {
            return [self getVisibleViewControllerFrom:vc.presentedViewController];
        } else {
            return vc;
        }
    }
}
           

62、runtime為一個類動态添加屬性

// 動态添加屬性的本質是: 讓對象的某個屬性與值産生關聯
        objc_setAssociatedObject(self, WZBPlaceholderViewKey, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
           

63、擷取runtime為一個類動态添加的屬性

64、KVO監聽某個對象的屬性

// 添加監聽者
[self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];

// 當監聽的屬性值變化的時候會來到這個方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"property"]) {
       [self textViewTextChange];
       } else {
     }
}
           

65、Reachability判斷網絡狀态

NetworkStatus status = [[Reachability reachabilityForInternetConnection] currentReachabilityStatus];
    if (status == NotReachable) {
        NSLog(@"目前裝置無網絡");
    }
    if (status == ReachableViaWiFi) {
        NSLog(@"目前wifi網絡");
    }
    if (status == NotReachable) {
        NSLog(@"目前蜂窩移動網絡");
    }
           

66、AFNetworking監聽網絡狀态

// 監聽網絡狀況
    AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
    [mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
                break;
            case AFNetworkReachabilityStatusNotReachable: {
                [SVProgressHUD showInfoWithStatus:@"目前裝置無網絡"];
            }
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                [SVProgressHUD showInfoWithStatus:@"目前Wi-Fi網絡"];
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                [SVProgressHUD showInfoWithStatus:@"目前蜂窩移動網絡"];
                break;
            default:
                break;
        }
    }];
    [mgr startMonitoring];
           

67、透明顔色不影響子視圖透明度

68、取圖檔某一點的顔色

if (point.x <  || point.y < ) return nil;

    CGImageRef imageRef = self.CGImage;
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    if (point.x >= width || point.y >= height) return nil;

    unsigned char *rawData = malloc(height * width * );
    if (!rawData) return nil;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSUInteger bytesPerPixel = ;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = ;
    CGContextRef context = CGBitmapContextCreate(rawData,
                                                 width,
                                                 height,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast
                                                 | kCGBitmapByteOrder32Big);
    if (!context) {
        free(rawData);
        return nil;
    }
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(, , width, height), imageRef);
    CGContextRelease(context);

    int byteIndex = (bytesPerRow * point.y) + point.x * bytesPerPixel;
    CGFloat red   = (rawData[byteIndex]     * ) / ;
    CGFloat green = (rawData[byteIndex + ] * ) / ;
    CGFloat blue  = (rawData[byteIndex + ] * ) / ;
    CGFloat alpha = (rawData[byteIndex + ] * ) / ;

    UIColor *result = nil;
    result = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    free(rawData);
    return result;
           

69、判斷該圖檔是否有透明度通道

- (BOOL)hasAlphaChannel
{
    CGImageAlphaInfo alpha = CGImageGetAlphaInfo(self.CGImage);
    return (alpha == kCGImageAlphaFirst ||
            alpha == kCGImageAlphaLast ||
            alpha == kCGImageAlphaPremultipliedFirst ||
            alpha == kCGImageAlphaPremultipliedLast);
}
           

70、獲得灰階圖

+ (UIImage*)covertToGrayImageFromImage:(UIImage*)sourceImage
{
    int width = sourceImage.size.width;
    int height = sourceImage.size.height;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef context = CGBitmapContextCreate (nil,width,height,,,colorSpace,kCGImageAlphaNone);
    CGColorSpaceRelease(colorSpace);

    if (context == NULL) {
        return nil;
    }

    CGContextDrawImage(context,CGRectMake(, , width, height), sourceImage.CGImage);
    CGImageRef contextRef = CGBitmapContextCreateImage(context);
    UIImage *grayImage = [UIImage imageWithCGImage:contextRef];
    CGContextRelease(context);
    CGImageRelease(contextRef);

    return grayImage;
}
           

71、根據bundle中的檔案名讀取圖檔

+ (UIImage *)imageWithFileName:(NSString *)name {
    NSString *extension = @"png";

    NSArray *components = [name componentsSeparatedByString:@"."];
    if ([components count] >= ) {
        NSUInteger lastIndex = components.count - ;
        extension = [components objectAtIndex:lastIndex];

        name = [name substringToIndex:(name.length-(extension.length+))];
    }

    // 如果為Retina螢幕且存在對應圖檔,則傳回Retina圖檔,否則查找普通圖檔
    if ([UIScreen mainScreen].scale == ) {
        name = [name stringByAppendingString:@"@2x"];

        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
        if (path != nil) {
            return [UIImage imageWithContentsOfFile:path];
        }
    }

    if ([UIScreen mainScreen].scale == ) {
        name = [name stringByAppendingString:@"@3x"];

        NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
        if (path != nil) {
            return [UIImage imageWithContentsOfFile:path];
        }
    }

    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:extension];
    if (path) {
        return [UIImage imageWithContentsOfFile:path];
    }

    return nil;
}
           

72、合并兩個圖檔

+ (UIImage*)mergeImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
    CGImageRef firstImageRef = firstImage.CGImage;
    CGFloat firstWidth = CGImageGetWidth(firstImageRef);
    CGFloat firstHeight = CGImageGetHeight(firstImageRef);
    CGImageRef secondImageRef = secondImage.CGImage;
    CGFloat secondWidth = CGImageGetWidth(secondImageRef);
    CGFloat secondHeight = CGImageGetHeight(secondImageRef);
    CGSize mergedSize = CGSizeMake(MAX(firstWidth, secondWidth), MAX(firstHeight, secondHeight));
    UIGraphicsBeginImageContext(mergedSize);
    [firstImage drawInRect:CGRectMake(, , firstWidth, firstHeight)];
    [secondImage drawInRect:CGRectMake(, , secondWidth, secondHeight)];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
           

73、根據bundle中的圖檔名建立imageview

+ (id)imageViewWithImageNamed:(NSString*)imageName
{
    return [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
}
           

74、為imageView添加倒影

CGRect frame = self.frame;
    frame.origin.y += (frame.size.height + );

    UIImageView *reflectionImageView = [[UIImageView alloc] initWithFrame:frame];
    self.clipsToBounds = TRUE;
    reflectionImageView.contentMode = self.contentMode;
    [reflectionImageView setImage:self.image];
    reflectionImageView.transform = CGAffineTransformMakeScale(, );

    CALayer *reflectionLayer = [reflectionImageView layer];

    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.bounds = reflectionLayer.bounds;
    gradientLayer.position = CGPointMake(reflectionLayer.bounds.size.width / , reflectionLayer.bounds.size.height * );
    gradientLayer.colors = [NSArray arrayWithObjects:
                            (id)[[UIColor clearColor] CGColor],
                            (id)[[UIColor colorWithRed: green: blue: alpha:] CGColor], nil];

    gradientLayer.startPoint = CGPointMake(,);
    gradientLayer.endPoint = CGPointMake(,);
    reflectionLayer.mask = gradientLayer;

    [self.superview addSubview:reflectionImageView];
           

75、畫水印

// 畫水印
- (void) setImage:(UIImage *)image withWaterMark:(UIImage *)mark inRect:(CGRect)rect
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= )
    {
        UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, );
    }
    //原圖
    [image drawInRect:self.bounds];
    //水印圖
    [mark drawInRect:rect];
    UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    self.image = newPic;
}
           

76、讓label的文字内容顯示在左上/右上/左下/右下/中心頂/中心底部

自定義UILabel
// 重寫label的textRectForBounds方法
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
    CGRect rect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
    switch (self.textAlignmentType) {
        case WZBTextAlignmentTypeLeftTop: {
            rect.origin = bounds.origin;
        }
            break;
        case WZBTextAlignmentTypeRightTop: {
            rect.origin = CGPointMake(CGRectGetMaxX(bounds) - rect.size.width, bounds.origin.y);
        }
            break;
        case WZBTextAlignmentTypeLeftBottom: {
            rect.origin = CGPointMake(bounds.origin.x, CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeRightBottom: {
            rect.origin = CGPointMake(CGRectGetMaxX(bounds) - rect.size.width, CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeTopCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / , CGRectGetMaxY(bounds) - rect.origin.y);
        }
            break;
        case WZBTextAlignmentTypeBottomCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / , CGRectGetMaxY(bounds) - CGRectGetMaxY(bounds) - rect.size.height);
        }
            break;
        case WZBTextAlignmentTypeLeft: {
            rect.origin = CGPointMake(, rect.origin.y);
        }
            break;
        case WZBTextAlignmentTypeRight: {
            rect.origin = CGPointMake(rect.origin.x, );
        }
            break;
        case WZBTextAlignmentTypeCenter: {
            rect.origin = CGPointMake((CGRectGetWidth(bounds) - CGRectGetWidth(rect)) / , (CGRectGetHeight(bounds) - CGRectGetHeight(rect)) / );
        }
            break;

        default:
            break;
    }
    return rect;
}
- (void)drawTextInRect:(CGRect)rect {
    CGRect textRect = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:textRect];
}
           

77、scrollView上的輸入框,鍵盤擋住的問題

推薦用IQKeyboardManager這個架構!
手動解決如下
、監聽鍵盤彈出/消失的通知
、在通知中加入代碼:
NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}
           

78、frame布局的cell動态高度

這種通常在你的模型中添加一個輔助屬性cellHeight,在模型中重寫這個屬性的get方法,根據你的布局和模型中的其他屬性值計算出總高度。最後在tableView:heightForRow方法中,根據indexPath找出對應的模型,傳回這個高度即可。

79、AutoLayout布局的cell動态高度

// 1、設定tableView的屬性
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = ; // 這個屬性非0,估計cell高度
           
// 、至上而下設定cell的限制,注意,上下左右最好都要頂到cell的四周
           
多年iOS開發經驗總結

cell

80、使用performSelector:調用函數,記憶體洩漏問題

當我們在開發中使用[obj performSelector:NSSelectorFromString(@"aMethod")];這類方法時可能會收到一個警告"performSelector may cause a leak because its selector is unknown".

是因為編譯器不清楚這個對象能不能相應這個方法,如果不能,則是不安全的,而且編譯器也不清楚該怎麼處理這個方法的傳回值!

使用以下代碼調用即可:
if (! obj) { return; }
SEL selector = NSSelectorFromString(@"aMethod");
IMP imp = [obj methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;
func(obj, selector);

或者:
SEL selector = NSSelectorFromString(@"aMethod");
((void (*)(id, SEL))[obj methodForSelector:selector])(obj, selector);
           

81、一個字元串是否包含另一個字元串

// 方法1
if ([str1 containsString:str2]) {
        NSLog(@"str1包含str2");
    } else {
        NSLog(@"str1不包含str2");
    }

// 方法2
if ([str1 rangeOfString: str2].location == NSNotFound) {
        NSLog(@"str1包含str2");
    } else {
        NSLog(@"str1不包含str2");
    }
           

82、cell去除選中效果

83、cell點按效果

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
           

84、當删除一個從xib拖出來的屬性時,一定記得把xib中對應的線也删掉,不然會報類似[<ViewController 0x7fea6ed05980> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key的crash

多年iOS開發經驗總結

點選這個叉号删除

85、真機測試的時候報錯:Could not launch "你的 App",process launch failed: Security

因為你的app沒有上線,iOS9開始,需要手動信任Xcode生成的描述檔案,打開手機設定->通用->描述檔案->點選你的app的描述檔案->點選信任

86、真機測試的時候報錯:Could not find Developer Disk Image

這是因為你的裝置系統版本大于Xcode能相容的系統版本,比如你的裝置是iOS10.3,而Xcode版本是8.2(Xcode8.2最大相容iOS10.2),就會報這個錯誤。解決辦法就是更新Xcode!

87、UITextView沒有placeholder的問題?

網上有很多此類自定義控件,也可以參考下我寫的一個UITextView分類 UITextView-WZB

88、移除字元串中的空格和換行

+ (NSString *)removeSpaceAndNewline:(NSString *)str {
    NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
    temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    return temp;
}
           

89、判斷字元串中是否有空格

+ (BOOL)isBlank:(NSString *)str {
    NSRange _range = [str rangeOfString:@" "];
    if (_range.location != NSNotFound) {
        //有空格
        return YES;
    } else {
        //沒有空格
        return NO;
    }
}
           

90、擷取一個視訊的第一幀圖檔

NSURL *url = [NSURL URLWithString:filepath];
    AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:url options:nil];
    AVAssetImageGenerator *generate1 = [[AVAssetImageGenerator alloc] initWithAsset:asset1];
    generate1.appliesPreferredTrackTransform = YES;
    NSError *err = NULL;
    CMTime time = CMTimeMake(, );
    CGImageRef oneRef = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err];
    UIImage *one = [[UIImage alloc] initWithCGImage:oneRef];

    return one;
           

91、擷取視訊的時長

+ (NSInteger)getVideoTimeByUrlString:(NSString *)urlString {
    NSURL *videoUrl = [NSURL URLWithString:urlString];
    AVURLAsset *avUrl = [AVURLAsset assetWithURL:videoUrl];
    CMTime time = [avUrl duration];
    int seconds = ceil(time.value/time.timescale);
    return seconds;
}
           

92、字元串是否為空

+ (BOOL)isEqualToNil:(NSString *)str {
    return str.length <=  || [str isEqualToString:@""] || !str;
}
           

93、将app上傳到App Store的時候通常會遇到這個問題

多年iOS開發經驗總結

try again

很多人說這事蘋果爸爸伺服器問題,重複嘗試幾次,總會成功的!

但是經過嘗試發現如果使用Application Loader上傳成功率就非常高,是以還是推薦把ipa檔案導出直接用Application Loader上傳。

如果Application Loader也不行,需要檢查下自己的網絡,有時候vpn也會提高速度。

94、當tableView占不滿一屏時,去除下邊多餘的單元格

self.tableView.tableHeaderView = [UIView new];
self.tableView.tableFooterView = [UIView new];
           

95、isKindOfClass和isMemberOfClass的差別

isKindOfClass可以判斷某個對象是否屬于某個類,或者這個類的子類。
isMemberOfClass更加精準,它隻能判斷這個對象類型是否為這個類(不能判斷子類)
           

96、__block

當一個局部變量需要在block裡改變時,需要在定義時加上__block修飾,具體請看官方文檔http://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

97、-[ViewController aMethod:]: unrecognized selector sent to instance 0x7fe91e607fb0

這是一個經典錯誤,ViewController不能響應aMethod這個方法,錯誤原因可能viewController檔案中沒有實作aMethod這個方法

98、UITableView (<UITableView: 0x7ff19b027000; >) failed to obtain a cell from its dataSource (<ViewController: 0x7ff19a507520>)

這個錯誤原因是tableView的代理方法-tableView:cellForRowAtIndexPath:需要傳回一個UITableViewCell,而你傳回了一個nil。另外這個地方傳回值不是UITableViewCell類型也會導緻崩潰

99、限制如何做UIView動畫?

、把需要改的限制Constraint拖條線出來,成為屬性
、在需要動畫的地方加入代碼,改變此屬性的constant屬性
、開始做UIView動畫,動畫裡邊調用layoutIfNeeded方法

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *buttonTopConstraint;
self.buttonTopConstraint.constant = ;
    [UIView animateWithDuration: animations:^{
        [self.view layoutIfNeeded];
    }];
           

100、從NSURL中拿到連結字元串

101、将tableView滾動到頂部

[tableView setContentOffset:CGPointZero animated:YES];
或者
[tableView scrollRectToVisible:CGRectMake(, , , ) animated:YES];
           

102、如果用addTarget:action:forControlEvents:方法為一個button添加了很多點選事件,在某個時刻想一次删除怎麼辦?隻需要調用下邊這句代碼

[youButton removeTarget:nil action:nil forControlEvents:UIControlEventAllEvents];
           

103、某個字型的高度

104、删除某個view所有的子視圖

[[someView subviews]
 makeObjectsPerformSelector:@selector(removeFromSuperview)];
           

105、删除NSUserDefaults所有記錄

//方法一
  NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
 [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];   
 //方法二  
- (void)resetDefaults {   
  NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
     NSDictionary * dict = [defs dictionaryRepresentation];
     for (id key in dict) {
          [defs removeObjectForKey:key];
     }
      [defs synchronize];
 }
// 方法三
[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];
           

106、禁用系統滑動傳回功能

- (void)viewDidAppear:(BOOL)animated
{
     [super viewDidAppear:animated];
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
     return NO;
}
           

107、模拟器報錯

多年iOS開發經驗總結

模拟器報錯

解決辦法:

打開模拟器->Simulator->Reset Content and Settings...

如果不行,就重新開機試試!

108、自定義cell選中背景顔色

UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor redColor];
[cell setSelectedBackgroundView:bgColorView];
           

109、UILabel設定内邊距

子類化UILabel,重寫drawTextInRect方法
- (void)drawTextInRect:(CGRect)rect {
    // 邊距,上左下右
    UIEdgeInsets insets = {, , , };
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
           

110、UILabel設定文字描邊

子類化UILabel,重寫drawTextInRect方法
- (void)drawTextInRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();
    // 設定描邊寬度
    CGContextSetLineWidth(c, );
    CGContextSetLineJoin(c, kCGLineJoinRound);
    CGContextSetTextDrawingMode(c, kCGTextStroke);
    // 描邊顔色
    self.textColor = [UIColor redColor];
    [super drawTextInRect:rect];
    // 文本顔色
    self.textColor = [UIColor yellowColor];
    CGContextSetTextDrawingMode(c, kCGTextFill);
    [super drawTextInRect:rect];
}
           

111、使用模拟器截圖

快捷鍵command + s

或者File->Save Screen Shot

112、scrollView滾動到最下邊

CGPoint bottomOffset = CGPointMake(, scrollView.contentSize.height - scrollView.bounds.size.height);
[scrollView setContentOffset:bottomOffset animated:YES];
           

113、UIView背景顔色漸變

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
    [self.view addSubview:view];
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = view.bounds;
    gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
    [view.layer insertSublayer:gradient atIndex:];
           

114、停止UIView動畫

[yourView.layer removeAllAnimations]
           

115、為UIView某個角添加圓角

// 左上角和右下角添加圓角
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(, )];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = view.bounds;
    maskLayer.path = maskPath.CGPath;
    view.layer.mask = maskLayer;
           

116、删除Xcode Derived data緩存資料

依次點選Xcode -> Preferences -> location,然後點選 Derived data路徑後到小箭頭,删除這個檔案夾下的資料就可以了,如圖
多年iOS開發經驗總結
Xcode Derived data

117、将一個view放置在其兄弟視圖的最上面

[parentView bringSubviewToFront:yourView]
           

118、将一個view放置在其兄弟視圖的最下面

[parentView sendSubviewToBack:yourView]
           

119、讓手機震動一下

倒入架構
#import <AudioToolbox/AudioToolbox.h>
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
或者
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
           

120、layoutSubviews方法什麼時候調用?

1、init方法不會調用

2、addSubview方法等時候會調用

3、bounds改變的時候調用

4、scrollView滾動的時候會調用scrollView的layoutSubviews方法(是以不建議在scrollView的layoutSubviews方法中做複雜邏輯)

5、旋轉裝置的時候調用

6、子視圖被移除的時候調用

參考請看:http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/

121、讓UILabel在指定的地方換行

// 換行符為\n,在需要換行的地方加上這個符号即可,如 
label.numberOfLines = 0;
label.text = @"此處\n換行";
           

122、搖一搖功能

、打開搖一搖功能
    [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
、讓需要搖動的控制器成為第一響應者
[self becomeFirstResponder];
、實作以下方法

// 開始搖動
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
// 取消搖動
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
// 搖動結束
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
           

123、擷取圖檔大小

CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = imageWidth * image.scale;
           

124、擷取view的坐标在整個window上的位置

// v上的(0, 0)點在toView上的位置
CGPoint point = [v convertPoint:CGPointMake(, ) toView:[UIApplication sharedApplication].windows.lastObject];
或者
CGPoint point = [v.superview convertPoint:v.frame.origin toView:[UIApplication sharedApplication].windows.lastObject];
           

125、送出App Store稽核程式限制

您的應用程式的未壓縮大小必須小于4GB。每個Mach-O可執行檔案(例如app_name.app/app_name)不能超過這些限制:

對于MinimumOSVersion小于7.0的應用程式:TEXT二進制檔案中所有部分的總數最多為80 MB 。

對于MinimumOSVersion7.x到8.x的應用程式:TEXT對于二進制檔案中每個體系結構片段的每個片段,最大為60 MB 。

對于MinimumOSVersion9.0或更高版本的應用程式:__TEXT二進制檔案中所有部分的總數最多為500 MB 。參閱:iTunes Connect開發者指南

126、修改UISegmentedControl的字型大小

[segment setTitleTextAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:f]} forState:UIControlStateNormal];
           

127、在非ViewController的地方彈出UIAlertController對話框

//  最好抽成一個分類
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
//...
id rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
if([rootViewController isKindOfClass:[UINavigationController class]])
{
    rootViewController = ((UINavigationController *)rootViewController).viewControllers.firstObject;
}
if([rootViewController isKindOfClass:[UITabBarController class]])
{
    rootViewController = ((UITabBarController *)rootViewController).selectedViewController;
}
[rootViewController presentViewController:alertController animated:YES completion:nil];
           

128、擷取一個view所屬的控制器

// view分類方法
- (UIViewController *)belongViewController {
    for (UIView *next = [self superview]; next; next = next.superview) {
        UIResponder* nextResponder = [next nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)nextResponder;
        }
    }
    return nil;
}
           

129、UIImage和base64互轉

// view分類方法
- (NSString *)encodeToBase64String:(UIImage *)image {
 return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}

- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData {
  NSData *data = [[NSData alloc]initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters];
  return [UIImage imageWithData:data];
}
           

130、UIWebView設定背景透明

[webView setBackgroundColor:[UIColor clearColor]];
[webView setOpaque:NO];
           

131、判斷NSDate是不是今天

NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
   [today month] == [otherDay month] &&
   [today year] == [otherDay year] &&
   [today era] == [otherDay era]) {
    // 是今天
}
           

132、設定tableView分割線顔色

[self.tableView setSeparatorColor:[UIColor myColor]];
           

133、設定螢幕方向

134、比較兩個顔色是否相等

- (BOOL)isEqualToColor:(UIColor *)otherColor {
    CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();

    UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color) {
        if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome) {
            const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
            CGFloat components[] = {oldComponents[], oldComponents[], oldComponents[], oldComponents[]};
            CGColorRef colorRef = CGColorCreate( colorSpaceRGB, components );

            UIColor *color = [UIColor colorWithCGColor:colorRef];
            CGColorRelease(colorRef);
            return color;            
        } else
            return color;
    };

    UIColor *selfColor = convertColorToRGBSpace(self);
    otherColor = convertColorToRGBSpace(otherColor);
    CGColorSpaceRelease(colorSpaceRGB);

    return [selfColor isEqual:otherColor];
}
           

135、tableViewCell分割線頂到頭

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [cell setSeparatorInset:UIEdgeInsetsZero];
    [cell setLayoutMargins:UIEdgeInsetsZero];
    cell.preservesSuperviewLayoutMargins = NO;
}

- (void)viewDidLayoutSubviews {
    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    [self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
           

136、不讓控制器的view随着控制器的xib拉伸或壓縮

self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
           

137、cocoaPods報錯 : [!] Unable to add a source with url 

https://github.com/CocoaPods/Specs.git

 named 

master-1

.

You can try adding it manually in 

~/.cocoapods/repos

 or via 

pod repo add

.

解決方法:這是因為電腦裡安裝了另外一個Xcode導緻cocoapods找不到路徑了

在終端執行 sudo xcode-select -switch /Applications/Xcode.app 即可

138、安裝cocoapods的時候出現 ERROR: While executing gem ... (Errno::EPERM)

解決辦法:直接在終端執行 sudo gem install -n /usr/local/bin cocoapods

139、在狀态欄增加網絡請求的菊花,類似safari加載網頁的時候狀态欄菊花

140、檢查一個rect是否包含一個point

// point是否在rect内
BOOL isContains = CGRectContainsPoint(rect, point);
           

141、在指定的寬度下,讓UILabel自動設定最佳font

142、将一個image儲存在相冊中

UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);

或者
#import <Photos/Photos.h>
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        changeRequest.creationDate          = [NSDate date];
    } completionHandler:^(BOOL success, NSError *error) {
        if (success) {
            NSLog(@"successfully saved");
        }
        else {
            NSLog(@"error saving to photos: %@", error);
        }
    }];
           

143、修改cell.imageView的大小

UIImage *icon = [UIImage imageNamed:@""];
CGSize itemSize = CGSizeMake(, );
UIGraphicsBeginImageContextWithOptions(itemSize, NO ,);
CGRect imageRect = CGRectMake(, , itemSize.width, itemSize.height);
[icon drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
           

144、為一個view添加虛線邊框

CAShapeLayer *border = [CAShapeLayer layer];
    border.strokeColor = [UIColor colorWithRed:/.f green:/.f blue:83/255.0f alpha:].CGColor;
    border.fillColor = nil;
    border.lineDashPattern = @[@4, @2];
    border.path = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
    border.frame = view.bounds;
    [view.layer addSublayer:border];
           

145、UITextView中打開或禁用複制,剪切,選擇,全選等功能

// 繼承UITextView重寫這個方法
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
// 傳回NO為禁用,YES為開啟
    // 粘貼
    if (action == @selector(paste:)) return NO;
    // 剪切
    if (action == @selector(cut:)) return NO;
    // 複制
    if (action == @selector(copy:)) return NO;
    // 選擇
    if (action == @selector(select:)) return NO;
    // 選中全部
    if (action == @selector(selectAll:)) return NO;
    // 删除
    if (action == @selector(delete:)) return NO;
    // 分享
    if (action == @selector(share)) return NO;
    return [super canPerformAction:action withSender:sender];
}
           
iOS