Swift学习过程问题记录

看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

哈哈


你可能感兴趣的:(swift)