- UITextView 中的文字默認(rèn)并不是從最上面開(kāi)始,在 UITextView 所在的 UIViewController中添加:
self.automaticallyAdjustsScrollViewInsets = false;
-
UITableView
自動(dòng)隱藏鍵盤:
tableView.keyboardDismissMode = .onDrag
- 設(shè)置
UITableView
中的Cell
選中打鉤的顏色:
tableView.tintColor = .red
- 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ě)。
- 靜音模式下播放音頻伸刃,最好在
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)
}
}
- 自定義 UITableViewCell 選中時(shí)的顏色
/**
設(shè)置選中背景色
- parameter color: 背景色
*/
public func setSelectColor(color: UIColor) {
let backgroundView = UIView();
backgroundView.backgroundColor = color;
self.selectedBackgroundView = backgroundView;
}
PS:self.selectionStyle
的值不能為.None
乔询。
- 判斷
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)
}
}
-
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)
}
- 給 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;
}
- 震動(dòng)
/**
震動(dòng),在真機(jī)上:設(shè)置/聲音 中開(kāi)啟響鈴/震動(dòng)選項(xiàng)開(kāi)啟后才能震動(dòng)
*/
public class func shark() {
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate));
}
- 打開(kāi) iPod
/**
打開(kāi) iPod
*/
public class func openIpod() {
UIApplication.sharedApplication().openURL(NSURL(string: "music://")!);
}
-
App 國(guó)際化時(shí)短纵,有時(shí)我們第一次安裝APP時(shí)不想默認(rèn)跟隨系統(tǒng),那么可以通過(guò)Xcode的scheme來(lái)指定特定語(yǔ)言
讓 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;
}
- 應(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 {
}
如果20秒內(nèi)無(wú)法啟動(dòng)程序的話报破,
iOS
檢測(cè)計(jì)時(shí)器就會(huì)終止你的應(yīng)用UIImage
的+imageNamed:
方法可避免延時(shí)加載悠就,不像+imageWithContentsOfFile:
(和其他別的UIImage
加載方法),這個(gè)方法會(huì)在加載圖片之后立刻進(jìn)行解壓充易。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;
}
- 獲取視頻的每秒幀數(shù)
fps
和 視頻的長(zhǎng)度duration
:
let asset = AVAsset(URL: NSURL(fileURLWithPath: "videoPath"));
let fps = asset.tracksWithMediaType(AVMediaTypeVideo)[0].nominalFrameRate;
let duration = CMTimeGetSeconds(asset.duration);
- 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
}
})
}
}
- App 運(yùn)行中不鎖屏:
UIApplication.sharedApplication().idleTimerDisabled = true;
禁止
oc
文件使用ARC
:-fno-objc-arc
Swift
獲取對(duì)象的引用次數(shù):CFGetRetainCount(obj)
禁止
UIButton
在按下時(shí)有動(dòng)態(tài)陰影:
button.adjustsImageWhenHighlighted = false;
- 隱藏導(dǎo)航欄的返回按鈕:
self.navigationItem.hidesBackButton = true;
- 隱藏導(dǎo)航欄下影線:
self.navigationController?.navigationBar.shadowImage = UIImage();
- 設(shè)置導(dǎo)航欄中間為圖片:
self.navigationItem.titleView = UIImageView(image: UIImage(named: "titleImage"));
- 導(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
- 機(jī)型與屏幕尺寸的對(duì)應(yīng):
- 4s_3.5inch
- 5s_4inch
- 6_4.7inch
- 6+_5.5inch
模擬器截圖時(shí)梭冠,必須設(shè)置分辨率為100%(Simulator > Window > Scale > 100%)
UIView 中添加定時(shí)器時(shí)導(dǎo)致內(nèi)存泄露處理:
override func willMoveToWindow(newWindow: UIWindow?) {
super.willMoveToWindow(newWindow);
if (newWindow == nil) {
self.updateTimer.invalidate();
}
}
- UITextfiled 設(shè)置 placehold 字體顏色:
self.passwdTextIpt.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("login_passwd", comment: ""), attributes: [NSForegroundColorAttributeName: UIColor(white: 1.0, alpha: 0.4)]);
使用自定義字體
-
將目標(biāo)字體拖入目標(biāo)項(xiàng)目;
-
在 Info.plist 文件中設(shè)置目標(biāo)字體改备;
-
將字體添加到 Copy Bundle Resources控漠;
使用字體:
UIFont(name: fontname, size: fontsize);
設(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);
}
- UIImage 顯示與圖片不同,設(shè)置其渲染模式即可:
UIImage(named: imageName)!.imageWithRenderingMode(.AlwaysOriginal);
設(shè)置狀態(tài)欄背景樣式無(wú)效:
在
Info.plist
文件中設(shè)置View controller-based status bar appearance
為No
悬钳;在
Appdelegate.swift
文件中設(shè)置UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.Default;
隱藏導(dǎo)航欄返回按鈕:
self.navigationItem.hidesBackButton = true;
- 使用 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");
- 添加陰影
view.layer.shadowColor = UIColor.blackColor().CGColor;
view.layer.shadowOffset = CGSizeMake(0, 0);
view.layer.shadowOpacity = 0.25;
view.layer.shadowRadius = 6;
- 檢查 API 可用性
if #available(iOS 9.0, *) {
let store = CNContactStore()
} else {
// 舊版本的情況
}
- swift 中將 Unmanaged<CGImage> 轉(zhuǎn)化為 UIImage
let unCGimage:Unmanaged<CGImage> = defaultRepresentation.fullResolutionImage();
let image = unCGimage.takeUnretainedValue())
- 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;
設(shè)置 App 沙盒內(nèi)的 Document 文件夾可以被其他軟件共享(各類手機(jī)助手):
在 Info.plist 文件中 添加Application supports iTunes file sharing
碉渡,并設(shè)置其值為YES
播放系統(tǒng)拍照時(shí)的 咔嚓聲(本質(zhì)就是播放系統(tǒng)聲音):
let soundID: SystemSoundID = 1108; //! 1108 就是拍照的系統(tǒng)聲音編號(hào),要播放其他的聲音可以到網(wǎng)上搜索對(duì)應(yīng)的編號(hào)
AudioServicesPlayAlertSound(soundID);
-
AudioServicesPlaySystemSound
和AudioServicesPlayAlertSound
的區(qū)別:-
AudioServicesPlaySystemSound
僅僅是播放系統(tǒng)聲音灾测,在靜音模式下不播放爆价; -
AudioServicesPlayAlertSound
當(dāng)設(shè)置了通用/聲音/響鈴模式振動(dòng)
垦巴,播放系統(tǒng)聲音并振動(dòng),否則只播放系統(tǒng)聲音铭段;當(dāng)設(shè)置了通用/聲音/靜音模式振動(dòng)
骤宣,振動(dòng),否則不播放系統(tǒng)聲音序愚。
-
當(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");
- 調(diào)用 AVPlayer 的
seekToTime
接口時(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);
使用
NSDateFormatter.dateFromString
總是返回nil
爸吮,原因可能是你的時(shí)間格式是12小時(shí)制而你的值是24小時(shí)制
芬膝,將hh:mm:ss
改成HH:mm:ss
即可。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)
- 指針偏移
let buf:UnsafePointer<UInt8> = CFDataGetBytePtr(rawData)
var r:UInt8 = 0
r = buf.advancedBy(i+0).memory
- 字符串保留特定字符(以下例子保留字母):
let notAllowedCharactersSet = NSCharacterSet(charactersInString: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdedghijklmnopqrsquvwxyz").invertedSet
let filterStr = (str.componentsSeparatedByCharactersInSet(notAllowedCharactersSet) as NSArray).componentsJoinedByString("")
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()
}
}
-
??
操作符
在 Swift 中,有一個(gè)非常有用的操作符桐早,可以用來(lái)快速地對(duì)nil
進(jìn)行條件判斷癣缅,那就是??
。這個(gè)操作符可以判斷輸入并在當(dāng)左側(cè)的值是非nil
的 Optional 值時(shí)返回其 value哄酝,當(dāng)左側(cè)是nil
時(shí)返回右側(cè)的值友存,比如:
var level : Int?
var startLevel = 1
var currentLevel = level ?? startLevel
- App 在啟動(dòng)界面停留特定時(shí)間:
NSThread.sleepForTimeInterval(3.0); // 3.0 表示 3 秒
- 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()
UIButton
中的文本
和圖片
默認(rèn)是水平對(duì)齊使用
單元測(cè)試
時(shí)顯示Module 'CTest' was not compiled for testing
:
在Build Settings
中Enable Testability
設(shè)置為YES
-
Xcode 8
控制臺(tái)輸出信息太多解決方法:Edit Scheme
->Run
->Arguments
陶衅, 在Environment Variables
里邊添加OS_ACTIVITY_MODE
屡立,值設(shè)置為disable
設(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;
- 設(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)
}()
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
了的止。給視圖及之上的子控件添加陰影:
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;
從項(xiàng)目中刪除了某個(gè)目錄、文件以后着撩,編譯出現(xiàn)警告信息:
ld: warning: directory not found for option“XXXXXX”
解決辦法:選擇工程诅福,選中
TARGETS
中的目標(biāo)工程選擇
Build Settings
菜單查找
Library Search Paths
和Framework Search Paths
,刪掉編譯報(bào)warning
的路徑即可拖叙。統(tǒng)一收起鍵盤:
UIApplication.shared.keyWindow?.endEditing(true);
- 動(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]) //
- 設(shè)置
UITableView
中的cell
的分隔線
鋪滿整個(gè)cell
let stView = UITableView();
stView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
- 動(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 賦值
- 獲取
UILabel
設(shè)置text
后的大忻ト蟆:
label.intrinsicContentSize
-
UIButton
添加子視圖后無(wú)法響應(yīng)事件的處理:
let btn = UIButton();
let subView = UIView(frame: btn.bounds);
subView.isUserInteractionEnabled = false; // 將子視圖的用戶交互禁止趴泌,這樣 UIButton 就能繼續(xù)響應(yīng)事件
btn.addSubview(subView);
- 使用
UISearchController
導(dǎo)致的黑屏問(wèn)題黄痪,在使用UISearchController
的UIViewController
的viewDidLoad
添加:
self.definesPresentationContext = true
?自定義
UISearchBar
中的UITextField
無(wú)效:必須確保UISearchBar
的searchBarStyle
為prominent
,當(dāng)其值為minimal
時(shí)汗洒,自定義UITextField
無(wú)效。手動(dòng)取消
UISearchController
:
searchController.isActive = false
- 子控件(比如按鈕)超出父視圖部分無(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;
}
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
在控制器
A
中伶唯,push
展示 控制器B
觉既,這時(shí)要隱藏控制器B
的返回按鈕的文本,需要在控制器A
中添加以下代碼乳幸,而不是在控制器B
中瞪讼,因?yàn)?控制器B
中的返回按鈕實(shí)際是控制器A
的:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)
- 設(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)題
- 設(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;
-
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
}
swift 3
之后闽颇,函數(shù)有返回值沒(méi)有被使用的時(shí)候會(huì)報(bào)警告盾戴,在該函數(shù)前加@discardableResult
可以讓編譯器不報(bào)警告-
串行
- 同步,在當(dāng)前線程中按順序執(zhí)行兵多,同時(shí)阻塞當(dāng)前線程
- 異步,新開(kāi)線程,但僅新開(kāi)一個(gè)線程,所有執(zhí)行的任務(wù)都在同一個(gè)新開(kāi)的線程中順序執(zhí)行,不會(huì)阻塞當(dāng)前線程
-
并發(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)前線程
-
總結(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ù)組的操作;慈格;
使用
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ù)更新