iOS - Common Sense

這些都是本身以爲很是寶貴的知識(也有踩過的坑),在此保存和分享一下html

持續更新...java

1.計算代碼行數

find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs wc -l
複製代碼

2.防止滑動tableView時,定時器中止運行

[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
複製代碼

3.iOS 判斷app程序第一次啓動方法

if(![[NSUserDefaults standardUserDefaults] boolForKey:@"firstStart"])
{
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"firstStart"];
        
        NSLog(@"第一次啓動");
}else{
        
        NSLog(@"不是第一次啓動");
}
複製代碼

4. cocoapods 版本管理

Podfile 或者 Cartfile 中指定依賴版本的時候咱們能夠看到相似這樣的小飄箭頭的符號,這表明版本兼容。好比兼容 2.6.1 表示高於 2.6.12.6.x 版本均可以使用,而 2.7 或以上不行;同理,若是兼容 2.6 的話,2.62.72.8 等等這些版本都是兼容的,而 3.0 不行。固然也可使用 >= 或者是 = 這些符號。ios

4.png

5. fastlane

開發老是有趣的,可是發佈通常都很無聊。由於發佈流程每次都同樣,很是機械。無非就是跑測試,打 tag,上傳代碼,寫 release log,更新 podspec 等等。雖然簡單,可是費時費力,容易出錯。對於這種情景,自動化流程顯然是最好的選擇。而相比於本身寫發佈腳本,在 Cocoa 社區咱們有更好的工具,那就是 fastlane。面試

fastlane 是一系列 Cocoa 開發的工具的集合,包括跑測試,打包 app,自動截圖,管理 iTunes Connect 等等。json

6.RunLoop 的運行狀態

註冊 RunLoopObserver 能夠觀測當前 RunLoop 的運行狀態,並在狀態機切換時收到通知:windows

  • RunLoop開始
  • RunLoop即將處理Timer
  • RunLoop即將處理Source
  • RunLoop即將進入休眠狀態
  • RunLoop即將從休眠狀態被事件喚醒
  • RunLoop退出

RunLoop.png

7.Autorelease對象何時釋放?

這個問題拿來作面試題,問過不少人,沒有幾個能答對的。不少答案都是「當前做用域大括號結束時釋放」,顯然木有正確理解Autorelease機制。tomcat

在沒有手加Autorelease Pool的狀況下,Autorelease對象是在當前的runloop迭代結束時釋放的,而它可以釋放的緣由是系統在每一個runloop迭代中都加入了自動釋放池Push和Pop
————Sunny 博客bash

8.CocoaPods pod install/pod update更新慢的問題

  • pod install --verbose --no-repo-update
  • pod update --verbose --no-repo-update

9.Object-C Category 和 Class Extension 的區別

Category
  • 用於給class及其subclass添加新的方法
  • 有本身單獨的 .h 和 .m 文件
  • 用於添加新方法,而不能添加新屬性(property)
Class Extension
  • Extension常被稱爲是匿名的Category
  • 用於給類添加新方法,但只做用於原始類,不做用於subclass
  • 只能對有implementation源代碼的類寫Extension,對於沒有implementation源代碼的類,好比framework class,是不能夠的
  • Extension能夠給原始類添加新方法,以及新屬性

10.URL 組成結構

NSURL *url = [NSURL URLWithString:@"http://www.onevcat.com/2011/11/debug/;param?p=307#more-307"];
    NSLog(@"Scheme: %@", [url scheme]);
    NSLog(@"Host: %@", [url host]);
    NSLog(@"Port: %@", [url port]);
    NSLog(@"Path: %@", [url path]);
    NSLog(@"Relative path: %@", [url relativePath]);
    NSLog(@"Path components as array: %@", [url pathComponents]);
    NSLog(@"Parameter string: %@", [url parameterString]);
    NSLog(@"Query: %@", [url query]);
    NSLog(@"Fragment: %@", [url fragment]);
