Swift 常用技巧

  1. 使xib中的控件距顶部预留出导航栏的宽度:
    在swift文件中的viewDidLoad方法中增加以下语句:
    self.navigationController?.navigationBar.translucent = false

  2. 防止循环引用:
    所谓循环引用,就是指两个类互相持有对方类型的变量,从而导致内存无法正确回收的情况,例如:

class A {var b : B?}
class B {var a : A?}

解决办法为:在某一方的变量定义前加上weak,表示不希望该对象主动去持有对方的变量,例如:

class A {var b : B?}
class B {weak var a : A?}

这样的话,当A被释放之后,B就不会再引用对象A,从而两个对象都可以正确释放

  1. 字符串与变量拼接:
println("location = \(recognizer.locationInView(view).x)")
  1. 在一个Label中设置多种文字颜色:
let length = valueString.characters.count
let mutableString = NSMutableAttributedString(string: "colored String: 
\(valueString)")
mutableString.addAttribute(NSFontAttributeName, value: UIFont.systemOfSize(25), range: NSMakeRange(0, length))
mutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellowColor(), range: NSMakeRange(0, length))
textLabel.attributedText = mutableString
  1. 控件自适应屏幕大小:
let screenWidth = UIScreen.mainScreen().applicationFrame.maxX                 //获取屏幕宽度
let screenHeight = UIScreen.mainScreen().applicationFrame.maxY                //获取屏幕高度
view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)     //设置View的Frame尺寸
  1. 为控件设置圆角和边框:
//为控件设置圆角
view.layer.masksToBounds = true     
//view.clipsToBounds = true
view.layer.cornerRadius = 10

 //设置返回按钮的点击事件
view.layer.borderColor = UIColor.whiteColor().CGColor
view.layer.borderWidth = 5.0
  1. ViewController之间跳转:
let targetView = TargetViewController(nibName: "TargetViewController"
, bundle: nil)
self.presentViewController(targetView, animated: true, completion: nil)     //打开新的页面(不可返回)
self.navigationController?.pushViewController(targetView, animated: true)   //打开下级页面(可以返回)
  1. ViewController返回上一级或关闭:
if (self.navigationController?.popViewControllerAnimated(true) == nil) {     //优先返回上级页面
    self.dismissViewControllerAnimated(true, completion: nil)               //若无法返回上级页面,则关闭此页面
}
  1. 设置键盘返回按钮的样式和点击事件:
    键盘上返回按钮的样式,是根据弹出键盘的TextField来决定的
    修改的方式是在xib中选中textField,设置Return Key的类型即可,如下图
    设置返回按钮的样式

    若需要设置返回按钮的点击事件,则使ViewController继承UITextFieldDelegate,并实现textFieldShouldReturn方法即可
class TestViewController: UIViewController, UITextFieldDelegate{
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self 
    }

    //设置返回按钮的点击事件
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()           //关闭键盘
        //...执行相应操作
        return true
    }
}
  1. 取消手势其他手势的冲突:
class HBFamilyViewController: UIViewController, UIGestureRecognizerDelegate {
     override func viewDidLoad() {
        panGesture = UIPanGestureRecognizer()
        panGesture.addTarget(self, action: Selector("handlePanGesture:"))
        panGesture.delegate = self
     }

     //设置允许手势与其他手势共存
     func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer        
        otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
  1. 判断TableView是否划动到顶部:
tableView.contentOffset.y == 0
  1. 在Swift中使用全局变量:
    首先在AppDelegate中定义一个变量,例如:
var globalString: String?

然后在其他类中获取到AppDelegate,并使用该变量即可,例如:

let app = UIApplication.sharedApplication().delegate as! AppDelegate
app.globalString = "test"
  1. 在Swift中使用泛型:
    Swift中的泛型可以是任意类型,但是必须要在类/方法定义的时候指定<T>
class HBCacheManager<T>: NSObject {
    var databaseDic = Dictionary <String, T> ()
}
  1. 禁止TableView上下划动:
    在xib文件中将bounces的复选框去掉

  2. 从xib文件中加载UIView:

let myView = NSBundle.mainBundle().loadNibNamed("MyView" , owner: nil, options: nil).firstas! MyView
myView.frame = CGRectMake(0, 0, width, height)
parentView.addSubview(missionView)

注意:目标xib文件需要设置Class属性为自定义的UIView文件,如下:


设置UIView的类型
  1. ImageView图片拉伸变形问题的解决:
    修改以下属性:

    修改红框中的属性

    其中:Aspect Fill属性用于解决图片拉伸问题
    Clip Subviews用于解决图片超出控件边缘的问题

  2. 为界面增加毛玻璃效果:
    下面的控件拖出来直接使用即可

    使用UIVisualEffectView

  3. NavigationBar背景透明:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
  1. 设置ViewController和xib文件的关联:
    首先设置xib文件的File’s Owner:

    设置FileOwner

    然后右键点击File’s Owner,指定xib文件的View:
    指定View

