iOS 中的那些小問(wèn)題

  1. UITextView 中的文字默認(rèn)并不是從最上面開(kāi)始,在 UITextView 所在的 UIViewController中添加:
self.automaticallyAdjustsScrollViewInsets = false;
  1. UITableView 自動(dòng)隱藏鍵盤:
tableView.keyboardDismissMode = .onDrag
  1. 設(shè)置 UITableView 中的 Cell 選中打鉤的顏色:
tableView.tintColor = .red
  1. UIButton 在邊緣的時(shí)候沒(méi)有高亮響應(yīng),重寫(xiě) UIButton 的 pointInside函數(shù):
/**
        解決按鈕在邊緣的時(shí)候被按下時(shí)沒(méi)有顯示高亮
     
     - parameter point: 按下的位置
     - parameter event: 目標(biāo)事件
     
     - returns: 是否在內(nèi)部
     */
    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
        
        let inside = super.pointInside(point, withEvent: event)
        
        if inside != highlighted && event?.type == .Touches {
            highlighted = inside
        }
        
        return inside
    }

PS:如果遇到需要這樣的情況下潮模,最好繼承 UIButton 重寫(xiě)該函數(shù)翻诉,而不是extension UIButton,因?yàn)檫@樣會(huì)使工程中用到的所有的 UIButton 都被重寫(xiě)。

  1. 靜音模式下播放音頻伸刃,最好在didFinishLaunchingWithOptions中進(jìn)行調(diào)用
/**
        靜音模式下仍可以播放音頻
    */
    public class func playInQuietMode() {
        
        let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
        
        do {
            try audioSession.setCategory(AVAudioSessionCategoryPlayback)
        } catch let error as NSError{
            print(error)
        }
        
        do {
            try audioSession.setActive(true)
        } catch let error as NSError{
            print(error)
        }
    }
  1. 自定義 UITableViewCell 選中時(shí)的顏色
/**
        設(shè)置選中背景色
     
     - parameter color: 背景色
     */
    public func setSelectColor(color: UIColor) {
        
        let backgroundView = UIView();
        backgroundView.backgroundColor = color;
        self.selectedBackgroundView = backgroundView;
    }

PS:self.selectionStyle的值不能為.None乔询。

  1. 判斷 UIScrollView 是否滾動(dòng)結(jié)束:
/// 記錄手指放開(kāi)滑動(dòng)時(shí) scrollView 的內(nèi)容偏移
fileprivate var offset = CGPoint.zero

// 記錄當(dāng)前滑動(dòng)狀態(tài)
fileprivate var isScrollEnd = true

extension Controller: UIScrollViewDelegate {
    
    public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        // 開(kāi)始滾動(dòng)樟插,記錄狀態(tài)
        isScrollEnd = false
    }
    
    public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        // 記錄手指放開(kāi)滑動(dòng)時(shí) scrollView 的內(nèi)容偏移
        offset = scrollView.contentOffset
        // 使用 perform 延遲檢測(cè) scrollView 內(nèi)容偏移,
        // 1. 如果手指放開(kāi)滑動(dòng)后 scrollView 繼續(xù)滑動(dòng),由于 perform 運(yùn)行在 NSDefaultRunLoopMode 模式黄锤,
        //    因此在 scrollView 繼續(xù)滑動(dòng)的情況下不會(huì)開(kāi)始定時(shí)搪缨,因此不會(huì)在設(shè)置的延時(shí)后調(diào)用;
        // 2. 如果手指放開(kāi)滑動(dòng)后 scrollView 停止滑動(dòng)鸵熟,則會(huì)在設(shè)置的延時(shí)后調(diào)用 checkScrollEnd副编;
        perform(#selector(self.checkScrollEnd), with: nil, afterDelay: 0.020)
    }
    
    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // 當(dāng)手指放開(kāi)滑動(dòng)后 scrollView 繼續(xù)滑動(dòng),取消 checkScrollEnd 的調(diào)用流强;
        NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self.checkScrollEnd), object: nil)
        // 結(jié)束滾動(dòng)齿桃,記錄狀態(tài)
        isScrollEnd = true
    }
    
    internal func checkScrollEnd() {
        // 判斷 scrollView 當(dāng)前內(nèi)容偏移與手指松開(kāi)時(shí)的內(nèi)容偏移是否相同,
        isScrollEnd = (offset == tableView.contentOffset)
    }
}
  1. UITableView 添加 UITextField 時(shí)鍵盤處理
