Swift / Objective_C / Xcode實際開發中可能遇到的小功能小技巧總結

一:Swift3.0爲視圖添加旋轉動畫,效果如下:

這裏寫圖片描述

代碼實現:

//創建動畫
let anim = CABasicAnimation(keyPath: "transform.rotation")
//設置相關屬性
anim.toValue =  2 * M_PI
anim.repeatCount = MAXFLOAT
anim.duration = 15
//完成之後不移除,testView被釋放,動畫隨着一起刪除
anim.isRemovedOnCompletion = false 
testView(anim, forKey: nil)

二:解決項目中每次界面跳轉隱藏TabBar的問題

思路:在UINavigationController 中重寫pushViewController 方法,不必每次跳轉都調用hidesBottomBarWhenPushed

override func pushViewController(_ viewController: UIViewController, animated: Bool) {
    //隱藏tabbar
    if childViewControllers.count > 0 {
        viewController.hidesBottomBarWhenPushed = true
    }
    super.pushViewController(viewController, animated: animated)
}

三:Swift3.0中使用NSLayoutConstraint爲控件添加約束

//設置通過代碼添加Constraint,否則View還是會按照以往的autoresizingMask進行計算
centerButton.translatesAutoresizingMaskIntoConstraints = false

//依次添加X,Y, W,H
view.addConstraint(NSLayoutConstraint(item: centerButton, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 0))
view.addConstraint(NSLayoutConstraint(item: centerButton, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1.0, constant: -60))
view.addConstraint(NSLayoutConstraint(item: centerButton, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 50))
view.addConstraint(NSLayoutConstraint(item: centerButton, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 50))

方法解讀:

在view視圖中,爲參數1添加約束

設置 參數1(一般爲視圖)參數2(座標或寬高) 屬性 參數3(大於等於小魚) 參數4(參照視圖)參數5(座標或寬高) 屬性 乘以 參數6 加上 參數7

注意:單純設置寬高的時候,參數4傳入nil,參數5傳入.notAnAttribute

view.addConstraint(NSLayoutConstraint(item: 參數1, attribute: 參數2, relatedBy: 參數3, toItem: 參數4, attribute: 參數5, multiplier: 參數6, constant: 參數7))

四:Swift3.0通過十六進制值設置UIColor

extension UIColor {
    class func colorWithHex(hexValue: UInt32) -> UIColor {
        let r = (hexValue & 0xff0000) >> 16
        let g = (hexValue & 0x00ff00) >> 8
        let b = hexValue & 0x0000ff
        return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
    }
}

//示例調用:
view.backGroundColor = UIColor.colorWithHex(hexValue: 0xff0000)

五:Swift3.0中&error的寫法

var error: NSError?
context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error)

六:動態設置TableView的滑動範圍

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //一般獲取最後控件的最大Y座標,labelExplain是最後一個cell下追加的控件
    self.tableView.contentSize = CGSizeMake(0,CGRectGetMaxY(self.labelExplain.frame) + 10);
}

七:clipstobounds與maskstobounds的區別

clipsToBounds(UIView)
是指視圖上的子視圖,如果超出父視圖的部分就截取掉

masksToBounds(CALayer)
卻是指視圖的圖層上的子圖層,如果超出父圖層的部分就截取掉

八:查看真機沙盒文件夾,查看真機崩潰日誌

這裏寫圖片描述

九:常用的路徑位置

模擬器的位置:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs 

文檔安裝位置:
/Applications/Xcode.app/Contents/Developer/Documentation/DocSets

插件保存路徑:
~/Library/ApplicationSupport/Developer/Shared/Xcode/Plug-ins

自定義代碼段的保存路徑:
~/Library/Developer/Xcode/UserData/CodeSnippets/     //如果找不到CodeSnippets文件夾,可以自己新建一個CodeSnippets文件夾。

描述文件路徑
~/Library/MobileDevice/Provisioning Profiles

十:富文本和HTML字符串互相轉化

//富文本轉html字符串
- (NSString *)attriToStrWithAttributeString:(NSAttributedString *)attributeString
{
    NSDictionary *tempDic = @{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute:[NSNumber numberWithInt:NSUTF8StringEncoding]};
    NSData *htmlData = [attributeString dataFromRange:NSMakeRange(0, attributeString.length) documentAttributes:tempDic error:nil];
    return [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];
}

//html字符串轉富文本
- (NSAttributedString *)strToAttriWithString:(NSString *)htmlString
{
    return [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType} documentAttributes:nil error:nil];
}

十一:Swift項目中引入Objective_C三方框架後手動橋接的方法

1>手動創建一個.h的文件,比如:Demo-Bridge.h

