close
当前位置: 物联网在线 > 技术文库 > ios >

那些设计iOS API需要知道的事(3)

在构建需要打印到日志的字符串时,object对象会收到description消息,该方法所返回的描述信息将取代“格式字符串”(format string)里的“%@”。

NSArray *obj = @[@"A string", @(123)]; NSLog(@"object=%@", obj);

输出:

object=( "A string", 123 )

如果在自定义类上这么做,那么则输出的信息却是如下:

object=<ZKRSqure: 0x7656d8a90060>

如果想要像上面NSArray那样打印出有用的信息,那么我们就应该在自己的类中覆写description方法,否则打印信息时就会调用NSObject类所实现的默认方法。此方法定义在NSObject协议里,不过NSObject类也实现了它。

- (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, \"%f %f\">", [self class], self, _width, _height]; }

使用结果:

ZKRRectangle *rectangle = [[ZKRRectangle alloc] initWithWidth:5.0 height:7.0]; NSLog(@"%@", rectangle); //Output <ZKRRectangle: 0x60000002fc20, "5.000000 7.000000">

NSObject协议中还有个需要注意的方法,就是 debugDescription ,此方法用意与 description 相似。二者区别在于, debugDescription 方法是开发者在调试器(debugger)中以控制台命令打印对象时才调用的。在NSObject类的默认实现中,它只是直接调用 description 。

初始化方法

所有对象均要初始化,在初始化时,有些对象可能无须开发者向其提供额外信息,不过一般来说还是需要提供的。通常情况下,对象若不知道必要的信息,则无法完成其工作。例如,UITAbleViewCell类初始化该类对象时,需要指明其样式及标识符,标识符能够区分不同类型的单元格。由于这种对象的创建成本较高,所以绘制表格时可依照标识符来复用,以提升程序效率。这种可为对象提供必要信息以便其能完成工作的初始化方法叫做“全能初始化方法”(designated initializer)。

如果创建类实例的方式不止一种,那么这个类就会有多个初始化方法。但是,我们仍然需要选定一个作为全能初始化方法,令其他初始化方法都来调用它。例如,NSDate类

- (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; - (instancetype)initWithTimeIntervalSinceNow:(NSTimeInterval)secs; - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)secs; - (instancetype)initWithTimeInterval:(NSTimeInterval)secsToBeAdded sinceDate:(NSDate *)date;

在上面几个初始化方法中, initWithTimeIntervalSinceReferenceDate: 是全能初始化方法。只有在全能初始化方法中,才会存储内部数据。这样的话,当底层数据存储机制改变时,只需修改此方法的代码就好,无须改动其他初始化方法。

示例代码:

// ZKRRectangle.h #import <UIKit/UIKit.h> @interface ZKRRectangle : NSObject<NSCopying> @property (nonatomic, assign, readonly) CGFloat width; @property (nonatomic, assign, readonly) CGFloat height; - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height; @end // ZKRRectangle.m #import "ZKRRectangle.h" @implementation ZKRRectangle - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { _width = [[aDecoder decodeObjectForKey:@"width"] floatValue]; _height = [[aDecoder decodeObjectForKey:@"height"] floatValue]; } return self; } - (instancetype)init { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must use initWithWidth:height: instad." userInfo:nil]; return [self initWithWidth:0 height:0]; } - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height { self = [super init]; if (self) { _width = width; _height = height; } return self; } @end // ZKRSquare.h #import "ZKRRectangle.h" @interface ZKRSquare : ZKRRectangle - (instancetype)initWithDimension:(CGFloat)dimension; @end // ZKRSquare.m #import "ZKRSquare.h" @implementation ZKRSquare - (instancetype)init { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must use initWithDimension: instad." userInfo:nil]; return [self initWithDimension:0]; } - (instancetype)initWithDimension:(CGFloat)dimension { return [super initWithWidth:dimension height:dimension]; } - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must use initWithDimension: instad." userInfo:nil]; CGFloat dimension = MIN(width, height); return [self initWithDimension:dimension]; } @end 小结

在类中提供一个全能初始化方法,并于文档里指明。其他初始化方法均调用此方法。

若全能方法于超类不同,则需要覆写超类中的对应方法。

如果超类的初始化方法不适用于子类,那么应该覆写这个超类方法,并在其中抛出异常。

NSCopying协议
(责任编辑:ioter)

用户喜欢...

聊一聊iOS的那些生命周期

iOS应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的。iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的...


iOS 开发周报:苹果正在重新设计 Mac Pro、Weex 布局引擎(Yoga)探究

苹果正在重新设计 Mac Pro :苹果正在加班加点开发一款 完全重新思考 的 Mac Pro,采用模块化设计,可以为高端 CPU 和 GPU 提供空间,而且未来的升级也将更加方便。苹果还在开发自有品牌的专...


iOS的那些面试

笔试面试是程序员应聘绕不过的坎,想进大厂就一定要有知识储备量,而这个却是最佳的考察方式。笔者分享一些收集的iOS面试题,答案仅供参考,如有错误,还请指正。 第一部分 1.Objecti...


iOS 组件化 —— 路由设计思路分析

前言 随着用户的需求越来越多,对App的用户体验也变的要求越来越高。为了更好的应对各种需求,开发人员从软件工程的角度,将App架构由原来简单的MVC变成MVVM,VIPER等复杂架构。更换适合...


iOS 导航栏的那些事儿

最近项目里有个需求和导航栏的样式定制有关,深入之后发现之前理解的一些概念有些模糊,刚好趁着这次机会全面整理了一下。 从 iOS7 开始,苹果采用了大量的扁平化和毛玻璃风格,刚升...


iOS那些“垃圾”的轮播

轮播视图通常也叫Banner,90%以上App都会用到的一个控件,网上有很多开源代码,但是至今我觉得比较好的一个是 SDCycleScrollView ,因为他解决了我接下来要吐槽的两个问题。 通常实现定时自动...


iOS开源 - 复制 iOS 样式库到 Sketch 以改善、加速设计流程

I’ve decided to take styles from Xcode and do my best to replicate them for Sketch. Along the way, I documented the process of how I ended up with the result so you can look into things even further. UIBlurEffectStyle The API doesn't provide any...


Java开发者需要了解的移动开发编程语言

移动应用开发行业在过去的五年里飞速地成倍增长,改变了全球企业功能。随着企业在最近一段时间调整移动应用到他们的生产力,以及他们跨平台移动设备的快速创新;它需要移动应用程序...


总结iOS开发中的断点续传那些事儿

前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始。当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主...


使用WKWebView遇见的那些坑

iOS8之后出了WKWebView,据说加载速度和内存占用情况都甩UIWebView好几条街,鉴于我们公司的项目用到挺多的webView,于是简单的调研下决定用WKWebView替换UIWebView。WKWebView的使用方法不多少,相信...