  2. 避免xib设置的控件布局错乱的技巧:
    在UIViewController中:
    在viewDidLoad方法中创建控件和获取数据
    在viewDidLayoutSubviews方法中设置控件的Frame

在UIView中:
在awakeFromNib中创建控件
在layoutSubviews方法中设置控件的Frame
*注意!由于layoutSubviews方法很可能会被多次调用,所以不要在该方法中创建控件!

  1. 自动布局控件的优先级:
    Content Hugging Priority:控件防止变大的优先级
    Content Compression Resistance Priority:控件防止变小的优先级

对于UILabel和UIButton等控件,在显示的时候可以根据里面的内容动态设置大小
但是,若一行中并排放置两个Label,并要求两个Label的总长度能够占满屏幕的话
由于Label的长度是根据里面的文字动态变化的,那么就会出现这样的问题:
1、若两个Label的长度总和小于屏幕宽度,那么由哪个Label变宽来占满屏幕?
2、若两个Label的长度总和大于屏幕宽度,那么由哪个Label变窄来让出屏幕?

这样就需要通过这两个属性来进行设置了
1、若两个Label的长度总和小于屏幕宽度,那么由Content Hugging Priority数值较小的Label变宽来占满屏幕
2、若两个Label的长度总和大于屏幕宽度,那么由Content Compression Resistance Priority数值较小的Label变窄来让出屏幕

  1. 设置UIView的位置:
    如果是固定设置UIView的位置,则修改UIView的.center
    如果是临时改变UIView的位置,则修改UIView的.transform

  2. TableView动态设置Cell高度:
    在viewDidLoad方法中将tableView设成动态高度,如下:

tableView.estimatedRowHeight = 100      //这个参数用于提升性能,
tableView.rowHeight = UITableViewAutomaticDimension

如果cell使用xib来定义,那么首先需要确保xib中各控件的顶部、底部和高度都设置了约束
其次,如果在代码中为cell中某个控件中添加了子控件,并且想要修改该控件的高度约束的话
那么绝对不要直接修改高度的约束!而是要手动调用updateConstraintsIfNeeded方法,并在该方法中设置控件高度的约束,如

class HBInteractionTableViewCell: UITableViewCell {
    @IBOutlet weak var galleryView: UIView!
    @IBOutlet weak var galleryHeight: NSLayoutConstraint!

    func setImage(imageView: UIImageView) {
        galleryView.addSubview(imageView)

        //注意!下面这行代码一定不能写在这里,否则cell不会自动更新其他控件的高度
        //galleryHeight.constant = imageView.height
 
        //立即触发更新布局
        self.updateConstraintsIfNeeded()
    }

    override func updateConstraintsIfNeeded() {
        galleryHeight.constant = imageSetView.height     //修改高度约束的代码要写在这里
        super.updateConstraintsIfNeeded()
    }
}
  1. 去掉float后面的.0:
NSString(format: "%.0f", lastUploadDate.timeIntervalSince1970 * 1000) as String
  1. 调用bundle中的文件:
    例如bundle的名称为pic.bundle,里面有名为save.jpg和cancel.jpg两个文件
    则调用方法为UIImage(named: "pic.bundle/cancel")

  2. 获取tableView中cell在整个页面中的位置:

let rectInTableView = tableView.rectForRowAtIndexPath(indexPath)
let cellFrame = tableView.convertRect(rectInTableView, toView: self.view)
  1. 在View上(如TextField)增加Loading遮罩:
func addIndicator(view: UIView) {    
  let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray)    
  view.addSubview(activityIndicator)
  activityIndicator.frame = view.bounds      
  activityIndicator.startAnimating()           
  //activityIndicator.removeFromSuperview()   //当执行完毕后,调用此方法移除遮罩
}
  1. 在程序中使用自定义字体:
    首先将.ttf文件拷贝到工程的任意目录下,点选该文件,在右侧Target Membership中选中当前项目,

    一定要注意选中红框中的内容

    然后在xib中查看是否有这个字体,如果有则直接可以使用
    如果没有,则在Finder中打开这个字体,右键 > 使用字体册打开,点击【安装字体】,然后在新打开的窗口中可以看到字体名称:
    红框内即是字体名称

  2. 生成纯色的图片(可用于Button的背景图):