2>在Build Setteings 中找到 Objective_C Bridging Header 添加路徑$(SRCROOT)/Demo/Demo-Bridge.h

3>包含Objective_C頭文件,例如:#import "UIView+WebCache.h"

十二:UITableView多行選擇修改系統默認選擇樣式

在自定義的cell中重寫layoutSubviews

- (void)layoutSubviews
{
    [super layoutSubviews];

    // 設置UITableViewCellEditControl樣式
    for (UIControl *control in self.subviews) {
        if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellEditControl")]) {
            for(UIView *view in control.subviews) {
                if([view isKindOfClass: [UIImageView class]]) {
                    UIImageView *img = (UIImageView *)view;
                    if(self.selected) {
                        //選擇狀態圖片
                        img.image= [UIImage imageNamed:@"image1"];
                    } else {
                        //未選中狀態圖片
                        img.image= [UIImage imageNamed:@"image2"];
                    }
                }
            }
        }
    }
}

十三:Xcode項目中一鍵替換項目中所有類中指定文字或代碼

1>快捷鍵command + shift + F喚醒全局搜索並進入輸入狀態

2>切換FindReplace(這裏也可以採用正則進行查找搜索Regular Expression)

這裏寫圖片描述

3>輸入要搜索的內容和替換結果,然後點擊Replace All即可

這裏寫圖片描述

十四:NSUserDefaults判斷應用程序是否是安裝完首次次啓動

if (![[NSUserDefaults standardUserDefaults] valueForKey:@"FirstStart"]) {
    [[NSUserDefaults standardUserDefaults] setValue:@"firstStart" forKey:@"FirstStart"];
    //第一次啓動,可以設置歡迎頁或者設置默認語言
} else {
    //非第一次啓動
}

十五:Swift 設置在debug模式下打印日誌,並且鎖定代碼位置(Objective_C打印設置)

// 可以把下列代碼放在AppDelegate的@UIApplicationMain的上方
func DebugLog<T>(messsage : T, file : String = #file, funcName : String = #function, lineNum : Int = #line) {
    #if DEBUG
        let fileName = (file as NSString).lastPathComponent
        print("\(fileName):(\(lineNum))-\(messsage)")
    #endif
}
//使用方法
DebugLog(messsage: "test")
//輸出類名 + 代碼行數 + 輸出信息
ViewController.swift:(37)-test

十六:修改默認開發語言(Xcode默認開發語言是英語這裏寫圖片描述)

1>先添加英語之外的一種語言

這裏寫圖片描述

2>Show in Finder工程文件 –> 顯示包內容 –> 用文本打開project.pbxproj –> 搜索developmentRegion –> 將值改爲zh-Hans

這裏寫圖片描述

3>修改成功這裏寫圖片描述

十七:使用runtime爲分類添加屬性

我們知道系統的UITableViewsectionrow屬性,就是定義在NSIndexPath的分類裏的

這裏寫圖片描述

示例方法:

//寫一個UIView的分類命名:UIView+Category
UIView+Category.h
//增加的屬性
@property (nonatomic, strong) NSObject *propertyTest;

