看OC的教程,写Swift代码,致醉了的人
TextField退出键盘:
1、sender.resignFirstResponder();
2、self.view.endEditing(true);
定义Model类时,为了方便编程人员之间的交流,实例化方法需要提供两种
1、init(xxx: XXX);
2、class func modelWithXXX(xxx: XXX) ->Model{};
获取屏幕中控件最大的x、y轴坐标值:
1、CGRectGetMaxX(rect: CGRect)
2、CGRectGetMaxY(rect: CGRect)
NSTimer定时器,一旦调用invalidate()方法,定时器将无法重用
所以需要清除内存,当需要再次使用定时器时,要重新实例化
使用NSTimer定时器时,需要给定时器设置执行优先级
NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes);
IOS7之后设置控件圆角
label.layer.cornerRadius =5;
label.layer.masksToBounds =true;
设置TableView中的Cell行
1、设置tableView的行高,每行高度一致,建议使用该方法
tableView.rowHeight =60;
2、heightForRowAtIndexPath可针对不同的行,设置对应的行高度
tableView(tableView:UITableView, heightForRowAtIndexPath indexPath:NSIndexPath) ->CGFloat { }
TableView中的Cell行,backgroundView的优先级别>backgroundColor
IOS中加载xib/nib文件方法:
1、UINib(nibName:"CFCellFootView", bundle:nil).instantiateWithOwner(nil, options:nil).firstasCFCellFootView;
2、NSBundle.mainBundle().loadNibNamed("CFCellFootView", owner: nil, options: nil).firstas CFCellFootView;
Swift定义代理协议:
1、使用protocol修饰符
2、继承自NSObjectProtocol类
3、代理协议的定义,需要将对应操作的View作为参数传递,以便于定位
4、代理名称的命名:控件类名+Delegate
5、代理方法普遍都是optional修饰
6、代理方法命名参照UITableViewDelegate:tableView + (will/did---动作) + 名称
7、在调用代理时,需要判断代理是否实现了对应的方法
计算传递过来的参数的所在位置的最大值
CGRectGetMaxX(rect: CGRect)
CGRectGetMaxY(rect: CGRect)
在Swift语言开发中,为了计算文字内容在屏幕中所占据的宽度与高度,需要使用NSString类型,而不用String类型
NSString中的boundingRectWithSize()函数可以准确的计算出文字内容的宽度与高度
使用代码如下:
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;">/// CGRectGetMaxX/CGRectGetMaxY计算传递参数所在位置的最大值 let nameX = CGRectGetMaxX(iconView.frame) + margin; let nameY = margin; /// 文字内容无须换行,设定为最大值 let nameMaxSize = CGSizeMake(CGFloat(MAXFLOAT), CGFloat(MAXFLOAT)); let nameAttrs = NSDictionary(object: nameFont, forKey: NSFontAttributeName); /** 计算文字在View中的宽度与高度 :param: <size 限制文字的最大宽度与高度 :param: options NSStringDrawingOptions.UsesLineFragmentOrigin :param: attributes 文字内容的字体参数 :param: context nil :returns: CGRect.size文字内容所占据的宽度与高度 */ let nameSize = dataSource.name.boundingRectWithSize(nameMaxSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: nameAttrs, context: nil).size;</span></span></span></span></span></span></span></span></span>
UILabel设置自动换行:textView.numberOfLines =0;
列表控件中,如果有的Cell数据中有图片,有的Cell中没有图片,需要在代码中设置pictureView控件的hidden属性值,而不能使用removeFromSupport方法,否则在华东之后重新填充数据会导致图片控件丢失
通过代码创建自定义Cell(Cell的高度不一致)
1、新建一个cell子类,继承自UITableViewCell类
2、重写init(style:UITableViewCellStyle, reuseIdentifier:String?)方法,将所有可能存在的子控件全部在init方法中创建,同时子控件需要添加到contentView中
3、针对Cell内容显示需要提供两个数据模型
。存储数据的Model模型
。针对存储数据的Model模型封装的Frame模型。在Frame模型中包含Model模型数据,Model模型属性的Frame数据,自定义Cell的最终高度
4、自定义Cell类只需要一个Frame模型即可,通过Frame模型可以获取Model模型数据,不需要直接拥有Model模型数据
5、自定义Cell类通过Frame模型设置子控件的显示数据与子控件的Frame属性
6、Frame模型的创建与数据初始化放在Controller中,并使用懒加载的方式,达到每个Model模型数据只初始化一次,以便减少不必要的内存浪费
对比自定义Cell类子控件前后优化过程
优化之前:
1、在Controller中获取Model模型数据集合
2、在cellForRowAtIndexPath中计算Cell子控件的Frame
该方式导致用户滑动TableView时,每次载入Cell数据内容,将重复计算Cell中子控件的Frame,从而导致内存浪费
优化之后:
1、在Controller中获取Model模型数据后,马上计算出每个Model模型数据对应的Frame模型,Controller中封装的数据集合为Frame模型,而不是Model模型
2、在cellForRowAtIndexPath中,直接从内存中获得Frame模型,Cell只需要填充显示子控件的数据内容,无须计算Frame数据
优化解析:因为用户操作TableView时,cellforRowAtIndexPath方法将会被无限放大,频繁在该方法中执行重复的Frame数据计算,将是一件十分浪费内存资源的事情,所以要将该方法中的不必要操作去除,从而达到避免内存浪费
以上Cell操作总结内容适用于Swift与OC
UITextField在设置背景图片的时候,需要先取出BorderStyle属性的边框
编程过程中,分类、类型等匹配条件尽量不要使用Int类型,而使用枚举(深有感触,可能描述不够详细,不过我自己能懂就OK了)
移动开发过程中的图片拉伸技术:
1、Android中的.9图片
2、IOS中的图片拉伸操作:
@availability(iOS, introduced=5.0)
func resizableImageWithCapInsets(capInsets:UIEdgeInsets) ->UIImage
该方法是IOS5.0中提供的图片拉伸技术,使用的是平铺方式,并可以返回一个新的UIImage对象
@availability(iOS, introduced=6.0)
func resizableImageWithCapInsets(capInsets:UIEdgeInsets, resizingMode:UIImageResizingMode) ->UIImage
该方法是IOS6.0中提供的图片拉伸技术,UIImageResizingMode枚举有两个值,Tile是平铺的方式,同resizableImageWithCapInsets(capInsets: UIEdgeInsets) -> UIImage方法的实现效果一样,Stretch直接拉伸。同时返回一个新的UIImage对象
func stretchableImageWithLeftCapWidth(leftCapWidth: Int, topCapHeight: Int) -> UIImage
该方法在IOS8.0中已经被废弃了,不做过多的介绍。
开发过程中,工具方法的提取
1、编写工具类(Java开发模式影响),多为类方法,使用class修饰方法名称
2、Swift中,提供了使用extension的扩展方法,在原有系统类的基础上进行扩充,类方法与成员方法需要根据情况区分
以上两种方式可根据开发人员自主选择
IOS中的通知
通知中心NSNotificationCenter
1、通知的发布
2、通知的监听
3、通知的移除
一个完整的通知包含3个属性
1、name:通知的名称
2、object:通知的发布者
3、userInfo:通知附带数据
代理与通知的区别
1、代理是一对第一的。一个通知发布者对应多个接收者,同时接收者可以接收多个通知。
代理与通知的共同点
1、利用代理和通知都能完成对象之间的通信
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><pre name="code" class="objc"> /** * observer: 接收者 * Selector: 接收处理方法 * name: 通知名称 当为nil时表示只要匹配object,全部接收 * object: 通知发送者 当为nil时表示只要匹配name,全部接收 * 当name与object都为nil时,表示全部通知,全部接收 */ center.addObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?)</span></span></span></span></span>
在Swift中,使用dealloc()方法,错误提示Cannot override 'dealloc' which has been marked unavailable,的解决方法是deinit{ },无须override和func,好坑爹
UITextFiled使用
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;">// 设置输入框对应键盘返回键样式 textInput.returnKeyType = UIReturnKeyType.Send; // 设置输入框的左边距,同时需要设置leftViewMode为Always textInput.leftView = UIView(frame: CGRectMake(0, 0, 10, 0)); textInput.leftViewMode = UITextFieldViewMode.Always;</span></span></span></span></span>
UI元素在调用init(reuseIdentifier:String?) {}方法时,frame/bounds都是0,在方法内获取的控件宽、高值无效。解决方法,将控件的frame设置放在layoutSubviews()方法中。当一个控件的frame发生改变时,系统自动调用layoutSubviews()方法,所以在该方法中设置子控件的frame属性
IOS中按钮的属性设置,内容太多,直接代码+注释:
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;">// 1、按钮 nameView = UIButton(); // .设置按钮背景色 nameView.setBackgroundImage(UIImage(named: "buddy_header_bg"), forState: UIControlState.Normal); nameView.setBackgroundImage(UIImage(named: "buddy_header_bg_highlighted"), forState: UIControlState.Highlighted); // .设置按钮文字颜色 nameView.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal); // .设置按钮内容左对齐 nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left; let margin: CGFloat = 10; // .设置按钮整体内容的边距 // nameView.contentEdgeInsets = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: 0); // .设置按钮内部图片的边距(设置图片右边距,图片与文字之间的距离没有改变,只能再次设置按钮内文字的边距) nameView.imageEdgeInsets = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: 0); // .设置按钮内部文字的边距 nameView.titleEdgeInsets = UIEdgeInsets(top: 0, left: margin * 2, bottom: 0, right: 0); // .设置按钮上的左侧箭头 var arrow = UIImage(named: "buddy_header_arrow"); nameView.setImage(arrow, forState: UIControlState.Normal);</span></span></span></span>
IOS在给View的layer设置cornerRadius属性后,未能达到圆角效果解决方法
1、view.layer.masksToBounds = true;通过父控件强制所有子控件都按照父控件的尺寸,超出部分全部剪切掉
2、view.clipsToBounds = true;通过子控件属性设置必须遵守父控件的尺寸,超出部分全部前切掉
使用UIPickerView级联操作时,要对动态级联的列做刷新操作pickerView.reloadComponent(1);然后再进行选中操作
UIApplication操作:
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"> @IBAction func onClickWithApplication() { // 获取Application对象 let application = UIApplication.sharedApplication(); // 设置应用图标上的数字 // application.applicationIconBadgeNumber = 10; // 清除应用图标上的数字 // application.applicationIconBadgeNumber = 0; // 设置状态栏联网操作提示 // application.networkActivityIndicatorVisible = true; // 隐藏状态栏联网操作提示 // application.networkActivityIndicatorVisible = false; // 利用Application打开Safari浏览器 // application.openURL(NSURL(string: "http://www.baidu.com")!); // 打电话 // application.openURL(NSURL(string: "tel://10086")!); // 发短信 // application.openURL(NSURL(string: "sms://10086")!); // 发邮件 // application.openURL(NSURL(string: "mailto://[email protected]")!); // 打开其他APP // 设置状态栏效果,需要在info.plist中进行配置,将状态栏控制交给UIApplication // application.statusBarHidden = true; // application.statusBarStyle = UIStatusBarStyle.LightContent; } </span></span></span>
Storyboard创建方式
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;"> let storyboard = UIStoryboard(name: "Main", bundle: nil); // 通过storyboard的instantiateInitialViewController()方法获得启动Controller let mainViewController = storyboard.instantiateInitialViewController() as ViewController; // 通过storyboard的instantiateViewControllerWithIdentifier("ViewController")方法获得指定Identifier的Controller let viewController = storyboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController;</span></span></span>参数中得bundle传入nil表示默认使用NSBundle.mainBundle();
使用xib创建控制器的View时,xib文件必须要有View对象,同时还需要设置First Owner属性
loadView()方法用来创建自定义View的内容
IOS中ViewController创建级别:loadView > Storyboard > xib
UINavigationController操作
<span style="font-family:Comic Sans MS;font-size:24px;"><span style="font-family:Comic Sans MS;font-size:24px;">// 将自己从NavigationController的栈中移除 self.navigationController?.popViewControllerAnimated(true); // 将NavigationController移除元素,直至根元素为止 self.navigationController?.popToRootViewControllerAnimated(true);</span></span>
1月2号,今天遇到一个十分奇怪的Bug,在使用UIAlertController编写提示框时,实例化UIAlertAction对象后,使用闭包的方式对Action的操作进行监听,结果如果在第一行调用self.navigationCtroller?.popViewControllerAnimated(true);方法会提示一个十分怪异的错误,如果继续在后面写其他代码,这个错误就会消失,或者在掉该方法之前定义一个变量,错误也会消失,故在此做下记录。
使用Segue进行跳转时,Segue大致分为2大类
1、自动型:点击控件之后,自动执行Segue,自动完成界面跳转。
主要执行的方法:
func prepareForSegue(segue:UIStoryboardSegue, sender:AnyObject?) :开始跳转之前的操作
func shouldPerformSegueWithIdentifier(identifier:String?, sender:AnyObject?) ->Bool:根据返回值判断是否进行跳转,不过因为控件直接控制跳转,并且不设置Identifier,故需要根据流程判断是否跳转,不推荐使用自动型
2、手动型:需要通过写代码手动执行Segue,才能完成界面跳转。同时必须设置Identifier属性
主要调用的方法:
self.performSegueWithIdentifier("IdentifierWithLogin", sender:nil)
主要执行的方法:
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) :开始跳转之前的操作
func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool
<span style="font-family:Comic Sans MS;font-size:24px;">// 成为第一响应者 nameInput.becomeFirstResponder(); // 取消第一响应者 nameInput.resignFirstResponder();</span>
应用沙盒结构分析
1、应用程序包:包含了所有的资源文件和可执行文件
2、Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录
3、tmp:保存应用运行时所需要的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行,系统也可能会清除该目录下的文件,iTunes不会同步备份该目录
4、Library/Cache:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不备份该目录。一般存放体积大、不需要备份的非重要数据
5、Library/Preference:保存应用的所有偏好设置,IOS的Settings应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
IOS中的数据存储
1、存储为plist属性列表
func saveWithFile() { /// 1、获得沙盒的根路径 let home = NSHomeDirectory() as NSString; /// 2、获得Documents路径,使用NSString对象的stringByAppendingPathComponent()方法拼接路径 let docPath = home.stringByAppendingPathComponent("Documents") as NSString; /// 3、获取文本文件路径 let filePath = docPath.stringByAppendingPathComponent("data.plist"); var dataSource = NSMutableArray(); dataSource.addObject("衣带渐宽终不悔"); dataSource.addObject("为伊消得人憔悴"); dataSource.addObject("故国不堪回首明月中"); dataSource.addObject("人生若只如初见"); dataSource.addObject("暮然回首,那人却在灯火阑珊处"); // 4、将数据写入文件中 dataSource.writeToFile(filePath, atomically: true); println("\(filePath)"); }
func readWithFile() { /// 1、获得沙盒的根路径 let home = NSHomeDirectory() as NSString; /// 2、获得Documents路径,使用NSString对象的stringByAppendingPathComponent()方法拼接路径 let docPath = home.stringByAppendingPathComponent("Documents") as NSString; /// 3、获取文本文件路径 let filePath = docPath.stringByAppendingPathComponent("data.plist"); let dataSource = NSArray(contentsOfFile: filePath); println("\(dataSource)"); }
2、使用NSUserDefaults存储数据
func saveWithNSUserDefaults() { /// 1、利用NSUserDefaults存储数据 let defaults = NSUserDefaults.standardUserDefaults(); // 2、存储数据 defaults.setObject("衣带渐宽终不悔", forKey: "name"); // 3、同步数据 defaults.synchronize(); }
func readWithNSUserDefaults() { let defaults = NSUserDefaults.standardUserDefaults(); let name = defaults.objectForKey("name") as NSString; println("\(name)"); }
3、归档存储:对象需要实现NSCoding协议,归档对应encode,反归档对应decode
/** 归档数据 需要实现NSCoding协议 */ func saveWithNSKeyedArchiver() { let home = NSHomeDirectory() as NSString; let docPath = home.stringByAppendingPathComponent("Documents") as NSString; let filePath = docPath.stringByAppendingPathComponent("book.data"); let book = CFAddressBook(name: "Francis", call: "199"); /** * 数据归档处理 */ NSKeyedArchiver.archiveRootObject(book, toFile: filePath); }
/** 反归档数据 */ func readWithNSKeyedUnarchiver() { let home = NSHomeDirectory() as NSString; let docPath = home.stringByAppendingPathComponent("Documents") as NSString; let filePath = docPath.stringByAppendingPathComponent("book.data"); let book = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as CFAddressBook; println("\(book.name), \(book.call)"); }
4、SQlite3
5、CoreData
哈哈