將url 轉換爲合法的url字符串
NSString *fixedStr = [reqStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
複製代碼

11.使label裏的內容字體大小自適應label

descriptionLabel.adjustsFontSizeToFitWidth = YES;
複製代碼

12.用蘋果自帶MessageComposer 發送email/sms

developer.apple.com/library/ios…app

調用 SMS編輯器

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://800888"]];
複製代碼

若須要傳遞內容能夠作以下操做:

加入:MessageUI.framework #import <MessageUI/MFMessageComposeViewController.h>

實現代理:MFMessageComposeViewControllerDelegate

調用sendSMS函數

//內容,收件人列表
- (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
    MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
    if([MFMessageComposeViewController canSendText])
    {
        controller.body = bodyOfMessage;  
        controller.recipients = recipients;
        controller.messageComposeDelegate = self;
        [self presentModalViewController:controller animated:YES];
    }  
}

複製代碼
// 處理髮送完的響應結果
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
  [self dismissModalViewControllerAnimated:YES];
 
  if (result == MessageComposeResultCancelled)
    NSLog(@"Message cancelled")
  else if (result == MessageComposeResultSent)
    NSLog(@"Message sent") 
  else
    NSLog(@"Message failed") 
}
複製代碼

默認發送短信的界面爲英文的,解決辦法爲: 在.xib 中的Localization添加一組chinese就ok了

13.測試跳轉頁面

#if 1
   
    LoginViewController *vc = [[LoginViewController alloc] init];
    _window.rootViewController = vc;

#else // 測試界面用 
    
    RegisterViewController *vc = [[RegisterViewController alloc] init];
    _window.rootViewController = vc;

#endif
複製代碼

14.iOS系統中的藍色色值

[UIColor colorWithRed:0.0 green:110.0/255.0 blue:1.0 alpha:1.0];

15.判斷字符串漢字和字母的個數

- (CGFloat)inputString:(NSString *)string{
    int x = 0;
    int y = 0;
    for (int i = 0; i < string.length; i++) {
        
        NSRange range = NSMakeRange(i,1);
        NSString *subString = [string substringWithRange:range];
       
        const char *cString = [subString UTF8String];
        if (strlen(cString) == 3)
        {
            NSLog(@"漢字");
            x+=1;
        }
        else if(strlen(cString) == 1){
            
            NSLog(@"字母");
            y+=1;
        }
    }

    return 10 + ([[NSString stringWithFormat:@"%lu",_selectRedAmount] length]+3+3*x+y)*5+10;
}
複製代碼

16.iOS 停靠模式

16.png

17.去掉UItableview headerview黏性

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (scrollView == _tableView)
      {
         CGFloat sectionHeaderHeight = SECTION_HEIGHT;
         
          if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
             
              scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
        
          } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
              
              scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
         }
      }
}
複製代碼

18.合成兩張圖片爲一張圖片

- (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2 {
    UIGraphicsBeginImageContext(image1.size);
    
    CGFloat width = image1.size.width;
    CGFloat height = image1.size.height;
    
    // Draw image1
    [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)];
    
    // Draw image2
    [image2 drawInRect:CGRectMake(width * 0.4, height * 0.4, width*0.2, height*0.2)];
    
    
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return resultingImage;
}
複製代碼

19.設置window alert等級以使其顯示在狀態欄之上

[_assetsCalendarWindow setWindowLevel:UIWindowLevelAlert];

iOS系統中定義了三個window層級,其中每個層級又能夠分好多子層級(從UIWindow的頭文件中能夠看到成員變量CGFloat _windowSublevel),不過系統並無把這個屬性開出來。UIWindow的默認級別是UIWindowLevelNormal,咱們打印輸出這三個level的值分別以下:

2012-03-27 22:46:08.752 UIViewSample[395:f803] Normal window level: 0.000000
2012-03-27 22:46:08.754 UIViewSample[395:f803] Alert window level: 2000.000000
2012-03-27 22:46:08.755 UIViewSample[395:f803] Status window level: 1000.000000

複製代碼