UIView+Category.m
//加入運行時頭文件
#import <objc/runtime.h>
@implementation UIView (Category)
//獲取關聯的對象
- (NSObject *)propertyTest {
    return objc_getAssociatedObject(self, @selector(propertyTest));
}
//給對象添加關聯對象
- (void)setPropertyTest:(NSObject *)value {
    objc_setAssociatedObject(self, @selector(propertyTest), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
此後,就可以正常訪問了該屬性了

十八:App迭代開發版本號的規則

0>首先我們的App第一版本首次上線, 比如以1.0.0爲首次上線的版本號

1>上線後突然發現一個嚴重的Bug那我們就要修復更新版本, 此時我們的版本號爲1.0.1, 所以說如果修復Bug或者優化功能, 我們只修改疊加第三位數字, 其他不變

2>如果有了新的需求, 在原來的基礎上增加了一個新功能, 那麼我們的版本號變爲1.1.0, 需要清空第三位數字爲0, 來疊加修改第二位數字

3>如果App需求功能大改, 更新量非常大, 那我們的版本號變爲2.0.0, 需要疊加修改第一位數字, 清空其他數字爲0

十九:Swift中懶加載

先說說OC中的懶加載,通常是寫get方法,例如:

- (DataModel *)model
{
    if (!_model) {
        _model  = [[DataModel alloc] init];
        _model.title = @"標題";
    }
    return _model;
}

swift中有專門的懶加載修飾符lazy,實現如下:

private lazy var model: DataModel = {
    let model = DataModel()
    model.title = "標題"
    return model
}()

二十:Swift中shouldAutorotate的重寫

override open var shouldAutorotate: Bool {
    return false / true
}
//或者
open override var shouldAutorotate: Bool {
    get {
        return false / true
    }
}

二十一:屏幕旋轉的時候狀態欄顯示問題

如果是在視圖View中,重寫layoutSubviews;如果是在ViewController中重寫viewWillLayoutSubviews,Swift代碼如下:

//視圖控制器中
override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    UIApplication.shared.isStatusBarHidden = false
}
//視圖中
override func layoutSubviews() {
    super.layoutSubviews()
    UIApplication.shared.isStatusBarHidden = false
}

二十二:區分==,isEqual,isEqualToString

==: 比較的是內存地址

isEqual: 是 NSObject 的方法,首先都會判斷指針是否相等 ,相等直接返回YES,不相等再判斷是否是同類對象或非空,空或非同類對象直接返回NO,而後依次判斷對象對應的屬性是否相等,若均相等,返回YES

isEqualToString: 是NSString的方法,從繼承關係角度來說是 isEqual的衍生方法,在都是字符串的前提下,判斷字符串的內容是否相等,如果知道了兩個對象都是字符串,isEqualToStringisEqual要快

二十三:修改GitHub項目顯示語言

打開Terminal 進入到倉庫文件夾
$:cd /Users/MacName/Desktop/Demo

創建一個`.gitattributes`的文件
$:touch .gitattributes

打開文件
$:open .gitattributes

寫入如下代碼,比如設置語言爲Swift
*.h linguist-language=swift
*.m linguist-language=swift

重新push項目到GitHub, 完成修改

二十四:Terminal命令查看系統隱藏文件

顯示隱藏文件:
$:defaults write com.apple.finder AppleShowAllFiles -bool true

關閉顯示隱藏文件:
defaults write com.apple.finder AppleShowAllFiles -bool false

***執行命令後需要打開強制退出界面(快捷鍵option+command+esc),重啓Finder

二十五:Masonry佈局後獲取Frame

需要立即更新子視圖的佈局後獲取即可

[self layoutIfNeeded];

二十六:Xcode同時打開兩個Simulator模擬器(做通信APP方便調試)

打開終端進到xcode路徑下的Applications路徑

$:cd /Applications/Xcode.app/Contents/Developer/Applications/

打開模擬器

$:open -n Simulator.app/

或者執行一個腳本也可以,創建文件xim.sh,鍵入以下代碼

#!/bin/sh
cd /Applications/Xcode.app/Contents/Developer/Applications/

open -n Simulator.app/
sudo sh sim.sh

會有如下提示:

這裏寫圖片描述

點擊OK後,換一個與當前模擬器設備不同的機型

這裏寫圖片描述

然後在Xcode中選擇剛選取的機型run包即可同時打開調試

實際上多開別的APP道理也是一樣的,進到APP應用目錄,open -n appName.app/即可

二十七:TableView檢測滑動到底部和頂部(可用於聊天界面取歷史消息)

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if (scrollView.contentOffset.y == scrollView.contentSize.height - scrollView.frame.size.height) {
        NSLog(@"滑到底部加載更多");
    }
    if (scrollView.contentOffset.y == 0) {
        NSLog(@"滑到頂部更新");
    }
}
// 另外點擊狀態欄會調用
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
    NSLog(@"點擊狀態欄調用");
}

二十八:區分__weak,__unsafe_unretained,__block

__weak 在釋放指針後能夠同時將指針置爲nil
__unsafe_unretained 只留下一個無效的也指針
__block 打破循環 copy副本 內部修改

二十九:Xcode恢復默認字體

這裏寫圖片描述

三十:UIAlertView點擊背景消失的方法

- (void)longPressTableViewShowAlertView:(UIGestureRecognizer *)gesture
{
    if (gesture.state == UIGestureRecognizerStateBegan) {
        self.alertView = [[UIAlertView alloc] initWithTitle:@"請輸入審批意見" message:nil delegate:self cancelButtonTitle:@"同意" otherButtonTitles:@"駁回", nil];
        [self.alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
        self.alertView.delegate = self;
        [self.alertView show];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
        tap.numberOfTapsRequired = 1;
        tap.cancelsTouchesInView = NO;
        [[UIApplication sharedApplication].keyWindow addGestureRecognizer:tap];
    }
}

- (void)tap:(UITapGestureRecognizer *)tap
{
    if (tap.state == UIGestureRecognizerStateEnded){
        CGPoint location = [tap locationInView:nil];
        if (![self.alertView pointInside:[self.alertView convertPoint:location fromView:self.alertView.window] withEvent:nil]){
            [self.alertView.window removeGestureRecognizer:tap];
            [self.alertView dismissWithClickedButtonIndex:0 animated:YES];
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章