您的当前位置:首页正文

开发技巧总结

来源:要发发知识网

<pre>
1.有时,一些文本控件,内容为空时,在storyboard中就找不到身影,这很不方便,按照下面的操作,即使控件内容为空,也会看到控件的轮廓以及位置
选择菜单栏中的Editor -> Canvas -> Show bounds Rectangles
最上面的红框内的控件是Label,内容清空时,将无法看到该控件位置,按照上面的设置,就可以看到控件的轮廓信息
</pre>

Image.png

<pre>
2.设置视图全屏
在控制器中,重写prefersStatusBarHidden函数,控制视图是否全屏
</pre>


Image.jpg

<pre>
3.弹出键盘后,点击界面空白处,关闭键盘
在控制器中,实现touchesEnded(...) 函数,在函数中执行关闭视图编辑代码,就实现了关闭键盘的效果
</pre>


Image [1].png

<pre>
4.模拟器中设置中文输入法

Settings->General->Keyboard->Keyboards->Add New Keyboard… Chinese-Simplified(PinYin)
</pre>

<pre>
5.应用程序图标设置
</pre>

Image [2].png

<pre>
6.UIScrollView 属性
</pre>

Image [3].png

<pre>
7.设置UITabBar效果
当自定义UITabBar时,需要设置TabBar效果时,除了单独在子控制器中设置效果,还可以在初始化函数中进行设置

推荐使用这种方式设置tabBarItem
let tabBarItem = UITabBarItem.appearanceWhenContainedInInstancesOfClasses([CustomTabBarController.self])
因为:
let tabBarItem = UITabBarItem.appearance() 会把系统默认的tabBar样式也进行修改,而上面的方式只修改当前类中定义的tabBar
</pre>
控制器设置tabBar效果

初始化函数中设置效果

Image [2].jpg

<pre>
8.模拟器中使用mac键盘输入无效果
shift + command + k 切换模拟器键盘和mac键盘
</pre>

<pre>
9.小数点取整
可以使用 Int 和 lroundf 函数来取整

两种方式的区别:
Int 取小数点前的整数,lroundf 则是四舍五入,取最接近的整数

例如:
12.12 使用Int 和 lroundf 得到的值都是12
12.89 使用Int 和 lroundf 得到的值 分别是 12 和 13
</pre>

<pre>
10.设置app名称(默认显示为项目名称)
在Info.plist中添加 Bundle display name 并且输入名称
就可以设置app的显示名称
</pre>

<pre>
12.查看模拟器在mac os文件系统中的位置
菜单中进行操作
前往 -> 按住Option键 -> 资源库隐藏文件夹将会显示出来
Developer/CoreSimulator/Devices/
在这个路径下就是全部的模拟器文件,plist文件中描述了模拟器的名称等信息
</pre>

<pre>
13.加载xib
xib是存储的视图文件,可以通过加载xib文件来呈现视图

如果是创建控制器时勾选了xib,那么需要在控制器中重写init(nibName nibNameOrNil: String, .....)方法
才能创建这个控制器
代码如下:
let xibVC = XibViewController(nibName:"xib文件的名称,不带后缀呦",bundle:nil)
self.presentViewController(xibVC,animated:true,completiton:nil)
</pre>

<pre>
14.常见控件尺寸整理
状态栏 高20px
导航栏 高44px
一般导航栏上的小控件 高35px
工具条 高49px
单元格 高44p
</pre>

<pre>
15.模拟器模拟内存警告
</pre>

Image [3].jpg

<pre>
16.如何在控制台打印当前app的沙盒目录
一、设置断点
二、
在控制台(lldb) 后面输入 po NSHomeDirectory(),回车
</pre>

Image [4].jpg

<pre>
17.The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.

有的时候因为依赖关系或者版本问题不能编译运行。
解决方案:
进入项目文件夹中,使用命令窗口执行下面两行语句
1.删除工作空间
2.重新下载第三方库
rm -rf MyProject.xcworkspace
pod install
</pre>

<pre>
18.解决xcode7.1无法安装插件

  1. 到githup上下载Alcatraz project
  2. 打开终端
  3. 输入

defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID

  1. 得到当前的UUID
  2. 打开下载的Alcatraz project
  3. 在这个工程的infos设置里添加
Image [4].png
  1. 把刚刚得到的UUID加入
  2. run
  3. 重启XCode
  4. 你会看到一个提示框 a load bundle or skip.. 选择 load bundle.

    </pre>

<pre>
19.xcode7.1无法添加*.dylib的解决办法

在项目Target中的Link Binary With Libraries 手动添加
首先点击 “+”
显示搜索添加页面,在这里如果搜索之前的libsqlite3.dylib是搜不出来ios9之前的。所以需要点击 Add Other,出现文件目录页面,正常情况这里去通过Finder也是找不到老的libsqlite3.dylib文件的,因为这个文件是隐藏掉的。所以需要按
快捷键 CMD+Shift+G (Go to the folder),输入/usr/lib后,进入隐藏的界面,然后添加你需要的 *.dylib,如libsqlite3.dylib文件。即可。
</pre>

<pre>
20.xcode7.1 手机9.2解决无法真机调试(could not find developer disk image)

方法1:拷贝这个文件9.2(13C75)到
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
然后重新启动xcode(完全退出)就可以了

方法2:更新Xcode到7.2版本。
</pre>

<pre>
21.空合运算符的应用
空合运算符其实是对三目运算符更优雅的封装

var str:String?

使用三目运算符 : var value = str != str ? str : "novalue"

使用空合运算符 : var value = str ?? "no value"
</pre>

<pre>
22.分组表格,去除顶部多余的空间
当表格类型是分组时,表格会默认填充顶部的headView,当我们不想要这部分多余空间时
</pre>


屏幕快照 2016-01-12 下午4.50.05.png

<pre>
23.使用base64转码上传图片需要注意的问题
要对转码后的base64字符串进行url编码处理,否则传输到服务器中会对一些特殊字符(+、/ 等等特殊字符)进行自动转换,导致解析base64传后,无法显示图片
</pre>

屏幕快照 2016-04-06 下午1.39.11.png

<pre>
24.设置单元格图片时,不能显示图片的解决办法
即使在主线程更新UI也不会显示图片,是因为UIImageView默认有一个尺寸,设置图片后,需要重新设置布局才可以显示图片
1.使用SDWebImage
2.给cell重新布局 在单元格类里 self.setNeedsLayout
</pre>

<pre>
25.类、结构体、枚举之间的一些注意点
1.类型
类 : 引用类型
结构体和枚举 : 值类型
2.静态static
类 : static修饰成员变量 class修饰方法
结构体、枚举 : static修饰成员变量 static修饰方法
3.方法中对成员变量进行修改
类 :由于是引用类型,可以对成员变量进行修改
结构体、枚举 : 由于是值类型,不可以直接对成员变量进行修改,如果想修改,需要用关键字mutating修饰方法
</pre>

屏幕快照 2016-05-26 下午2.13.16.png

<pre>
26.图片尺寸与屏幕的关系
</pre>

对比图

<pre>
27.自定义返回按钮,滑动返回手势的处理
隐藏或删除系统返回按钮,会自动把返回手势删除
想要使用滑动返回手势,需要恢复手势

// 定义手势代理
var gestureDelegate:UIGestureRecognizerDelegate?

// 恢复手势代理(替换了系统的返回按钮就删除了手势,所以在这里恢复手势,代码写在导航栏控制器中)
self.interactivePopGestureRecognizer?.delegate = self.gestureDelegate
</pre>

<pre>28.xib中使用kvc
选中控件,在属性工具栏中User Defined Runtime Attributes添加属性、值
</pre>

8A025C22-8DDF-4B70-82E7-394F82120511.png

<pre>29.xib中添加控件,同级间控件添加顺序会影响显示效果,例如:后添加的view会覆盖前面的控件,所以在xib中设置背景时,需要把它放在首位,其他控件放在后面,才不会导致背景把控件遮挡住
ps:控件的层次图,背景放在首位,才不会遮挡住其他按钮等控件
</pre>

左侧控件层次图