/// 添加監(jiān)聽(tīng)
public override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // 監(jiān)聽(tīng)鍵盤的彈出
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    // 監(jiān)聽(tīng)鍵盤的隱藏
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
/// 移除監(jiān)聽(tīng)
public override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}
/// 鍵盤彈出處理
public func keyboardDidShow(_ notification : Notification) {
    // 獲取當(dāng)前活躍的textField及其rect
    guard let textField = activeField, let rect = textField.superview?.convert(textField.frame, to: nil) else {
            return
    }
    // 獲取鍵盤信息
    guard let keyboardInfo = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    // 獲取鍵盤高度
    let keyboardHeight = keyboardInfo.cgRectValue.size.height;
    // 獲取 textField 底部剩余空間
    let cellBottomHeight = UIScreen.main.bounds.height - rect.maxY
    // 獲取 textField 需要向上平移多少才能滿足鍵盤彈出所需的空間
    var offset = keyboardHeight - cellBottomHeight
    // 設(shè)置底部偏移,保證鍵盤彈出后仍能滑動(dòng)到底部
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
    // 當(dāng) offset 小于 0 時(shí)煮盼,表示空間已滿足
    guard offset > 0 else { return }
    // 加上 tableView 當(dāng)前偏移
    offset += self.tableView.contentOffset.y
    self.tableView.setContentOffset(CGPoint(x: 0, y: offset), animated: true)
}
/// 鍵盤收回處理
public func keyboardWillHide(_ notification : Notification) {
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}
  1. 給 UIView 添加陰影
/**
        添加陰影
     
     - parameter color:  陰影顏色
     - parameter offset: 陰影偏移
     */
    public func addShadow(color: UIColor, offset: CGFloat) {
        
        self.layer.shadowColor = color.CGColor;
        self.layer.shadowOffset = CGSizeMake(-offset, offset);
        self.layer.shadowOpacity = 0.8;
        self.layer.shadowRadius = offset;
    }
  1. 震動(dòng)
/**
        震動(dòng),在真機(jī)上:設(shè)置/聲音 中開(kāi)啟響鈴/震動(dòng)選項(xiàng)開(kāi)啟后才能震動(dòng)
    */
    public class func shark() {
        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate));
    }
  1. 打開(kāi) iPod
/**
        打開(kāi) iPod
     */
    public class func openIpod() {
        
        UIApplication.sharedApplication().openURL(NSURL(string: "music://")!);
    }
  1. App 國(guó)際化時(shí)短纵,有時(shí)我們第一次安裝APP時(shí)不想默認(rèn)跟隨系統(tǒng),那么可以通過(guò)Xcode的scheme來(lái)指定特定語(yǔ)言


  2. 讓 UITableView 在沒(méi)有數(shù)據(jù)時(shí)不能滾動(dòng)

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        self.tableView.scrollEnabled = (data.count > 0);
        
        return data.count;
}
  1. 應(yīng)用內(nèi)打開(kāi)其他 App
    Info.plist文件中設(shè)置URL types

    之后就可以使用下面的模式來(lái)發(fā)送一個(gè)URL:
myapp://
myapp://some/path/here
myapp://?foo=1&bar=2
myapp://some/path/here?foo=1&bar=2

然后僵控,App 的UIApplicationDelegate會(huì)收到一個(gè)消息香到。若你想自己處理該URL,可以重載下面這個(gè)方法:

func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {
}
  1. 如果20秒內(nèi)無(wú)法啟動(dòng)程序的話报破,iOS 檢測(cè)計(jì)時(shí)器就會(huì)終止你的應(yīng)用

  2. UIImage+imageNamed: 方法可避免延時(shí)加載悠就,不像 +imageWithContentsOfFile:(和其他別的 UIImage 加載方法),這個(gè)方法會(huì)在加載圖片之后立刻進(jìn)行解壓充易。

  3. App 播放視頻時(shí)進(jìn)入后臺(tái)讓視頻繼續(xù)播放梗脾,有兩種方法可以實(shí)現(xiàn):

第一種、 對(duì)目標(biāo)視頻對(duì)象的視頻軌進(jìn)行以下處理:

let playerItem = AVPlayerItem(URL: NSURL(string: "videoUrl")!);
let tracks = playerItem.tracks;
for track in tracks {
   if (track.assetTrack.hasMediaCharacteristic(AVMediaCharacteristicVisual)) {
       track.enabled = false;
   }
}

