- UITextView 中的文字默认并不是从最上面开始,在 UITextView 所在的 UIViewController中添加:
self.automaticallyAdjustsScrollViewInsets = false;复制代码
UITableView
自动隐藏键盘:
tableView.keyboardDismissMode = .onDrag复制代码
- 设置
UITableView
中的Cell
选中打钩的颜色:
tableView.tintColor = .red复制代码
- UIButton 在边缘的时候没有高亮响应,重写 UIButton 的 pointInside函数:
/** 解决按钮在边缘的时候被按下时没有显示高亮 - parameter point: 按下的位置 - parameter event: 目标事件 - returns: 是否在内部 */ 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 重写该函数,而不是extension UIButton
,因为这样会使工程中用到的所有的 UIButton 都被重写。
- 静音模式下播放音频,最好在
didFinishLaunchingWithOptions
中进行调用
/** 静音模式下仍可以播放音频 */ 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 选中时的颜色
/** 设置选中背景色 - parameter color: 背景色 */ public func setSelectColor(color: UIColor) { let backgroundView = UIView(); backgroundView.backgroundColor = color; self.selectedBackgroundView = backgroundView; }复制代码
PS:self.selectionStyle
的值不能为.None
。
- 判断
UIScrollView
是否滚动结束:
/// 记录手指放开滑动时 scrollView 的内容偏移fileprivate var offset = CGPoint.zero// 记录当前滑动状态fileprivate var isScrollEnd = trueextension Controller: UIScrollViewDelegate { public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { // 开始滚动,记录状态 isScrollEnd = false } public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { // 记录手指放开滑动时 scrollView 的内容偏移 offset = scrollView.contentOffset // 使用 perform 延迟检测 scrollView 内容偏移, // 1. 如果手指放开滑动后 scrollView 继续滑动,由于 perform 运行在 NSDefaultRunLoopMode 模式, // 因此在 scrollView 继续滑动的情况下不会开始定时,因此不会在设置的延时后调用; // 2. 如果手指放开滑动后 scrollView 停止滑动,则会在设置的延时后调用 checkScrollEnd; perform(#selector(self.checkScrollEnd), with: nil, afterDelay: 0.020) } public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { // 当手指放开滑动后 scrollView 继续滑动,取消 checkScrollEnd 的调用; NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(self.checkScrollEnd), object: nil) // 结束滚动,记录状态 isScrollEnd = true } internal func checkScrollEnd() { // 判断 scrollView 当前内容偏移与手指松开时的内容偏移是否相同, isScrollEnd = (offset == tableView.contentOffset) }}复制代码
UITableView
添加UITextField
时键盘处理
/// 添加监听public override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 监听键盘的弹出 NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: NSNotification.Name.UIKeyboardDidShow, object: nil) // 监听键盘的隐藏 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)}/// 移除监听public override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver(self)}/// 键盘弹出处理public func keyboardDidShow(_ notification : Notification) { // 获取当前活跃的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 // 设置底部偏移,保证键盘弹出后仍能滑动到底部 self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0) // 当 offset 小于 0 时,表示空间已满足 guard offset > 0 else { return } // 加上 tableView 当前偏移 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; }复制代码
- 震动
/** 震动,在真机上:设置/声音 中开启响铃/震动选项开启后才能震动 */ public class func shark() { AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate)); }复制代码
- 打开 iPod
/** 打开 iPod */ public class func openIpod() { UIApplication.sharedApplication().openURL(NSURL(string: "music://")!); }复制代码
-
App 国际化时,有时我们第一次安装APP时不想默认跟随系统,那么可以通过Xcode的scheme来指定特定语言
-
让 UITableView 在没有数据时不能滚动
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { self.tableView.scrollEnabled = (data.count > 0); return data.count;}复制代码
- 应用内打开其他 App 在
Info.plist
文件中设置URL types
: 之后就可以使用下面的模式来发送一个URL:
myapp://myapp://some/path/heremyapp://?foo=1&bar=2myapp://some/path/here?foo=1&bar=2复制代码
然后,App 的UIApplicationDelegate
会收到一个消息。若你想自己处理该URL,可以重载下面这个方法:
func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {}复制代码
-
如果20秒内无法启动程序的话,
iOS
检测计时器就会终止你的应用 -
UIImage
的+imageNamed:
方法可避免延时加载,不像+imageWithContentsOfFile:
(和其他别的UIImage
加载方法),这个方法会在加载图片之后立刻进行解压。 -
App 播放视频时进入后台让视频继续播放,有两种方法可以实现:
第一种、 对目标视频对象的视频轨进行以下处理:
let playerItem = AVPlayerItem(URL: NSURL(string: "videoUrl")!);let tracks = playerItem.tracks;for track in tracks { if (track.assetTrack.hasMediaCharacteristic(AVMediaCharacteristicVisual)) { track.enabled = false; }}复制代码
第二种、 在进入后台前将目标视频渲染层设为 nil
,在恢复到前台时重新设置:
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;}复制代码
- 获取视频的每秒帧数
fps
和 视频的长度duration
:
let asset = AVAsset(URL: NSURL(fileURLWithPath: "videoPath"));let fps = asset.tracksWithMediaType(AVMediaTypeVideo)[0].nominalFrameRate;let duration = CMTimeGetSeconds(asset.duration);复制代码
- App 进入后台仍然继续运行:
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 运行中不锁屏:
UIApplication.sharedApplication().idleTimerDisabled = true;复制代码
-
禁止
oc
文件使用ARC
:-fno-objc-arc
-
Swift
获取对象的引用次数:CFGetRetainCount(obj)
-
禁止
UIButton
在按下时有动态阴影:
button.adjustsImageWhenHighlighted = false;复制代码
- 隐藏导航栏的返回按钮:
self.navigationItem.hidesBackButton = true;复制代码
- 隐藏导航栏下影线:
self.navigationController?.navigationBar.shadowImage = UIImage();复制代码
- 设置导航栏中间为图片:
self.navigationItem.titleView = UIImageView(image: UIImage(named: "titleImage"));复制代码
- 导航栏相关属性效果
/// rootView 的布局从(0,0)开始edgesForExtendedLayout = .allnavigationController?.navigationBar.isTranslucent = false/// rootView 的布局从(0,64)开始edgesForExtendedLayout = .allnavigationController?.navigationBar.isTranslucent = true复制代码
- 机型与屏幕尺寸的对应:
- 4s_3.5inch
- 5s_4inch
- 6_4.7inch
- 6+_5.5inch
-
模拟器截图时,必须设置分辨率为100%(Simulator > Window > Scale > 100%)
-
UIView 中添加定时器时导致内存泄露处理:
override func willMoveToWindow(newWindow: UIWindow?) { super.willMoveToWindow(newWindow); if (newWindow == nil) { self.updateTimer.invalidate(); }}复制代码
- UITextfiled 设置 placehold 字体颜色:
self.passwdTextIpt.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("login_passwd", comment: ""), attributes: [NSForegroundColorAttributeName: UIColor(white: 1.0, alpha: 0.4)]);复制代码
-
使用自定义字体
-
将目标字体拖入目标项目;
-
在 Info.plist 文件中设置目标字体;
-
将字体添加到 Copy Bundle Resources;
-
使用字体:
UIFont(name: fontname, size: fontsize);
-
设置 UITextfiled 文字偏移:
self.userIdTextIpt.layer.sublayerTransform = CATransform3DMakeTranslation(10, 0, 0);复制代码
或者重写 UITextfiled :
override func textRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, 44, 0);}override func editingRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, 44, 0);}复制代码
- UIImage 显示与图片不同,设置其渲染模式即可:
UIImage(named: imageName)!.imageWithRenderingMode(.AlwaysOriginal);复制代码
-
设置状态栏背景样式无效:
-
在
Info.plist
文件中设置View controller-based status bar appearance
为No
; -
在
Appdelegate.swift
文件中设置UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.Default;
-
隐藏导航栏返回按钮:
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 转化为 UIImage
let unCGimage:Unmanaged= defaultRepresentation.fullResolutionImage();let image = unCGimage.takeUnretainedValue())复制代码
- CADisplayLink 使用完成后内存无法被释放:
self.displaylink = CADisplayLink(target: self, selector: #selector(SCGifView.changeKeyFrame))self.displaylink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)复制代码
以上在我一个工程中使用到的,在测试的时候,发现其内存无法被释放,检查看发现需要手动调用以下代码来完成释放:
self.displaylink?.removeFromRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes);self.displaylink?.invalidate();self.displaylink = nil;复制代码
-
设置 App 沙盒内的 Document 文件夹可以被其他软件共享(各类手机助手): 在 Info.plist 文件中 添加
Application supports iTunes file sharing
,并设置其值为YES
-
播放系统拍照时的 咔嚓声(本质就是播放系统声音):
let soundID: SystemSoundID = 1108; //! 1108 就是拍照的系统声音编号,要播放其他的声音可以到网上搜索对应的编号AudioServicesPlayAlertSound(soundID);复制代码
-
AudioServicesPlaySystemSound
和AudioServicesPlayAlertSound
的区别:AudioServicesPlaySystemSound
仅仅是播放系统声音,在静音模式下不播放;AudioServicesPlayAlertSound
当设置了通用/声音/响铃模式振动
,播放系统声音并振动,否则只播放系统声音;当设置了通用/声音/静音模式振动
,振动,否则不播放系统声音。
-
当 UIButton 即有文字又有图像时,只让图像旋转:
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");复制代码
- 调用 AVPlayer 的
seekToTime
接口时间不对,将
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
,原因可能是你的时间格式是12小时制而你的值是24小时制
,将hh:mm:ss
改成HH:mm:ss
即可。 -
swift
中结构体与结构体指针的使用,SMsgAVIoctrlSetPlayVolumeReq
为结构体,IOTYPE_USER_IPCAM_AUDIO_PLAY_VOLUME_SETTING_REQ
为枚举变量:
let cmd = UnsafeMutablePointer(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 (cmd), dataSize: sizeof(SMsgAVIoctrlSetPlayVolumeReq)) free(cmd)复制代码
- 指针偏移
let buf:UnsafePointer= CFDataGetBytePtr(rawData)var r:UInt8 = 0r = buf.advancedBy(i+0).memory复制代码
- 字符串保留特定字符(以下例子保留字母):
let notAllowedCharactersSet = NSCharacterSet(charactersInString: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdedghijklmnopqrsquvwxyz").invertedSetlet 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 中,有一个非常有用的操作符,可以用来快速地对nil
进行条件判断,那就是??
。这个操作符可以判断输入并在当左侧的值是非nil
的 Optional 值时返回其 value,当左侧是nil
时返回右侧的值,比如:
var level : Int?var startLevel = 1var currentLevel = level ?? startLevel复制代码
- App 在启动界面停留特定时间:
NSThread.sleepForTimeInterval(3.0); // 3.0 表示 3 秒复制代码
- swift 中根据字符串创建对象:
//动态获取命名空间: let nameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String //根据命名空间和传过来的控制器名字获取控制器的类 let controllerClass:AnyClass = NSClassFromString(nameSpace + "." + controllerName)! //告诉编译器真实的控制器类型,比如这个控制器本质是UITableViewController则: let realClass = controllerClass as! UITableViewController.Type //实例化这个控制器出来 let childController = realClass.init()复制代码
-
UIButton
中的文本
和图片
默认是水平对齐 -
使用
单元测试
时显示Module 'CTest' was not compiled for testing
: 在Build Settings
中Enable Testability
设置为YES
-
Xcode 8
控制台输出信息太多解决方法:Edit Scheme
->Run
->Arguments
, 在Environment Variables
里边添加OS_ACTIVITY_MODE
,值设置为disable
-
设置
WKWebView
的字体大小:
//创建网页配置对象 let config = WKWebViewConfiguration(); // 创建设置对象 let preference = WKPreferences(); // 设置字体大小(最小的字体大小) preference.minimumFontSize = 60; // 设置偏好设置对象 config.preferences = preference; // 创建WKWebView let webView = WKWebView(frame: self.view.bounds, configuration: config); webView.loadHTMLString("Some Text
", baseURL: nil) return webView;复制代码
- 设置
WKWebView
根据屏幕宽度调整内容大小:
/// 网络浏览视图 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) //创建网页配置对象 let config = WKWebViewConfiguration() config.userContentController = userContentController // 创建设置对象 let preference = WKPreferences() // 设置字体大小(最小的字体大小) preference.minimumFontSize = 18 // 设置偏好设置对象 config.preferences = preference return WKWebView(frame: .zero, configuration: config) }()复制代码
-
lazy
属性本质上是一个闭包,闭包中的表达式只会调用一次。需要强调的是,虽然这个闭包中捕获了self
,但是这样做并不会导致循环引用,猜测是swift
自动把self
标记为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;复制代码
-
从项目中删除了某个目录、文件以后,编译出现警告信息:
ld: warning: directory not found for option“XXXXXX”
解决办法: -
选择工程,选中
TARGETS
中的目标工程 -
选择
Build Settings
菜单 -
查找
Library Search Paths
和Framework Search Paths
,删掉编译报warning
的路径即可。 -
统一收起键盘:
UIApplication.shared.keyWindow?.endEditing(true);复制代码
- 动态创建控制器
let vcs = [RunLoopViewController.self, CDrawViewController.self] as [UIViewController.Type];let vc = self.vcs[indexPath.row].init() // 创建控制器let vcString = NSStringFromClass(self.vcs[indexPath.row]) // 复制代码
- 设置
UITableView
中的cell
的分隔线
铺满整个cell
let stView = UITableView();stView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);复制代码
- 动态修改 tableFooterView 的高度
self.footview.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: heightOfFooterView);self.tableView.tableFooterView = self.footview; // 需要重新给 tableFooterView 赋值复制代码
- 获取
UILabel
设置text
后的大小:
label.intrinsicContentSize复制代码
UIButton
添加子视图后无法响应事件的处理:
let btn = UIButton();let subView = UIView(frame: btn.bounds);subView.isUserInteractionEnabled = false; // 将子视图的用户交互禁止,这样 UIButton 就能继续响应事件btn.addSubview(subView);复制代码
- 使用
UISearchController
导致的黑屏问题,在使用UISearchController
的UIViewController
的viewDidLoad
添加:
self.definesPresentationContext = true复制代码
-
自定义
UISearchBar
中的UITextField
无效:必须确保UISearchBar
的searchBarStyle
为prominent
,当其值为minimal
时,自定义UITextField
无效。 -
手动取消
UISearchController
:
searchController.isActive = false复制代码
- 子控件(比如按钮)超出父视图部分无法响应事件,在父视图添加以下代码(其思路是遍历父视图的所有子视图,并判断触发事件的点是否在子视图的bounds内如果在就返回这个子视图。):
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
无法在高于某系统的真机上运行:This iPhone 6 is running iOS 10.1 (14B55或者14B72), which may not be supported by this version of Xcode
: 把升级包放在路径:应用程序(xcode)-右键-显示包内容 /Developer/Platforms/iPhoneOS.platform/DeviceSupport
-
在控制器
A
中,push
展示 控制器B
,这时要隐藏控制器B
的返回按钮的文本,需要在控制器A
中添加以下代码,而不是在控制器B
中,因为 控制器B
中的返回按钮实际是控制器A
的:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.plain, target:nil, action:nil)复制代码
- 设置导航栏标题:
方式一:
self.title = "标题" // 当控制器处于 UITabbarViewController 中时,对应的 Tabbar 项也会显示该标题复制代码
方式二:
self.navigationItem.title = "标题" // 这样设置的话,即使当控制器处于 UITabbarViewController 中时,对应的 Tabbar 项也不会显示该标题复制代码
- 设置导航栏返回按钮图片:在创建导航栏的时候添加以下代码
// 绘制图片,主要是原始图片问题,可以跳过此步UIGraphicsBeginImageContextWithOptions(image.size, false, 0)image.draw(at: CGPoint(x: -10, y: 10))var backImage = UIGraphicsGetImageFromCurrentImageContext()!UIGraphicsEndImageContext()// 设置渲染模式,不设置的话,会使用系统默认颜色backImage = backImage.withRenderingMode(.alwaysOriginal);// 设置返回按钮图片self.navigationController?.navigationBar.backIndicatorImage = backImage;self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage;复制代码
UITableViewCell
被点击时,subviews
消失,这是因为当UITableViewCell
被点击时会改变它内部的subviews
的背景色,因此重写UITableViewCell
以下两个方法即可:
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
之后,函数有返回值没有被使用的时候会报警告,在该函数前加@discardableResult
可以让编译器不报警告 -
多线程
-
串行
- 同步,在当前线程中按顺序执行,同时阻塞当前线程
- 异步,新开线程,但仅新开一个线程,所有执行的任务都在同一个新开的线程中顺序执行,不会阻塞当前线程
-
并发
- 同步,在当前线程中顺序执行,同时阻塞当前线程。(这个运行结果和串行队列,同步执行是一模一样的。 因为同步任务的概念就是按顺序执行,后面都要等。言外之意就是不允许多开线程。 同步和异步则是决定开一条还是开多条。)
- 异步,每一个 async 新开一个线程(也可能多个 async 共有一个线程,具体看系统分配)并发执行,不会阻塞当前线程
-
总结
- 同步/异步决定开不开新线程;
- 只有并发异步内的任务是并发执行的;
- 其他的都是顺序执行;
- 主队列是一个串行队列,全局队列是一个并行队列;
- 异步串行队列添加的任务按添加的顺序执行,在一些情况可以用来当锁,比如多线程中对数组的操作;;
-
使用
for in
操作序列:
// 只对非 nil 值进行循环for case let item? in seq { // i 将是 Int 值,而不是 Int? print(item)}或for case let .some(item) in seq { // i 将是 Int 值,而不是 Int? print(item)}// 只对 nil 值进行循环 for case nil in seq { // 将对每个 nil 执行一次 print("No value") }let j=5 if case0..<10=j{ print("\(j) 在范围内") }//5在范围内复制代码
持续更新