extension UIImage {
    /** 源于色彩的UIImage,可自定义size */
    class func imageWithColor(color: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1), size: CGSize = CGSizeMake(1, 1)) -> UIImage {
        let rect = CGRectMake(0, 0, size.width, size.height)

        //开启一个图形上下文     
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)

        //获取图形上下文
        let context = UIGraphicsGetCurrentContext()
        CGContextSetFillColorWithColor(context, color.CGColor)
        CGContextFillRect(context, rect)              

        //获取图像
        let image = UIGraphicsGetImageFromCurrentImageContext()               

        //关闭上下文      
        UIGraphicsEndImageContext();               
        return image;
    }
}```

30. **为类定义delegate(代理):**

@objcpublic protocol MyDelegate {
func requiredFunc()
optional func optionalFunc()
}


31. **FirstResponder的使用:**
当需要为某个控件或事件注册响应,但又不知道注册给谁的时候
可以注册给FirstResponder,然后在程序中将某个控件注册为响应者,例如:
```textField.becomeFirstResponder()```
这样,当事件被发出后,textField就可以第一时间响应该事件

32. **为TableViewCell增加向右箭头:**
设置TableViewCell的Accessory属性为**Disclosure Indicator**,如下图:
![](http://upload-images.jianshu.io/upload_images/2250628-b5642c0af817e32b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

33. **struct和class的区别:**
struct里面的变量和常量默认是全局访问的,而class里面的变量和常量默认是私有的
如果想要定义一个全局可用的静态常量,则可以定义在struct**里面**,但必须要定义在class**外面**
因此,我们如果想要通过**类名.变量名**的方式来调用一个全局静态变量的话,就需要把这个变量定义在struct中

34. **解决iOS界面设计和开发字体大小不一致的问题:**
iOS开发时,所用的字体单位均为pt,即point
# 
之所以用pt而不是用px,是因为不同的设备屏幕像素密度(PPI)不同
在非Retina屏上,像素密度为72PPI,而在Retina屏上,像素密度则为144PPI
由于Retina屏的像素密度比非Retina屏要高一倍,因此同样的像素值,在Retina屏上显示的大小就要小一半
因此,若将文字大小设成20px,在Retina屏上显示的大小就比非Retina屏上的大小要小一倍
# 
因此,文字的pt值,是保证文字在不同的屏幕上都显示为同样的大小
在不同的设备屏幕上,1pt显示的实际像素,是由屏幕的PPI决定的
在Retina屏上,1pt对应的像素值为1px。如果设备是Retina屏,则为1pt=2px
由于目前iOS主流设备均为Retina屏,因此设计时用144 PPI,就能保证设计出的pt数值与开发时的pt数值完全一致。

35. **解决UITextView左侧和上方空白的问题:**

descriptTextView.contentInset = UIEdgeInsets(top: -8, left: -5, bottom: 0, right: 0)


36. **解决隐藏NavigationBar时动画错乱的问题:**
不要直接设置```navigationController.hidden = true```,而是调用下面的方法:

self.navigationController?.setNavigationBarHidden(true, animated: true)


37. **删除不用的Profile和证书:**
**证书:**打开钥匙串访问,直接删除即可
**Profile:**打开~/Library/MobileDevice/Provisioning Profiles,删除所有文件
*注:~表示当前用户的目录

38. **解决cell中控件尺寸始终不正确的问题:**

self.contentView.setNeedsLayout()
self.contentView.layoutIfNeeded()


39. **为工具栏和NavigationBar预留出空间:**
工具栏的高度为16
NavigationBar的高度为48

40. **代码获取TabbarController当前显示的ViewController:**

let navController = self.selectedViewController as! UINavigationController
let viewController = navController.topViewController!


41. **为UIColor增加透明效果:**

color.colorWithAlphaComponent(0.7)


42. **向ScrollView中添加控件:**

let imageSpaceX:CGFloat = 5.0
let imageSizeX:CGFloat = 50
let imageSizeY:CGFloat = 50

var originX:CGFloat = 0
for index in 0...imageViewList.count-1 {
let view = scrollView.subviews[index]
view.frame = CGRectMake(originX, 0, imageSizeX, imageSizeY)
originX += (imageSizeX + imageSpaceX)
}

scrollView.contentSize = CGSize(width: originX, height: scrollView.frame.height)


43. **改变UITextField中placeholder文字的颜色:**

content.setValue(UIColor.darkGrayColor(), forKeyPath: "_placeholderLabel.textColor")


44. **使UILabel中文字自动适配控件大小并居中显示:**

originalPriceLabel.adjustsFontSizeToFitWidth = true
originalPriceLabel.baselineAdjustment = UIBaselineAdjustment.AlignCenters


45. **为UILabel中文字增加删除线**

let attributedText = NSAttributedString(string: "( self.packageInfo.costPrice )", attributes: [NSStrikethroughStyleAttributeName: 2])
originalPriceLabel.attributedText = attributedText


**46、为UIView增加在xib中可编辑的属性**

extension UIView {
@IBInspectable var cornerRadius: CGFloat { //重点是@IBInspectable
get {
return layer.cornerRadius
}

    set {            
      layer.cornerRadius = newValue            
      layer.masksToBounds = newValue > 0        
    }
}

}




**附录:一些常用的开发技巧:**
奇淫巧技:http://www.cocoachina.com/ios/20141231/10783.html
自定义界面切换效果:http://blog.csdn.net/zhuzhihai1988/article/details/39228955
叶孤城博客:http://www.jianshu.com/users/b82d2721ba07/latest_articles
优秀开源项目:http://www.cocoachina.com/swift/20150126/11016.html
PHAsset的用法:http://kayosite.com/ios-development-and-detail-of-photo-framework.html/comment-page-1

获取图片的背景颜色:http://www.csdn.net/article/2015-01-12/2823525-swiftcolorart
LTBouncyPlaceHolder:https://github.com/nixzhu/dev-blog/blob/master/2014-06-12-LTBouncyPlaceholder.md

http://my.oschina.net/u/2340880/blog/538356
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容