<pre>30.自定义单元格的滑动菜单
默认情况下,单元格开启编辑模式时,滑动菜单只有1个选项,如果需要设置多个选项,就需要通过代理方法,自定义滑动菜单
下图是通过代理方法,自定义的滑动菜单,在代理方法中,可以对选项进行动作设置以及样式的设置
</pre>

自定义具有多个选项的滑动菜单

<pre>通过代理方法,自定义滑动菜单</pre>

屏幕快照 2016-06-11 下午10.28.21.png

<pre>31.区分图片填充方式
scale to Fill : 图片适应容器的尺寸,图片可以被完整显示,但可能会被拉伸而改变外观
Aspect to Fit : 图片保持原比例不变,可以完整显示并居于容器中间。
Aspect to Fill : 图片原始尺寸不变,超出容器部分会被截断一部分
</pre>

<pre>32.修改返回按钮的两种方式
拥有导航栏的app,从父页面跳转至子页面,系统会子页面的导航栏左侧添加一个具有文字的返回按钮,如果不想要文字,只想要返回按钮,一般有两种方法,根据你的喜好来进行设置
</pre>

<pre>
①.给导航栏左侧按钮,自定义一个按钮(文字或图片都可以),默认替换了系统的返回按钮
注意:这时,系统默认的滑动返回手势将失效,需要恢复手势才能滑动返回上一个页面
</pre>

<pre>
②.在父页面设置返回按钮的样式,设置完成后,跳转至子页面,只显示返回箭头,没有文字
注意:必须在父页面设置才会生效
</pre>

<pre>33.设置状态栏样式
在info.plist中添加节点 View controller-based status bar appearance 设置为false(表示状态不是由控制器来设置),并在appDelegate中设置状态栏样式
LightContent : 白色
BlackOpaque、Default : 黑色

ps:
barTintColor:导航栏背景色
tintColor: 导航栏按钮颜色
</pre>

<pre>
34.设置单元格自适应高度
①代码,计算高度
②storyboard,设置约束,并用代码设置单元格自适应高度
这里讲述第二种方式,单元格需要给高度不确定的控件设置约束,设置距离单元格顶部和底部距离为0
(单元格内的布局一般都很复杂,有时需要设置其他控件距离顶部和底部的距离,才能保证目标控件自适应高度。
一句话总结就是需要明确设置整体控件距离单元格顶部和底部的距离,才能自适应)

// 设置单元格自适应高度
self.hotCommentTable.estimatedRowHeight = 44 // 设置预期高度
self.hotCommentTable.rowHeight = UITableViewAutomaticDimension // 设置高度自适应
</pre>

<pre>
35.UICollectionView的布局设置

// 这个方法会返回rect范围内所有cell的尺寸,所以当需要对cell进行定制化设置时,需要遍历数组,对每一个cell进行设置
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

    let attrs = super.layoutAttributesForElementsInRect(rect)
    
    for attr in attrs! {
        attr.alpha = 0.5
    }
    
    return attrs!
}

</pre>

<pre>
36.guard 表达式 else { statement }
ps:在不同的语句环境时,else中的退出关键字也有所不同

如果是在函数中,只能用return结束
func test() {
let num:Int? = nil
guard let n = num else {
print("没有值吧")
return
}
print(n)
}

如果是在函数中的循环语句中,可以用continue或break结束
func test2() -> Int {
var result = 0
for i in 0...10 {
guard i == 8 else {
continue
}
print(i)
result += i
}
return result
}
</pre>

<pre>
37.控件使用弱引用(weak)的原因
控件所在的控制器已经是强引用,当控制器被销毁时,控件自然会被销毁
如果把控件设置成与控制器的关系为强引用,那么当控制器被销毁时,由于两者之间存在强引用,控件将不会被释放销毁,将会导致内存泄露
</pre>

<pre>
38.添加三方框架后,无法真机的解决办法
</pre>

<pre>
39.swift扩展中,不能写属性观察者,可以写计算属性
// 计算属性
var a:CGFloat {
get{}
set{}
}

// 属性观察者
var b:CGFloat {
didSet{}
willSet()
}
</pre>