這樣印證了他們級別的高低順序從小到大爲Normal < StatusBar < Alert

20.獲取當前導航控制器下前一個控制器

- (UIViewController *)backViewController
{
    NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];

    if ( myIndex != 0 && myIndex != NSNotFound ) {
        return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
    } else {
        return nil;
    }
}
複製代碼

21.mac 使用終端鏈接後臺,輸出日誌,查看驗證碼

cd /usr/local/tomcat-app/logs/
tail -1000f /usr/local/tomcat-app/logs/catalina.out
複製代碼

22.Xcode 8 運行一堆沒用的logs解決辦法

22-1.png

上圖咱們看到,本身新建的一個工程啥也沒幹就打印一堆爛七八糟的東西,這個應該是Xcode 8的問題,解決辦法是設置OS_ACTIVITY_MODE : disable以下圖:

22-2.png

23.升級Xcode8以後文字佔用空間變化

建立一個Label而後讓它自適應大小,字體大小都是17最後輸出的寬度是不同的,咱們再看一下,下面的數據就知道爲何升級 iOS 10 以後App中有的文字顯示不全了: 

英文字母會不會也有這種問題,我又經過測試,後來發現英文字母沒有問題,只有漢字有問題。目前只有一個一個修改控件解決這個問題,暫時沒有其餘好辦法來解決。

23.png

24.給tabbar添加點擊動畫

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {

    NSInteger index = [self.tabBar.items indexOfObject:item];

    if (self.indexFlag != index) {
        [self animationWithIndex:index];
    }

}
// 動畫
- (void)animationWithIndex:(NSInteger) index {
    NSMutableArray * tabbarbuttonArray = [NSMutableArray array];
    for (UIView *tabBarButton in self.tabBar.subviews) {
        if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
            [tabbarbuttonArray addObject:tabBarButton];
        }
    }
    CABasicAnimation*pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    pulse.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    pulse.duration = 0.08;
    pulse.repeatCount= 1;
    pulse.autoreverses= YES;
    pulse.fromValue= [NSNumber numberWithFloat:0.7];
    pulse.toValue= [NSNumber numberWithFloat:1.3];
    [[tabbarbuttonArray[index] layer]
     addAnimation:pulse forKey:nil];

    self.indexFlag = index;

}
複製代碼

25.獲取當前界面上顯示的鍵盤UIKeyboard方法

正常狀況下咱們對iOS系統鍵盤的使用僅限於讓其顯示或者隱藏,不會有須要獲取到它的對象,僅當有一種狀況,便是當咱們須要在界面上添加一些元素,而且但願這些元素可以不被鍵盤擋住。這種狀況下咱們須要找到當前鍵盤所在的Window,並將元素添加到這個Window上,如此一來,咱們先要找到鍵盤的實例對象,它是UIView的子類對象,咱們只須要調用其window方法就能找到包含了鍵盤的UIWindow對象,就能夠進行元素的添加了。具體方法以下:

- (UIView *)findKeyboard
{
    UIView *keyboardView = nil;
    NSArray *windows = [[UIApplication sharedApplication] windows];
    for (UIWindow *window in [windows reverseObjectEnumerator])//逆序效率更高,由於鍵盤總在上方
    {
        keyboardView = [self findKeyboardInView:window];
        if (keyboardView)
        {
            return keyboardView;
        }
    }
    return nil;
}


- (UIView *)findKeyboardInView:(UIView *)view
{    
    for (UIView *subView in [view subviews])
    {
        if (strstr(object_getClassName(subView), "UIKeyboard"))
        {
            return subView;
        }
        else
        {
            UIView *tempView = [FTEView findKeyboardInView:subView];
            if (tempView)
            {
                return tempView;
            }
        }
    }
    return nil;
}
複製代碼

26.設置UILabel行間距

NSMutableAttributedString * attrString = [[NSMutableAttributedString  alloc] initWithString:label.text];
NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:20];
[attrString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, label.text.length)]; 
label.attributedText = attrString;
複製代碼