第二種盹靴、 在進(jìn)入后臺(tái)前將目標(biāo)視頻渲染層設(shè)為 nil炸茧,在恢復(fù)到前臺(tái)時(shí)重新設(shè)置:

func applicationDidEnterBackground(application: UIApplication) { 
   let playerView = "Get your player view"; 
   playerView.playerLayer.player = nil; 
}
func applicationDidBecomeActive(application: UIApplication) {
   let playerView = "Get your player view";
   playerView.playerLayer.player = player;
}
  1. 獲取視頻的每秒幀數(shù) fps 和 視頻的長(zhǎng)度 duration
let asset = AVAsset(URL: NSURL(fileURLWithPath: "videoPath"));
let fps = asset.tracksWithMediaType(AVMediaTypeVideo)[0].nominalFrameRate;
let duration = CMTimeGetSeconds(asset.duration);
  1. App 進(jìn)入后臺(tái)仍然繼續(xù)運(yùn)行:
public func applicationDidEnterBackground(application: UIApplication) {
        
        application.beginReceivingRemoteControlEvents();

        var bgTask : UIBackgroundTaskIdentifier?
        bgTask = application.beginBackgroundTaskWithExpirationHandler {
            dispatch_async(dispatch_get_main_queue(), {
                if bgTask != UIBackgroundTaskInvalid
                {
                    bgTask = UIBackgroundTaskInvalid
                }
            })
        }
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            dispatch_async(dispatch_get_main_queue(), {
                if bgTask != UIBackgroundTaskInvalid
                {
                    bgTask = UIBackgroundTaskInvalid
                }
            })
        }
    }
  1. App 運(yùn)行中不鎖屏:
UIApplication.sharedApplication().idleTimerDisabled = true;
  1. 禁止 oc 文件使用 ARC-fno-objc-arc

  2. Swift 獲取對(duì)象的引用次數(shù):CFGetRetainCount(obj)

  3. 禁止 UIButton 在按下時(shí)有動(dòng)態(tài)陰影:

button.adjustsImageWhenHighlighted = false;
  1. 隱藏導(dǎo)航欄的返回按鈕:
self.navigationItem.hidesBackButton = true;
  1. 隱藏導(dǎo)航欄下影線:
self.navigationController?.navigationBar.shadowImage = UIImage();
  1. 設(shè)置導(dǎo)航欄中間為圖片:
self.navigationItem.titleView = UIImageView(image: UIImage(named: "titleImage"));
  1. 導(dǎo)航欄相關(guān)屬性效果
/// rootView 的布局從(0,0)開(kāi)始
edgesForExtendedLayout = .all
navigationController?.navigationBar.isTranslucent = false
/// rootView 的布局從(0稿静,64)開(kāi)始
edgesForExtendedLayout = .all
navigationController?.navigationBar.isTranslucent = true
  1. 機(jī)型與屏幕尺寸的對(duì)應(yīng):
  • 4s_3.5inch
  • 5s_4inch
  • 6_4.7inch
  • 6+_5.5inch
  1. 模擬器截圖時(shí)梭冠,必須設(shè)置分辨率為100%(Simulator > Window > Scale > 100%)

  2. UIView 中添加定時(shí)器時(shí)導(dǎo)致內(nèi)存泄露處理:

override func willMoveToWindow(newWindow: UIWindow?) {
    super.willMoveToWindow(newWindow);
    if (newWindow == nil) {
        self.updateTimer.invalidate();
    }
}
  1. UITextfiled 設(shè)置 placehold 字體顏色:
self.passwdTextIpt.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("login_passwd", comment: ""), attributes: [NSForegroundColorAttributeName: UIColor(white: 1.0, alpha: 0.4)]);
  1. 使用自定義字體

  2. 將目標(biāo)字體拖入目標(biāo)項(xiàng)目;


    F001.png
  3. Info.plist 文件中設(shè)置目標(biāo)字體改备;

    F002.png

  4. 將字體添加到 Copy Bundle Resources控漠;

    F003.png

  5. 使用字體:UIFont(name: fontname, size: fontsize);

  6. 設(shè)置 UITextfiled 文字偏移:

self.userIdTextIpt.layer.sublayerTransform = CATransform3DMakeTranslation(10, 0, 0);

或者重寫(xiě) UITextfiled

override func textRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectInset(bounds, 44, 0);
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectInset(bounds, 44, 0);
}
  1. UIImage 顯示與圖片不同,設(shè)置其渲染模式即可:
