- 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 = true
extension 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/here
myapp://?foo=1&bar=2
myapp://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 = .all
navigationController?.navigationBar.isTranslucent = false
/// rootView 的布局从(0,64)开始
edgesForExtendedLayout = .all
navigationController?.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<CGImage> 转化为 UIImage
let unCGimage:Unmanaged<CGImage> = 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<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 中,有一个非常有用的操作符,可以用来快速地对nil
进行条件判断,那就是??
。这个操作符可以判断输入并在当左侧的值是非nil
的 Optional 值时返回其 value,当左侧是nil
时返回右侧的值,比如:
var level : Int?
var startLevel = 1
var 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("<p>Some Text</p>", 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在范围内
持续更新