27.在image上繪製文字並生成新的image

UIFont *font = [UIFont boldSystemFontOfSize:12];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x, point.y, image.size.width, image.size.height);
[[UIColor whiteColor] set];
[text drawInRect:CGRectIntegral(rect) withFont:font]; 
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

複製代碼

28.iPhone X 適配的宏定義

#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) 
// 狀態欄高度
#define STATUS_BAR_HEIGHT (iPhoneX ? 44.f : 20.f) 
// 導航欄高度
#define NAVIGATION_BAR_HEIGHT (iPhoneX ? 88.f : 64.f) 
// tabbar高度
#define TAB_BAR_HEIGHT (iPhoneX ? (49.f+34.f) : 49.f)
 // home indicator 
#define HOME_INDICATOR_HEIGHT (iPhoneX ? 34.f : 0.f)
複製代碼

29.使用YYLabel實現超連接效果

NSString *string = @"註冊即表示贊成《註冊協議》和《隱私聲明》";
       
        NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:string];
        attrString.yy_font           = [UIFont systemFontOfSize:12.0f];
        attrString.yy_color          = DEF_UICOLORFROMRGB(0x999999);
        attrString.yy_underlineStyle = NSUnderlineStyleNone;
        @weakify(self);
        [attrString yy_setTextHighlightRange:[string rangeOfString:@"《註冊協議》"]
                                color:DEF_UICOLORFROMRGB(0x0076FF)
                      backgroundColor:[UIColor clearColor]
                            tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){
                                @strongify(self);
                                [self registerProtocolButtonClicked:nil];
                            }];
        [attrString yy_setTextHighlightRange:[string rangeOfString:@"《隱私聲明》"]
                                color:DEF_UICOLORFROMRGB(0x0076FF)
                      backgroundColor:[UIColor clearColor]
                            tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){
                                @strongify(self);
                                [self privacyStatementButtonClicked:nil];
                            }];
        
        _linkLabel           = [[YYLabel alloc] init];
        _linkLabel.frame     = CGRectMake((DEF_DEVICE_WIDTH -290)/2, self.registerBtn.bottom +20, 290, 20);
        _linkLabel.attributedText  = attrString;
        _linkLabel.textAlignment   = NSTextAlignmentCenter;
        _linkLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
        _linkLabel.numberOfLines   = 0;
        _linkLabel.backgroundColor = [UIColor clearColor];
        [self addSubview:_linkLabel];

複製代碼

30. 帶有.00的數字,使用number類型json解析以後會失去精度

今天遇到了一個大坑,這個問題調查了好久。一直覺得是jar包或者哪裏轉錯了,本身動手實驗了一下,發現是json js 和java數值範圍不一樣引發的。

{ 
      「boolean」: true, 
      「starttimeseconds」:9223372036854122112, 
      「null」: null, 
      「number」: 11222222222222222223, 
} 
複製代碼

上邊是一段json格式的字符串,經由json編輯器轉成json對象的結果是starttimeseconds:9223372036854122000; 形成這個現象的主要緣由是 js 中的 number 數值類型是雙浮點精度類型即 double , 而 java 中的 starttimeseconds 的類型爲 long 類型, 也就是說 java 中得 long 能表示的範圍比 js 中 number 大, 也就意味着部分數值在 js 中存不下, 因此在 js 中字符串轉成 js 中的 object 的過程當中數字精度發生額了丟失。

  • 解決方法一:將starttimeseconds設置爲string類型的,這個的話來回轉換的 是字符串,不存在數值丟失。
  • 解決方法二:protoful.js 的 long.js 解決。

31.進入某一頁面,使某一輸入框成爲第一響應者,可能須要延遲

//鍵盤成爲第一響應者,延遲展現(牢記)
- (void)viewDidAppear:(BOOL)animated{
    
    [super viewDidAppear:animated];
    [self.textField becomeFirstResponder];
}
//或者
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        [self.textField becomeFirstResponder];
    });
複製代碼
相關文章
相關標籤/搜索