UIImage(named: imageName)!.imageWithRenderingMode(.AlwaysOriginal);
  1. 設(shè)置狀態(tài)欄背景樣式無(wú)效:

  2. Info.plist 文件中設(shè)置 View controller-based status bar appearanceNo悬钳;

  3. Appdelegate.swift 文件中設(shè)置 UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.Default;

  4. 隱藏導(dǎo)航欄返回按鈕:

self.navigationItem.hidesBackButton = true;
  1. 使用 Cookie:
let url = NSURL(string: url);
guard let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL(url!) else {
    return
}
let header = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies);
let request = NSMutableURLRequest(URL: url!);
request.addValue(header["Cookie"]!, forHTTPHeaderField: "Cookie");
  1. 添加陰影
view.layer.shadowColor = UIColor.blackColor().CGColor;
view.layer.shadowOffset = CGSizeMake(0, 0);
view.layer.shadowOpacity = 0.25;
view.layer.shadowRadius = 6;
  1. 檢查 API 可用性
if #available(iOS 9.0, *) { 
      let store = CNContactStore()
} else { 
      // 舊版本的情況
}
  1. swift 中將 Unmanaged<CGImage> 轉(zhuǎn)化為 UIImage
let unCGimage:Unmanaged<CGImage> = defaultRepresentation.fullResolutionImage();
let image = unCGimage.takeUnretainedValue())
  1. CADisplayLink 使用完成后?內(nèi)存無(wú)法被釋放:
self.displaylink = CADisplayLink(target: self, selector: #selector(SCGifView.changeKeyFrame))
self.displaylink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)

以上在我一個(gè)工程中使用到的盐捷,在測(cè)試的時(shí)候,發(fā)現(xiàn)其內(nèi)存無(wú)法被釋放默勾,檢查看發(fā)現(xiàn)需要手動(dòng)調(diào)用以下代碼來(lái)完成釋放:

self.displaylink?.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes);
self.displaylink?.invalidate();
self.displaylink = nil;
  1. 設(shè)置 App 沙盒內(nèi)的 Document 文件夾可以被其他軟件共享(各類手機(jī)助手):
    Info.plist 文件中 添加 Application supports iTunes file sharing碉渡,并設(shè)置其值為 YES

  2. 播放系統(tǒng)拍照時(shí)的 咔嚓聲(本質(zhì)就是播放系統(tǒng)聲音):

let soundID: SystemSoundID = 1108;    //! 1108 就是拍照的系統(tǒng)聲音編號(hào),要播放其他的聲音可以到網(wǎng)上搜索對(duì)應(yīng)的編號(hào)
AudioServicesPlayAlertSound(soundID);
  1. AudioServicesPlaySystemSoundAudioServicesPlayAlertSound 的區(qū)別:

    1. AudioServicesPlaySystemSound 僅僅是播放系統(tǒng)聲音灾测,在靜音模式下不播放爆价;
    2. AudioServicesPlayAlertSound 當(dāng)設(shè)置了 通用/聲音/響鈴模式振動(dòng)垦巴,播放系統(tǒng)聲音并振動(dòng),否則只播放系統(tǒng)聲音铭段;當(dāng)設(shè)置了 通用/聲音/靜音模式振動(dòng)骤宣,振動(dòng),否則不播放系統(tǒng)聲音序愚。
  2. 當(dāng) UIButton 即有文字又有圖像時(shí)憔披,只讓圖像旋轉(zhuǎn):

let animation = CABasicAnimation(keyPath: "transform.rotation.z");
animation.fromValue = NSNumber(float: 0);
animation.toValue = NSNumber(double: 2 * M_PI);
animation.duration = 3;
animation.repeatCount = HUGE;
button.imageView?.layer.addAnimation(animation, forKey: "scRotationAnimation");
  1. 調(diào)用 AVPlayerseekToTime 接口時(shí)間不對(duì),將
self.player!.seekToTime(CMTimeMakeWithSeconds(time, self.player!.currentItem!.currentTime().timescale));

更換為:

self.player!.seekToTime(CMTimeMakeWithSeconds(time, self.player!.currentItem!.currentTime().timescale), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero);
  1. 使用 NSDateFormatter.dateFromString 總是返回 nil爸吮,原因可能是你的時(shí)間格式是12小時(shí)制而你的值是24小時(shí)制芬膝,將 hh:mm:ss 改成 HH:mm:ss即可。

  2. swift 中結(jié)構(gòu)體與結(jié)構(gòu)體指針的使用形娇,SMsgAVIoctrlSetPlayVolumeReq 為結(jié)構(gòu)體锰霜, IOTYPE_USER_IPCAM_AUDIO_PLAY_VOLUME_SETTING_REQ 為枚舉變量:

let cmd = UnsafeMutablePointer<SMsgAVIoctrlSetPlayVolumeReq>(malloc(sizeof(SMsgAVIoctrlSetPlayVolumeReq)))
cmd.memory.command_types_ = 1;
cmd.memory.value_ = 1;  
self.camera.sendIOCtrlToChannel(0, type: Int(IOTYPE_USER_IPCAM_AUDIO_PLAY_VOLUME_SETTING_REQ.rawValue), data: UnsafeMutablePointer<Int8>(cmd), dataSize: sizeof(SMsgAVIoctrlSetPlayVolumeReq))
        free(cmd)
  1. 指針偏移
let buf:UnsafePointer<UInt8> = CFDataGetBytePtr(rawData)
var r:UInt8 = 0
r = buf.advancedBy(i+0).memory
  1. 字符串保留特定字符(以下例子保留字母):
let notAllowedCharactersSet = NSCharacterSet(charactersInString: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdedghijklmnopqrsquvwxyz").invertedSet
let filterStr = (str.componentsSeparatedByCharactersInSet(notAllowedCharactersSet) as NSArray).componentsJoinedByString("")
  1. swift 的黑魔法
extension UIButton {
    
    class func oyc_swizzleSendAction() {
        
        struct oyc_swizzleToken {
            static var onceToken : dispatch_once_t = 0
        }
        
        dispatch_once(&oyc_swizzleToken.onceToken) {
            
            let cls: AnyClass! = UIButton.self
            
            let originalSelector = #selector(sendAction(_:to:forEvent:))
            let swizzledSelector = #selector(oyc_sendAction(_:to:forEvent:))
            
            let originalMethod =
                class_getInstanceMethod(cls, originalSelector)
            let swizzledMethod =
                class_getInstanceMethod(cls, swizzledSelector)
            
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
    
    public func oyc_sendAction(action: Selector, to: AnyObject!, forEvent: UIEvent!) {
        
        struct oyc_buttonTapCounter {
            static var count: Int = 0
        }
        
        oyc_buttonTapCounter.count += 1
        print(oyc_buttonTapCounter.count)
        oyc_sendAction(action, to: to, forEvent: forEvent)
    }
    
    override public class func initialize() {
        if self != UIButton.self {
            return
        }
        UIButton.oyc_swizzleSendAction()
    }
}
  1. ?? 操作符
    在 Swift 中,有一個(gè)非常有用的操作符桐早,可以用來(lái)快速地對(duì) nil 進(jìn)行條件判斷癣缅,那就是 ?? 。這個(gè)操作符可以判斷輸入并在當(dāng)左側(cè)的值是非 nilOptional 值時(shí)返回其 value哄酝,當(dāng)左側(cè)是 nil 時(shí)返回右側(cè)的值友存,比如:
var level : Int?
var startLevel = 1
var currentLevel = level ?? startLevel
  1. App 在啟動(dòng)界面停留特定時(shí)間:
NSThread.sleepForTimeInterval(3.0);      // 3.0 表示 3 秒
  1. swift 中根據(jù)字符串創(chuàng)建對(duì)象:
        //動(dòng)態(tài)獲取命名空間:
        let nameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
        //根據(jù)命名空間和傳過(guò)來(lái)的控制器名字獲取控制器的類
        let controllerClass:AnyClass = NSClassFromString(nameSpace + "." + controllerName)!
        
        //告訴編譯器真實(shí)的控制器類型,比如這個(gè)控制器本質(zhì)是UITableViewController則:
        let realClass = controllerClass as! UITableViewController.Type
        
        //實(shí)例化這個(gè)控制器出來(lái)
        let childController = realClass.init()
  1. UIButton 中的 文本圖片 默認(rèn)是水平對(duì)齊

  2. 使用 單元測(cè)試 時(shí)顯示 Module 'CTest' was not compiled for testing
    Build SettingsEnable Testability 設(shè)置為 YES

  3. Xcode 8 控制臺(tái)輸出信息太多解決方法:Edit Scheme -> Run -> Arguments陶衅, 在 Environment Variables 里邊添加 OS_ACTIVITY_MODE屡立,值設(shè)置為 disable

  4. 設(shè)置 WKWebView 的字體大小:

        //創(chuàng)建網(wǎng)頁(yè)配置對(duì)象
        let config = WKWebViewConfiguration();
        // 創(chuàng)建設(shè)置對(duì)象
        let preference = WKPreferences();
        // 設(shè)置字體大小(最小的字體大小)
        preference.minimumFontSize = 60;
        // 設(shè)置偏好設(shè)置對(duì)象
        config.preferences = preference;
        // 創(chuàng)建WKWebView
        let webView = WKWebView(frame: self.view.bounds, configuration: config);
        webView.loadHTMLString("<p>Some Text</p>", baseURL: nil)
        return webView;
  1. 設(shè)置 WKWebView 根據(jù)屏幕寬度調(diào)整內(nèi)容大胁缶:
    /// 網(wǎng)絡(luò)瀏覽視圖
    fileprivate let webView: WKWebView = {
        let source = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
        let script = WKUserScript(source: source, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
        let userContentController = WKUserContentController()
        userContentController.addUserScript(script)
        //創(chuàng)建網(wǎng)頁(yè)配置對(duì)象
        let config = WKWebViewConfiguration()
        config.userContentController = userContentController
        // 創(chuàng)建設(shè)置對(duì)象
        let preference = WKPreferences()
        // 設(shè)置字體大小(最小的字體大小)
        preference.minimumFontSize = 18
        // 設(shè)置偏好設(shè)置對(duì)象
        config.preferences = preference
        return WKWebView(frame: .zero, configuration: config)
    }()
  1. lazy 屬性本質(zhì)上是一個(gè)閉包膨俐,閉包中的表達(dá)式只會(huì)調(diào)用一次。需要強(qiáng)調(diào)的是奕巍,雖然這個(gè)閉包中捕獲了self吟策,但是這樣做并不會(huì)導(dǎo)致循環(huán)引用,猜測(cè)是 swift 自動(dòng)把 self 標(biāo)記為 unowned 了的止。

  2. 給視圖及之上的子控件添加陰影:

    let container = UIView();
    container.clipsToBounds = true;
    container.layer.cornerRadius = 5;
    container.layer.borderWidth = 1;
    container.layer.borderColor = UIColor.gray.cgColor;
    container.layer.shadowColor = UIColor.black.cgColor;
    container.layer.shadowOffset = CGSize(width: 4, height: 4);
    container.layer.shadowOpacity = 0.5;
    container.layer.shadowRadius = 3;
    return container;
  1. 從項(xiàng)目中刪除了某個(gè)目錄、文件以后着撩,編譯出現(xiàn)警告信息:
    ld: warning: directory not found for option“XXXXXX”
    解決辦法:

  2. 選擇工程诅福,選中 TARGETS 中的目標(biāo)工程

  3. 選擇 Build Settings 菜單

  4. 查找 Library Search PathsFramework Search Paths,刪掉編譯報(bào) warning 的路徑即可拖叙。

  5. 統(tǒng)一收起鍵盤:

UIApplication.shared.keyWindow?.endEditing(true);
  1. 動(dòng)態(tài)創(chuàng)建控制器
let vcs = [RunLoopViewController.self, CDrawViewController.self] as [UIViewController.Type];
let vc = self.vcs[indexPath.row].init()    // 創(chuàng)建控制器
let vcString = NSStringFromClass(self.vcs[indexPath.row])    // 
  1. 設(shè)置 UITableView 中的 cell分隔線鋪滿整個(gè) cell
let stView = UITableView();
stView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
  1. 動(dòng)態(tài)修改 tableFooterView 的高度
self.footview.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: heightOfFooterView);
self.tableView.tableFooterView = self.footview;    // 需要重新給 tableFooterView 賦值
  1. 獲取 UILabel 設(shè)置 text 后的大忻ト蟆:
label.intrinsicContentSize
  1. UIButton 添加子視圖后無(wú)法響應(yīng)事件的處理:
let btn = UIButton();
let subView = UIView(frame: btn.bounds);
subView.isUserInteractionEnabled = false;     // 將子視圖的用戶交互禁止趴泌,這樣 UIButton 就能繼續(xù)響應(yīng)事件
btn.addSubview(subView);
  1. 使用 UISearchController 導(dǎo)致的黑屏問(wèn)題黄痪,在使用 UISearchControllerUIViewControllerviewDidLoad 添加:
self.definesPresentationContext = true
  1. ?自定義 UISearchBar 中的 UITextField 無(wú)效:必須確保 UISearchBarsearchBarStyleprominent ,當(dāng)其值為 minimal 時(shí)汗洒,自定義 UITextField 無(wú)效。

  2. 手動(dòng)取消 UISearchController

searchController.isActive = false
  1. 子控件(比如按鈕)超出父視圖部分無(wú)法響應(yīng)事件崩溪,在父視圖添加以下代碼(其思路是遍歷父視圖的所有子視圖浅役,并判斷觸發(fā)事件的點(diǎn)是否在子視圖的bounds內(nèi)如果在就返回這個(gè)子視圖。):
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    var view = super.hitTest(point, with: event);
    guard view == nil else { return view }
    for subView in self.subviews {
        let p = subView.convert(point, from: self);
        if subView.bounds.contains(p) {
            view = subView;
        }
    }
    return view;
}
  1. Xcode 無(wú)法在高于某系統(tǒng)的真機(jī)上運(yùn)行:This iPhone 6 is running iOS 10.1 (14B55或者14B72), which may not be supported by this version of Xcode
    把升級(jí)包放在路徑:應(yīng)用程序(xcode)-右鍵-顯示包內(nèi)容 /Developer/Platforms/iPhoneOS.platform/DeviceSupport

  2. 在控制器 A 中伶唯,push 展示 控制器 B觉既,這時(shí)要隱藏控制器 B 的返回按鈕的文本,需要在控制器 A 中添加以下代碼乳幸,而不是在控制器 B 中瞪讼,因?yàn)?控制器 B 中的返回按鈕實(shí)際是控制器 A 的:

self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
  1. 設(shè)置導(dǎo)航欄標(biāo)題:

方式一:

self.title = "標(biāo)題"          // 當(dāng)控制器處于 UITabbarViewController 中時(shí),對(duì)應(yīng)的 Tabbar 項(xiàng)也會(huì)顯示該標(biāo)題

方式二:

self.navigationItem.title = "標(biāo)題"          // 這樣設(shè)置的話粹断,即使當(dāng)控制器處于 UITabbarViewController 中時(shí)符欠,對(duì)應(yīng)的 Tabbar 項(xiàng)也不會(huì)顯示該標(biāo)題
  1. 設(shè)置導(dǎo)航欄返回按鈕圖片:在創(chuàng)建導(dǎo)航欄的時(shí)候添加以下代碼
// 繪制圖片,主要是原始圖片問(wèn)題瓶埋,可以跳過(guò)此步
UIGraphicsBeginImageContextWithOptions(image.size, false, 0)
image.draw(at: CGPoint(x: -10, y: 10))
var backImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
// 設(shè)置渲染模式背亥,不設(shè)置的話,會(huì)使用系統(tǒng)默認(rèn)顏色
backImage = backImage.withRenderingMode(.alwaysOriginal);
// 設(shè)置返回按鈕圖片
self.navigationController?.navigationBar.backIndicatorImage = backImage;
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage;
  1. UITableViewCell 被點(diǎn)擊時(shí)悬赏,subviews 消失狡汉,這是因?yàn)楫?dāng) UITableViewCell 被點(diǎn)擊時(shí)會(huì)改變它內(nèi)部的 subviews 的背景色,因此重寫(xiě) UITableViewCell 以下兩個(gè)方法即可:
override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    guard selected else { return }
    subview.backgroundColor = subviewColor
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    super.setHighlighted(highlighted, animated: animated)
    guard highlighted else { return }
    subview.backgroundColor = subviewColor
}
  1. swift 3 之后闽颇,函數(shù)有返回值沒(méi)有被使用的時(shí)候會(huì)報(bào)警告盾戴,在該函數(shù)前加 @discardableResult 可以讓編譯器不報(bào)警告

  2. 多線程

  3. 串行

    • 同步,在當(dāng)前線程中按順序執(zhí)行兵多,同時(shí)阻塞當(dāng)前線程
    • 異步,新開(kāi)線程,但僅新開(kāi)一個(gè)線程,所有執(zhí)行的任務(wù)都在同一個(gè)新開(kāi)的線程中順序執(zhí)行,不會(huì)阻塞當(dāng)前線程
  4. 并發(fā)

    • 同步尖啡,在當(dāng)前線程中順序執(zhí)行,同時(shí)阻塞當(dāng)前線程剩膘。(這個(gè)運(yùn)行結(jié)果和串行隊(duì)列衅斩,同步執(zhí)行是一模一樣的。 因?yàn)橥饺蝿?wù)的概念就是按順序執(zhí)行怠褐,后面都要等畏梆。言外之意就是不允許多開(kāi)線程。 同步和異步則是決定開(kāi)一條還是開(kāi)多條奈懒。)
    • 異步,每一個(gè) async 新開(kāi)一個(gè)線程(也可能多個(gè) async 共有一個(gè)線程奠涌,具體看系統(tǒng)分配)并發(fā)執(zhí)行,不會(huì)阻塞當(dāng)前線程
  5. 總結(jié)

    • 同步/異步?jīng)Q定開(kāi)不開(kāi)新線程;
    • 只有并發(fā)異步內(nèi)的任務(wù)是并發(fā)執(zhí)行的磷杏;
    • 其他的都是順序執(zhí)行溜畅;
    • 主隊(duì)列是一個(gè)串行隊(duì)列,全局隊(duì)列是一個(gè)并行隊(duì)列极祸;
    • 異步串行隊(duì)列添加的任務(wù)按添加的順序執(zhí)行,在一些情況可以用來(lái)當(dāng)鎖,比如多線程中對(duì)數(shù)組的操作;慈格;
  6. 使用 for in 操作序列:

// 只對(duì)非 nil 值進(jìn)行循環(huán)
for case let item? in seq { 
    // i 將是 Int 值,而不是 Int? 
    print(item)
}
或
for case let .some(item) in seq { 
    // i 將是 Int 值,而不是 Int? 
    print(item)
}
// 只對(duì) nil 值進(jìn)行循環(huán) 
for case nil in seq { 
    // 將對(duì)每個(gè) nil 執(zhí)行一次
    print("No value") 
}
let j=5 
if case0..<10=j{
    print("\(j) 在范圍內(nèi)") 
}//5在范圍內(nèi)

持續(xù)更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怠晴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子浴捆,更是在濱河造成了極大的恐慌蒜田,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汤功,死亡現(xiàn)場(chǎng)離奇詭異物邑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)滔金,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門色解,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人餐茵,你說(shuō)我怎么就攤上這事科阎。” “怎么了忿族?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵锣笨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我道批,道長(zhǎng)错英,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任隆豹,我火速辦了婚禮椭岩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘璃赡。我一直安慰自己判哥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布碉考。 她就那樣靜靜地躺著塌计,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侯谁。 梳的紋絲不亂的頭發(fā)上锌仅,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音良蒸,去河邊找鬼技扼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嫩痰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窍箍,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼串纺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼丽旅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纺棺,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榄笙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后祷蝌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體茅撞,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年巨朦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了米丘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糊啡,死狀恐怖拄查,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棚蓄,我是刑警寧澤堕扶,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站梭依,受9級(jí)特大地震影響稍算,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜役拴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一糊探、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扎狱,春花似錦侧到、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至污抬,卻和暖如春汞贸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背印机。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工矢腻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人射赛。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓多柑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親楣责。 傳聞我的和親對(duì)象是個(gè)殘疾皇子竣灌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)聂沙、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評(píng)論 4 62
  • “等等初嘹!”潘朵拉進(jìn)入電梯及汉,里面是明媚。兩人互相看了一眼屯烦。 “謝謝坷随。”潘朵拉友好地說(shuō)驻龟。 明媚沒(méi)有理睬温眉,一臉清高,一身...
    魔寧閱讀 363評(píng)論 0 1
  • 我不知道這算不算得上是美好的相遇…… 樹(shù)葉迅脐,開(kāi)始枯萎了芍殖,西風(fēng),開(kāi)始蕭瑟了谴蔑,而我們豌骏,相遇了…… 就暫且把它叫做“邂逅...
    陳大仙兒閱讀 561評(píng)論 0 1
  • 總不能 流血就喊痛 怕黑就開(kāi)燈 想念就聯(lián)系 疲憊就放空 被孤立就討好 脆弱就想家 不要被現(xiàn)在而蒙蔽雙眼 終究是要長(zhǎng)...
    張萌萌Sophie閱讀 156評(píng)論 0 0
  • 文丨膜小欣 圖丨網(wǎng)絡(luò) 這是2015年8月8日寫(xiě)的話題:《你與父母40年》——原創(chuàng) 小E填高考志愿的那天,她做了一...
    膜小欣閱讀 280評(píng)論 0 0