原创:知识点总结性文章
无私奉献,为国为民,创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 一、oc语言--面向对象的三大特性
- 二、XCode开发环境
- 三、UIKit框架的使用
- 四、Foundation框架的使用
- 五、知识点大杂烩
一、oc语言--面向对象的三大特性
OC语言是C 编程语言的超集,提供面向对象的功能和动态运行时。虽然消息发送同函数调用相比确实慢一点,但却有面向对象的动态绑定、多态等优点。
面向对象的三大特性是面向对象语言的精华所在。面向对象是基于万物皆对象这个哲学观点。抽象化指的是尽可能地不考虑相关细节,只关注对象的核心和本质。类就是舍弃了每个具体对象的各种细节的模版。把一个对象抽象成类,具体上就是把一个对象的静态特征和动态特征抽象成相应的属性和方法,也就是把一类事物的算法和数据结构封装在一个类之中,程序就是多个对象和互相之间的通信组成的。用类创建对象的过程叫作实例化(instantiation ),不同对象之间可以共享该类中的方法,差异就在于具体值的不同。
面向对象具有封装性,继承性,多态性,封装隐蔽了对象内部不需要暴露给外人的细节,使得内部细节的变动跟外界不相关,只单纯依靠提供的接口进行通信。封装性降低了编程的复杂,通过继承,使得新建一个类变得更加容易,一个类从父类那里获得其方法和属性的工作就交给了编译器。而继承、实现和运行时的类型绑定机制所产生的多态,使得不同的类所产生的对象能够对相同的消息作出不同的反应,这极大地提高了代码的通用性。言而总之,面向对象的三大特性大大提高了程序的重用性和可维护性。
1、封装
什么是封装
- 在程序上,隐藏对象的属性和方法实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;
- 将数据和功能相结合,形成一个有机的整体,形成“类”,其中数据和函数都是类的成员。
封装的好处
- 过滤不合理的值
- 屏蔽内部的赋值过程
- 让外部不必关注内部实现细节
2、继承
什么是继承:通过继承,子类可以拥有父类中所有的成员变量和方法
重写:子类重新实现父类中某个方法,覆盖父类以前的做法
super:super处在对象方法中,就调用父类的对象方法;super处在类方法中,就调用父类的类方法
作用
- 不改变原来模型的基础上,拓充方法
- 建立了类与类之间的联系
- 抽取了公共代码
使用场合
- 子类重写父类方法时,想保留父类方法的一些行为
- 当两个类拥有相同的属性和方法时,就可以将相同的东西抽取出到父类中
注意
- 调用某个方法时,优先去当前类中寻找,如果找不到,再去父类中寻找
- oc语言是单继承,父类必须声明在子类前面
- 子类不能拥有和父类相同的成员变量
- 缺点:耦合性太强,删除父类后,子类就不能够继续使用
3、多态
什么是多态:没有继承就没有多态,不同对象对同一消息的不同相应,子类可以重写父类的方法
局限性:父类类型变量不能够直接调用子类特有的方法(编译过程会有警告)。必须强转为子类类型便后后,才能够直接调用子类特有的方法。
二、XCode开发环境
1、视图元素
控件:继承自 UIControl
类,能够响应用户高级事件
窗口:应用只有一个UIWindow
对象,它是所有子视图的“根"容器
容器视图:UIScrollView
的子类有UITextView
、UITableView
和 UICollectionView
, 在内容超出屏幕时,它们可以提供水平或垂直滚动条。
显示视图:包括UIImageView
、 UILabel
、 UIProgressView
和UIActivityindicatorView
文本和Web视图:包括UITextview
和UIWebView
, UIWebView
是能够加载和显示 HTML
代码的视图
导航视图:包括UITabBar
和UINavigationBar
2、视图跳转
故事板:本质上是一个XML
文件,可以用来描述应用中有哪些界面、界面中有哪些视图元素,它 们的布局、事件处理,以及界面之间是如何导航(或跳转)的
场景 (scene) 和过渡 (segue):一个场景中包含一个视图控 制器,视图控制器通过管理视图来显示界面 ,过渡定义了场景之间的导航(或跳转)方式。
- Show Segue:在当前视图上展示视图,如果当前控制器是导航控制器,那么视图的显示会采用树形结构导航模式:如果不是导航控制器,那么视图显示会采用模态 (Modal) 导航模式。
- Show Detail Segue:当采用UISplitViewController控制器时, 在Detail视图中显示视图。 如果在其他导航控制器中使用这个过渡,那么它和ShowSegue的效果是一样的
- Modal Segue:模态导航模式。
- Popover Segue:Pad设备上呈现浮动窗口
3、Project属性设置
Deployment Target:部署配置,主要是对本project
的生成的App的可以运行的最低版本进行配置,默认是当前Xcode
上API的最新版本,所以,在我们的项目中有需要对低版本适配的地方需要在这里设置。同样的,我们还可以在build setting
中对这一属性进行设置,两者是同步的。
Localizations:本地化,这里的功能主要是添加我们的App所支持的语言,通过上图最下面的红色圈内的【+】【-】按钮可以添加或删除不同的语种,并可以选择根据手机的设置进行不同语种的自适应。关于最下面的选择是否开启国际化,默认是开启的,至于如何进行国际化和不同语种的适配详情见:详述iOS国际化
Configurations:用来配置iOS项目的xcconfig
文件,主要用于在几套不同的开发环境编译。Cocoapods
的项目配置管理很多都是依赖xcconfig
文件去实现的。
4、target属性设置
发布信息:
Identify(标识符)栏:主要定义了一些和应用发布有关的标识属性。
Display Name(App应用显示名):安装到iOS手机或iPad上App的名称。
Bundle Identifier(包标识符):是该应用的唯一ID
,用来让操作系统和AppStore
识别。在创建项目或者对象过程中Xcode
就自行创建了包标识符,一般情况下不要修改它。
Version(外部版本号):使用户能够看到的版本号。
Build(内部版本号):开发者自己看到的版本号,以区分内部测试版本。
Signing(签名):主要是进行证书管理,在真机调试或者打包时我们都需要进行签名进行认证才可以的。
部署信息:
Deployment Target(部署对象):用来设置支持的最低版本。这个和project
的info
中的一个意思,并且,这两个的设置最好是一样,如果不一样,最后的App会以target
的设置为准。
Devices(设备):用来设置支持的设备,有iPhone、iPad和Universal三个选项。
Main Interface(主界面):应用启动时预加载的主界面视图。
Device Orientation(设备方向):定义应用支持的方向。有Portrait
、Upside Down
、Landscape Left
(横评、Home
键在左)、Landscape Right
几种方向。
App icon Source(应用图标):
Notification:通知时的图标,类似有应用相关的推送消息时,有时候需要显示本应用的图标则会显示这个尺寸的
Spotlight:搜索小图标,当在Spotlight
中输入应用名,搜索结果中出现该应用时的图标就是这个尺寸的,还有设置里的图标也是这个尺寸的。
App:这就是正常的App图标,安装好之后在桌面显示的,或者分享推荐时显示的应用也是这个尺寸的图标
App store:应用商店中的显示的图标
Luanch Image Source(启动图片):将所有切好的图标直接拖过来,他们会自动找到自己应该放在的格子里
启动图片实际上定义了应用启动后的界面大小,所以在不同机型中我们需要做好适配,一款App必须设定对应设备的启动图片,否则点开应用会是一片黑白。
Luanch Screen File(启动页面文件):storyboard
文件,作用与Luanch Image
一样,但是启动文件的优先级高于启动图片,就是说如果两个都设置了,那么启动页面以启动文件为准,如果都没有设置,则无法启动。
Embedded Binaries(绑定二进制文件):用来连接二进制文件,一般在使用第三方SDK的时候使用。
Linked Frameworks and Libraries(链接的框架和库):既可以是SDK自带的框架,也可以是第三方框架,在Build Phases
中也有类似的功能选项。
5、info属性设置
项目资源目录下的info.plist
文件中的内容是一致,并且修改其中一个另一个会自动修改。
Localization native development region : 与本地化设置有关,为默认的开发语言
Executable file:程序安装包的名称
Bundle identifier:软件唯一的标识,是根据公司的标识与项目名称自动生成的,在上传和测试的时候会用到
InfoDictionary version:版本信息
Bundle name:App安装后显示的名称
Bundle OS Type code:用来标识软件包类型
Bundle versions string, short:发布的版本字符串
Bundle creator OS Type code:创建者的标识
Bundle version:应用程序版本号
Application requires iPhone environment:用于指示程序包是否只能运行在iPhone OS 系统上,默认为YES
Launch screen interface file base name:欢迎界面的文件名称
Main storyboard file base name:默认情况下程序的主入口
Supported interface orientations:设置程序默认支持的方向
常用权限设置:
麦克风权限:Privacy - Microphone Usage Description
是否允许使用你的麦克风?
相机权限: Privacy - Camera Usage Description
是否允许使用你的相机?
相册权限: Privacy - Photo Library Usage Description
是否允许访问你的媒体资料库?
通讯录权限: Privacy - Contacts Usage Description
是否允许访问你的通讯录?
蓝牙权限:Privacy - Bluetooth Peripheral Usage Description
是否许允使用蓝牙?
语音转文字权限:Privacy - Speech Recognition Usage Description
是否允许使用语音识别?
日历权限:Privacy - Calendars Usage Description
是否允许使用日历?
定位权限:Privacy - Location When In Use Usage Description
我们需要通过您的地理位置信息获取您周边的相关数据
定位权限:Privacy - Location Always Usage Description
我们需要通过您的地理位置信息获取您周边的相关数据
6、capabilities属性设置
性能设置开关选择,例如推送通知、云存储、游戏中心、后台模式等。
在info.plist
添加一些权限或性能开关之后,在target
的capabilities
中也会进行相应的修改的。
7、Resource Tag属性设置
Resource Tag
选项卡主要是为项目中的资源进行添加tag
分类,方便我们对齐加载顺序和加载时机进行选择和设置,即实现在需要的时候才加载资源。
初始资源的延迟加载:app有一些资源是主要功能要用到的,但在启动时并不需要。将这些资源标记为“初始需要”。操作系统在app启动时会自动下载这些资源。例如,图片编辑app有许多不常用的滤镜。
app资源的延迟加载:app有一些只在特定情景下使用的资源,当应用可能要进入这些场景时,会请求这些资源。例如,在一个有很多关卡的游戏中,用户只需要当前关卡和下一关卡的资源。
不常用资源的远程存储:app有一些很少使用的资源,当需要这些资源时会去请求它们。例如,当app第一次打开时会展示一个教程,而这个教程之后就可能不会在用到。app在第一次启动时请求教程的资源,这之后只在需要展示教程或者添加了新功能才去请求该资源。
应用内购买资源的远程存储:app提供包含额外资源的应用内购买。app会在启动完成后请求已购买模块的资源。例如,用户在一个键盘app内购买了SuperGeeky
表情包。应用程序会在启动完成后请求表情包的资源。
第一次启动时必需资源的加载:app有一些资源只在第一次启动时需要,之后的启动不再需要。例如,app有一个只在第一次启动时展示的教程。
8、build setting属性设置
Resolved列:最终确定的编译方式,无法自己设定,其结果是根据其右边三栏的选择结果以及优先级顺序来确定最后编译时采用的编译方式。在图的第二行选项卡中选择combined
选项,可以直接地看到只有该栏的最后结果。
带Target图标列:target
的build setting
配置的编译选项,可自定义。其优先级最高,一旦进行设置,则最后的编译方式以该栏的结果为准。
带Project图标列:project
的build setting
配置的编译选项,可自定义,这一栏的结果与project
中build setting
选项卡中的结果是一致的,修改其中一个地方,另一处也会自动修改。其优先级介于target
和default
之间,当target
没有设置编译选项,而该栏进行了设置时,则最后的编译方式以该栏为准。
iOS Default列:在创建项目时系统自带的默认编译选项,无法修改。优先级最低,只有当其他两栏都没有设置选项时,最后的编译方式才会以该栏为准。
优先级顺序:带Target
图标列 >> 带Project
图标列 >> iOS Default
列
9、build phase属性设置
配置编译器在不同编译阶段的参数,包括编译所需的资源文件(包括代码、配置以及各种资源文件)
Target Dependencies Target 对象依赖阶段:某些Target
可能依赖某个Target
输出的值,这里设置依赖。依赖于其他target
的输出的时候,在编译时系统会自动先编译被依赖的target
,得到输出值,再编译当前target
。(比如应用扩展、插件等等),这个阶段是无法被删除的。
Compile Sources 源文件编译阶段: 是指将有哪些源代码被编译,可以通过红框中的【+】【-】按钮进行添加或删除资源来控制编译的代码文件。并且可以通过修改改阶段的Compiler Flags
(编译器标识)来为每个单独文件设置其编译器标识,比如优化设置等等。
Link Binary With Libraries 链接二进制库阶段:是指编译过程中会引用哪些库文件,我们同样可以通过【+】【-】按钮进行添加或删除编译所引用的库文件。
Copy Bundle Resources 复制资源文件阶段:是指生成的product
的.app
内将包含哪些资源文件,同样可以通过红框中的【+】【-】按钮进行添加或删除资源来控制编译的资源文件。该阶段定义了对象中的资源文件,包括应用程序、图标、界面构造器、视频、模板等等。这些资源都会被复制到安装包的Contents/Resources
文件夹下。
10、设置应用图标和启动图片
一来通过启动图片设定了我们App应用在本次启动时以多大的界面进行展示信息,如果不设置启动界面,我们的App在打开后后会出现黑屏的显影导致应用无法正常使用。如果启动图片是iPhone6
的屏幕大小的图片,则在iPhone X
上只显示iPhone6
的屏幕大小区域,上下会有两条黑边。因此,我们再设定启动界面的时候一般是需要适配各种屏幕大小尺寸的启动图片。如下图所示的界面可以看到设置Luanch Image Source
(启动图片)是有多种尺寸的。
二来则是在我们点击应用图标启动应用时,应用启动需要一定的操作时间,在启动期间,为了增强应用程序启动时的用户体验,您应该提供一个启动图像。启动图像与应用程序的首屏幕看起来非常相似。当用户在主屏幕上点击您的应用程序图标时,iPhone OS
会立即显示这个启动图像。一旦准备就绪,您的应用程序就会显示它的首屏幕,来替换掉这个启动占位图像。一定要强调的是,之所以提供启动图像,是为了改善用户体验,并不是为了提供:应用程序进入体验」,比如启动动画。
Luanch Image Source(启动图片):同样对应着文件资源Assets.xcassets
目录中的LuanchImage
中的图片,设定了各种情况下的启动图片,具体界面如上图所示,和Appicon
一样,我们将所有切好的图标直接拖过来,他们会自动找到自己应该放在的格子里,同样可以选择设备以及不同方向的启动图。
Luanch Screen File(启动页面文件):是通过一个LuanchScreen.storyboard
文件来作为启动界面。
两种方法之间主要的区别在于启动文件的优先级高于启动图片,也就是说如果两个都设置了,那么启动页面以启动文件为准,如果都没有设置,则应用会黑屏。
由于启动文件的优先级高于启动图片,所以我们需要将启动文件后的文件名删去,此外我们还需要将项目中的LuanchScreen.storyboard
文件也给删去,这是因为App在启动时系统会自动查找LuanchScreen.storyboard
的文件进行加载。
三、UIKit框架的使用
视图分类
控件:UIControl
事件
窗口:UIWindow
根容器
容器视图:UIScrollView
(及其子视图)、UIToolbar
显示视图:UIImageView
、UILabel
、UIProgressView
、UIActivity
文本和Web视图:UITextView
、UIWebView
导航视图:UITabBar
、UINavigationBar
警告框和操作表:UIAlertController
事件传递&视图响应
UIView CALayer(单一执行原则):UIView
为其提供内容以及负责处理触摸等事件,参与响应链
CALayer
负责显示内容contents
。
视图传递流程:
视图传递流程视图响应流程:
视图响应流程属性声明:
@property (nonatomic, strong, readonly) UILabel *title;
@property (nonatomic, strong) UIPickerView *pickerView;
@property (nonatomic, strong) UIDatePicker *datePicker;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
UIView
UIWindow
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
UIView
- (void)setNeedsLayout;
- (void)layoutIfNeeded;
- (void)layoutSubviews;
- (void)removeFromSuperview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
self.view.subviews
[self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
CALayer
CALayer *layer;
layer.borderWidth
layer.borderColor
UISlider
slider.value
horizontalSlider.minimumValue = 10;
horizontalSlider.maximumValue = 100;
[horizontalSlider addTarget:self action:@selector(horizontalSliderChanged:) forControlEvents:UIControlEventValueChanged];
UISegmentedControl
segmentControl.selectedSegmentIndex = 1;
UISwitch
// 切换明文/密文时,需要去掉光标空白部分
- (void)secureSwitchAction:(UISwitch *)sender {
//切换
self.passwordTextField.secureTextEntry = !self.passwordTextField.secureTextEntry;
//
NSString* text = self.passwordTextField.text;
self.passwordTextField.text = @" ";
self.passwordTextField.text = text;
}
UIActivityIndicatorView
// 是否在旋转
self.activityIndicatorView.isAnimating
// 非活动状态时,控件会隐藏
Hides When Stopped
UIProgressView
self.progressView.progress = self.progressView.progress + 0.1;
if (self.progressView.progress == 1.0) {
[self.timer invalidate];
}
UIRefreshControl
self.collectionView.alwaysBounceVertical = YES;// 必须打开
self.refreshControl.tintColor = [UIColor grayColor];
[self.refreshControl addTarget:self action:@selector(urlRequestForCollection) forControlEvents:UIControlEventValueChanged];
[self.collectionView addSubview:self.refreshControl];
[weakSelf.refreshControl endRefreshing];// 结束刷新
UIPageController
self.pageControl = [[UIPageControl alloc] init];
self.pageControl.numberOfPages = 3;
self.pageControl.pageIndicatorTintColor = [UIColor colorWithWhite:1 alpha:0.5];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
UIScrollView
self.scrollView.pagingEnabled = YES;
self.scrollView.showsVerticalScrollIndicator = FALSE;
self.scrollView.showsHorizontalScrollIndicator = FALSE;
self.scrollView.minimumZoomScale = 0.5;
self.scrollView.maximumZoomScale = 2.0;
self.scrollView.contentSize = CGSizeMake(WIDTH * 3, HEIGHT);//内容3倍横向滑动
self.scrollView.frame = self.view.frame;//正是因为内容视图超出了屏器滚动视图的大小,才有滚动屏幕的必要
self.scrollView.contentOffset = CGPointMake(S_WIDTH * whichPage, 0.0f);
UITableView
// 设置为0不起作用
heightForHeaderInSection: return 0.1;
// 不显示右侧滑块
showsVerticalScrollIndicator = NO;
// 分割线
separatorStyle = UITableViewCellSeparatorStyleSingleLine;
// 选中风格
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// cell可以设置装饰图
cell.accessoryView = imageBtn;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;//右指示器
accessoryButtonTappedForRowWithIndexPath://方法
// cell自带imageView属性、text属性、detailTextLabel属性
cell.detailTextLabel.text = @"更多";
cell.detailTextLabel.userInteractionEnabled = YES;
cell.detailTextLabel.backgroundColor = [UIColor blackColor];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(moreInformation:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[cell.detailTextLabel addGestureRecognizer:tap];
// 表头表尾高度
self.tableView.sectionHeaderHeight = 0.1;
self.tableView.sectionFooterHeight = 20;
// 弹动
self.tableView.bounces = NO;
// 能否编辑某行
canEditRowAtIndexPath:return YES;
// cell初始化
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
cell.textLabel.text = self.vcTitles[indexPath.row];
// 选中cell
switch (indexPath.row) {
case 0:
{
UCARSubviewViewController *vc = [[UCARSubviewViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
break;
}
default:
break;
UICollectionView
// 集合视图布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(90, 130);
layout.sectionInset = UIEdgeInsetsMake(15, 15, 20, 20);//内边距
layout.minimumLineSpacing = 5;//单元格之间的间距
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
UITextField
// viewWillDisappear中调用,因为跳转页面时,警告框或者键盘不能再出现
[self.view endEditing:YES];
// 显示清空按钮
self.phoneNumberTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
// 点击清除按钮,应该将之前的文本清空
- (BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField == self.loginView.phoneNumberTextField ) {
self.phoneNumber = @"";
}
if (self.loginView.passwordTextField == textField) {
self.password = @"";
}
return YES;
}
// 去掉空格
NSString *phone = [textField.text stringByReplacingCharactersInRange:range withString:string];
self.phoneNumber = [phone stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// 边框样式
self.searchTextField.borderStyle = UITextBorderStyleRoundedRect;
// 左视图
self.searchTextField.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"commodity_searchCommodityViewController_search"]];
self.searchTextField.leftViewMode = UITextFieldViewModeAlways;
// 及时捕获文本框的值
- (NSString *)text {
_text = self.searchTextField.text;
return _text;
}
// 返回类型
self.searchTextField.returnKeyType = UIReturnKeySearch;
UIViewController
生命周期
alloc
创建对象,分配空间
init (initWithNibName)
初始化对象,初始化数据
initWithCoder:(NSCoder *)aDecoder:
(如果使用storyboard或者xib)
loadView:
加载view
viewDidLoad
载入完成,只会在APP刚开始加载的时候调用一次,所以只能用来做初始设置
viewWillAppear
需要对数据做更新
viewDidAppear
视图已在屏幕上渲染完成
viewWillDisappear
被移除覆盖时进行善后的处理,按了Home键之后,APP本身仍是挂起时候的view,不调用
viewDidDisappear
对已经消失、覆盖、隐藏了的视图做一些其他操作
dealloc
视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放
viewWillLayoutSubviews
多次调用布局
viewDidLayoutSubviews
UINavigationController
navigationItem.rightBarButtonItems = @[dismissVCItem, popVCItem];// 数组
// 配置导航栏
- (void)configureNavigationbar {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"rightItem" style:UIBarButtonItemStylePlain target:self action:@selector(rightBarItemAction)];
}
UITabBarController
// push到下个界面隐藏底部TabBar
loginViewController.hidesBottomBarWhenPushed = YES;
// 获取当前选中的item
selectedItem
// badge的数值
tabBarItem.badgeValue = @"10";
// Tab标签栏跳转,比如从用户中心跳转到首页:
[self.navigationController popViewControllerAnimated:NO];
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
UITabBarController *tab = (UITabBarController *)delegate.window.rootViewController;
tab.selectedIndex = 0;
// 数组
self.viewControllers = @[redVC, blueVC];
四、Foundation框架的使用
属性声明:
//默认关键字
@property (atomic, strong, readwrite) NSString *firstName;
@property (readonly, getter=isShit) BOOL shit;
@property (nonatomic, strong) NSArray *vcTitles;
@property (nonatomic, strong) NSArray<NSArray *> *pickerData;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) personBlock runFinishBlock;
@property (nonatomic, weak) id<WorkProtocol> delegate;
@property (nonatomic, weak) id<CountToolDataSource> dataSource;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) BOOL bodyTextChanged;
@property (nonatomic, assign) NSTimeInterval created;
缩写:
f: function
函数
p: parameter
参数
m:method
方法
c: class
类
v: variable
变量
属性关键字:
atomic:系统默认,声明的属性保证赋值和获取是线程安全的,不保证添加和移除是线程安全的(如数组)
noatomic:经常声明
retain/strong
assign/unsafe_unretained:修饰基本数据类型,如int、Bool。修饰对象类型时候,不改变其引用计数。对象释放后,会产生悬垂指针,仍访问会产生内存泄露。
weak:不改变修饰对象的引用计数,对象释放后,自动置为nil
。
copy浅拷贝和深拷贝的区别:是否开辟了新的内存空间,是否影响了引用计数。可变对象copy
后是NSArray
不可以调用add delete
等方法。只有不可变对象的copy
是浅拷贝,其他都是深拷贝。
1、基本数据类型
NSObject
NSObject *boolObj = [[NSObject alloc] init];
if (boolObj) {
NSLog(@"not nil = YES");
}
//描述信息
[Person description]
//包含关系
BOOL isKind = [aPerson isKindOfClass:[Person class]];
BOOL isKindObj = [aPerson isKindOfClass:[NSObject class]];
BOOL isMemeber = [admin isMemberOfClass:[Administrator class]];
Struct
typedef struct {
int I;
float f;
} MyIntegerFloatStruct;
//NSRange/CGRect/CGSize/CGPoint:本质为struct
NSRange dRange = NSMakeRange(1, 2);
枚举
typedef NS_ENUM(NSInteger, NumberType) {
NumberTypeInt = 0,
NumberTypeFloat = 1,
NumberTypeDouble = 2
};
NumberType type = NumberTypeInt;
typedef NS_OPTIONS(NSUInteger, TMEnumTest)
{
TMEnumTestOne = 0, // 0
TMEnumTestTwo = 1 << 0, // 1
TMEnumTestThree = 1 << 1, // 2
TMEnumTestFour = 1 << 2, // 4
};
// 基本用不到下面的语法,一般不用管
TMEnumTest test = TMEnumTestTwo | TMEnumTestThree; // 3
// 添加TMEnumTestFour到test中
test += TMEnumTestFour
// 将TMEnumTestThree从test中去除
test -= TMEnumTestThree
// 判断 TMEnumTestFour枚举 是否被包含
if (test & TMEnumTestFour)
typedef NS_OPTIONS(NSUInteger, LifeRoleOptions) {
LifeRoleOptionsFather = 1UL << 0,
LifeRoleOptionsSon = 1UL << 1,
LifeRoleOptionsHusband = 1UL << 3,
};
//基本用不到下面的语法,一般不用管
LifeRoleOptions lifeRole = LifeRoleOptionsFather | LifeRoleOptionsSon;
if (lifeRole & LifeRoleOptionsFather) {
NSLog(@"father");
}
if (lifeRole & LifeRoleOptionsHusband) {
NSLog(@"husband");
}
NSNumber
static int globalCount = 0;
NSInteger aInt = -1;
NSUInteger bUInt = 1;
// 用语法糖进行声明,可转换为多种数据类型
NSNumber *intNumber = @(-1);
NSNumber *boolNumber = @(YES);//1
NSNumber *charNumber = @('A');//65
NSLog(@"int %@ bool %@ char %@", intNumber, boolNumber, charNumber);
NSLog(@"char %d str %@ int %d", charNumber.charValue, charNumber.stringValue, charNumber.intValue);//65
BOOL
BOOL hidden = YES;
BOOL bigger = 0 > 1;
CGFloat
CGFloat cFloat = 0.0f;
NSData
dataWithContentsOfFile //从参数path 指定的文件读入二进制数据,用该数据初始化NSData 对象
writeToFile //将接收者的二进制数据写入path 指定的文件中
NSString *dataString = @"abc";
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];//<616263>
NSData *zeroData = [NSData data];//<>
NSMutableData *appendData = [zeroData mutableCopy];
[appendData appendData:data];//<616263>
NSString
//字符串对象内部使用Unicode 编码
UTF8String //返回C语言字符串的指针
initWithData //用存储在data中的二进制数据来初始化NSString 对象
caseInsensitiveCompare //不区分大小写
localizedStandardCompare //本地化
substringTo(from)Index //截取
subtringWithRange //范围
lowercaseString //小写
uppercaseString //大写
capitalizedString //首字母变为大写
floatValue 、intValue 、integerValue 、boolValue //分别被用来把NSString 类型的字符串转为float 、int、NSinteger 和BOOL 类型的数值
lastPathComponent //以文件路径名@"/tmp/image/cat.tiff' 为例,返回"cat.tiff'
pathExtension //返回文件的扩展
StringW ithContentsOfFile //通过读取文件path 中的内容来初始化一个NSString
NSString *copyChineseString = [chineseString copy];
NSString *pureChineseString = [chineseString stringByReplacingOccurrencesOfString:@"哈" withString:@""];//replace(删除)
NSComparisonResult abcOrder = [abc compare:aBc];// compare
BOOL hasSuffix = [aBc hasSuffix:@"Bc"];// hasSuffix
NSString *homePath = NSHomeDirectory();// 能够访回当前用户的主目录
NSString *workPath = [homePath stringByAppendingPathComponent:@"*work"]; //将" . "和指定的扩展名添加到现有路径的最后一个组成部分
NSArray *pathArray = [homePath componentsSeparatedByString:@"/"];//str to array
NSMutableString *testStr = [[NSMutableString alloc] initWithString:@"我知道什么呢?"];
[testStr appendString:@"什么都知道"];
//随着字符串的变化而自动扩展内存,所以capacity 不需要非常精密
NSMutableString* mutableString = [[NSMutableString alloc] initWithCapacity:20];
//在尾部添加,返回void,不产生新字符串
[mutableString appendString:@"hello"];
//尾部添加格式化字符串
[mutableString appendFormat:@"hello%i",100];
//插入字符串
[mutableString insertString:@"你好" atIndex:5];
//替换
[mutableString replaceCharactersInRange:range withString:@"大家好"];
//分割
NSArray *newArray = [str componentsSeparatedByString:@","];
//拼接
NSString *newStr = [array componentsJoinedByString:@","];
NSAttributedString *singleLineTextAttr = [[NSAttributedString alloc] initWithString:singleLineText attributes:@{NSUnderlineStyleAttributeName: @(1)}];
singleLineLabel.attributedText = singleLineTextAttr;
nil
//默认值: NO/0/nil
Person *aPerson = nil;
aPerson.age //0
NSNull
+ (NSNull *) null //不能在数组和词典对象中放入nil ,又确实需要一个特殊的对象来表示空值
NSArray
// 初始化
NSArray *columnFirst = @[@"row0",@"row1",@"row2",@"row3",@"row4"];
self.pickerData = @[columnFirst, columnFirst];
NSArray *aArray = @[@1, @2, @3];
NSArray *cArray = [NSArray arrayWithObjects:@1, @"2", nil, @3, bPerson, nil];
NSArray<NSString *> *numArray = @[@"2", @"4", @"3", @"1"];
NSArray<NSNumber *> *numArray = @[@0, @(0+1), @(1+1)];
Person *aPerson = [Person new];
_allPersons = @[aPerson, bPerson];
//取值
NSString *index1InbArray = [bArray objectAtIndex:1];
NSNumber *index0InbArray = bArray[0];
// 遍历器
// 遍历方式:for循环、NSEnumerator、for in
// enumerateObjectsUsingBlock:通过block回调,在子线程中遍历,对象的回调次序是乱序的,而且调用线程会等待该遍历过程完成
//这几个for in性能最好,for循环较低, 多线程遍历方式是性能最差的
NSEnumerator *enumerator = [array objectEnumerator];
for(id object = [enumerator nextObject]) {}
// 排序
NSArray *newArray = [array sortedArrayUsingSelector:@selector(compare:)];
//过滤
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF matches %@", @"[2-9]+"];
NSArray *filteredArray = [numArray filteredArrayUsingPredicate:predicate];
//可变
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:numArray];
[mutableArray replaceObjectAtIndex:0 withObject:@"0"];
//浅拷贝
NSArray *shallowCopyArray = [bArray copy];(shallowCopyArray == bArray)(shallowCopyArray[3] == bArray[3])
NSDictionary
NSDictionary *aDict = @{@"key": @"2", @"3": @"4", @4: @5, bPerson: @""}; //error,person不遵循copying协议
NSDictionary *bDict = @{@"key": @"2", @"3": nil}; //error,can't store nil,推荐使用语法糖初始化,常规方式遇nil可能截断,语法糖则会报错
NSDictionary<NSString *, NSString *> *strDict = @{@"1": @"a", @"2": @"b"};
// 可变
[mutableDictionary removeObjectForKey:bArray];
mutableDictionary[@"newKey"] = @"newKey";
NSSet
//初始化
NSSet *aSet = [NSSet setWithObjects:@1, bPerson, nil];
//if deep copy, all elements must conform NSCopying
NSSet *deepCopySet = [[NSSet alloc] initWithSet:aSet copyItems:YES];
NSDate
// NSString转NSDate
- (NSDate *)dateFromString:(NSString *)dateString
{
//设置转换格式
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
//NSString转NSDate
NSDate *date=[formatter dateFromString:dateString];
return date;
}
NSComparisonResult
//字符串比较大小
NSComparisonResult result = [str1 compare:str2];
if(result == NSOrderedSame) {
NSLog(@"str1 == str2");
} else if(result == NSOrderedAscending) {
NSLog(@"str1 < str2");
}
// 自定义比较方法
- [(NSComparisonResult)compareWithAge:(Person *)p {
if(_age == p.age) {
return NSOrderedSame;
}else if(_age > p.age) {
return NSOrderedDescending;
}
}
get/set
//自定义get
- (NSString *)fullName {
if (self.firstName && self.lastName) {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
return nil;
}
[self fullName];//调用get
aPerson.objCopy = testStr;//调用set
[aPerson setObjCopy:testStr];//调用set
present模式(present/dismiss)/ navi模式(push/pop)
[self.navigationController presentViewController:presentNavi animated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:layoutVC animated:YES];// 压入页面为栈顶显示
[self.navigationController popViewControllerAnimated:YES];// 能退到栈中任意位置,其上的页面全部丢弃
扩展(category)
#import "Person.h"
.h
@interface Person(Worker)
- (void)printWorkerID;
@end
.m
#import "Person+Worker.h"
@implementation Person(Worker)
默认值初始化
- (instancetype)init {
self = [super init];
if (self) {
_firstName = @"zili";
_lastName = @"kou";
_privateName = @"linux";
}
return self;
}
重载系统方法
- (instancetype)copyWithZone:(NSZone *)zone {
Person *p = [[Person alloc] init];
p.firstName = self.firstName;
p.lastName = self.lastName;
return p;
}
五、知识点大杂烩
- 在命名类时使用前缀命名可以保证类名唯一,两个字母的前缀NS和UI被苹果公司保留使用
- APP 来说最好的用户体验是隐蔽地从错误中恢复
-
import
优于include
的地方在于不会导致重复引入头文件, 不存在嵌套引用的问题 -
NSError
对象包含一个数字错误代码,域名和描述,以及封装在一个用户信息字典里的其他相关信息 -
NSNull
用于在集合中作占位符,NSNull
是单例对象,全局只能有一个(设备管理类)NSNull *null = [NSNull null];
如果你需要在集合中表示“没有对象”,你要使用NSNull
代替nil
- 加入集合中的每一个对象的生命周期都将至少和集合的生命周期一样长
-
NSValue
是NSNumber
基类,除了 C 的基本纯量类型,NSValue
也可以表示指针和结构体 -
Number
实际上是一个类集。这意味着当你在运行时创建了一个实例时,你会得到一个合适的具体化的子类,值为给定值 - 通常会在公共接口中将一个属性定义为只读,而在实现代码的上方的类扩展中将其定义为读写。这是为了让内部方法可以直接修改属性值
- 如果对于一个可读写的属性同时手动实现了存取方法,或对于一个只读属性实现了取方法,那么编译器就会认定读者接管了属性的实现,不会自动合成实例变量
- 属性默认是多线程的, 可以使用
nonatomic
单线程特性来明确编译器自动合成的存取方法只单纯设置或返回一个值,如果同一个值同时被多个线程访问,可能会发生意外。 -
@synthesize firstName = ivar_firstName;
属性名仍然为firstName
,而且可以通过firstName
和setFirstName
的存取方法以及点语法访问,但其背后运行机制中的实例变量的名称将为ivar_firstName
- 如果读者直接使用
@synthesize +
属性名,其后不加任何实例变量名,例如@synthesize firstName;
那么实例变量将会和属性名同名,没有下划线 - 读取属性时使用
somePerson.firstName
就等同于使用[somePerson firstName]
设置属性时使用somePerson.firstName = @"Johnny"
就等同于使用[somePerson setFirstName:@"Johnny""]
- 把数值类型的实例变量初始化为0,id 和其他类型的指针变量也会被初始化为nil。对于返回值类型为对象的消息来说,其返回值为nil;数字类型的是0;布尔类型的是NO;结构体类型的全部结构成员都会被设置为0;
-
==
用来判断两个不同的指针是否指向同一个对象,isEqual
用来判断是否代表相同的数据值 -
init
方法有可能返回一个同alloc
方法所创建的对象相比完全不同的对象,所以最好的方法是将两个方法嵌套发送。工厂方法是内存分配和初始化这一过程的另一种选择,或者使用简便字面量语法创建对象,这样就不用再嵌套两个方法 - 如果要使用全局变量,那么其名称在整个应用或者项目中必需唯一
- 不要在自定义
get
和set
方法中使用点语法,否则造成方法递归死循环 - 成员变量放在
interface
里默认是@protected;
,放在implementation
,默认是@private
- 不要滥用自动释放池,因为自动释放池只有在它销毁时候才会对它管理的对象做释放,如果程序中创建了大量对象,这些对象得不到有效及时释放
-
retain
是浅复制,copy
是深复制,字符串对象一般使用copy
,而不用retain
,防止字符串改变导致的连锁反应 - 自定义对象如果要支持
copy
操作,必须实现copywithzone
方法, 遵从<NSCpoying>
协议 -
stop
提供了对遍历的控制,想要让遍历过程停止的时候,将它设置为YES -
NSSet
使用散列表(hash table)
的技术存储对象,不是连续存储, 相同值只能有一个 - 编译时之所以没出错,是因为编译时无法确定存储在
id
中的对象的类型,动态绑定 - 消息选择器和参数和返回值的类型信息息结合起来构成签名
(signature)
- 没指定
nonatomic
的时候,访问方法中需要使用lock
和unlock
来保证方法的原子性,每次最多有一个线程执行lock
和unlock
之间的代码。对使用频繁且不用考虑多线程竞争的访问方法,可以在声明的时候加上nonatomic
-
@synthesize
能自动生成和接口文件中声明的属性一致的访问方法。@dynamic
自动合成无效, 用户会自已生成属性的getter
和setter
方法,@dynamic
是可选的 - 类的前置声明:引入的头文件中还有可能还引入了其他类的头文件,如此循环会大大加大编译时的负担
- 类仅能生成一个实例,程序中访问到这个类的对象时使用的都是同一个实例对象。在设计模式中这种清况称为单例模式(
singleton
),例如控制程序运行的NSApplication
。这些类通过以shared
开头的类方法返回唯一的实例对象 - 实际的复制操作并不是由
copy
来完成的.而是由实例方法copyWithZone:
完成的,需要满足协议NSCopying
将对象打包成二进制文件就称为归档(archive
),可以使用NSKeyedArchiver
和NSKeyedUnarchiver
完成对象的归档和解档操作,需要遵循协议NSCoding
-
xib
文件为XML
格式文件, 在应用被构建的问时,Storyboard
内部也会变为nib
文件资源 - 属性列表中实际的键值和Xcode 中表示的字符串有时是不同的。例如,之前所述的键
CFBundleldentifier
可能就会被表示为"Bundleindentifier"
,为表示键值原本的意思,在Xcode 中, 可以右击并选择上下文菜单中的"Show Raw Keys/Values"
集合
-
对元素均为
strong
引用, 集合持有关系,不是存副本拷贝 -
集合类型常规
copy
均为浅copy
-
copyItems
=YES
,deep copy
,会给每一个元素发送copy
消息 -
数组会给其中的所有对象发送
集合Copyretain
消息。当数组被释放的时候,它会给数组中的所有对象发送release
消息
-
字典没有越界问题,有值就返回
-
字典基于
Hash map
映射机制,hash
值唯一 -
key
和Value
必须是对象类型 不能是bool
、int
-
字典的
key
必须为NSObject
且遵循NSCopying
协议
-
NSNumber
遵循NSCopying
/NSSecureCoding
协议 -
NSData
、NSString
遵循NSCopying
/NSMutableCopying
/NSSecureCoding
协议 -
immutable
对象的copy
,会直接返回自身(优化手段) -
immutable
对象的mutableCopy
,会返回一个mutable
副本 -
mutable
对象的copy
,会返回一个immutable
副本 -
mutable
对象的mutableCopy
,会返回一个mutable
副本 -
mutableClass
为immutableClass
子类, 具备添加,删除,替换等功能, 自身可变,无需返回新实例 -
Move to Trash:
可以彻底删除 文件,而Remove References
按钮只是从工程中删除文件 - 一个工程中可以包含多个目标,一个目标包含了一些源程序文件、资源文件和编译说明 文件等内容,其中编译说明文件通过“编译参数设置"
(Build Settings)
和"编译阶段"(Build Phases)
设置,目标可以覆盖工程的设置 - 要指定运行哪一个目标,可以通过选择不同的方案
(Scheme)
来实现
布局
Auto Layout
解决布局问题,而 SizeClass
解决屏幕适配问题。
-
状态栏占用20点——导航栏占用44点——标签栏占用49点,导航栏、工具栏、搜索栏、搜索范围栏和表视图单元格等的高度都是44点。
-
Horizontally in Container
, 后面的 数字是与中间轴的偏移量 ,设置为 0表示刚好居中 -
虚线线段代表相对距离,实线线段代表绝对距离,点击可以相互切换
-
看到该约束被加粗和添加阴影显示,通过Delete键删除它
-
Top Edges
表示顶边对齐,BottomLayoutGuide
限制了视图能够放置的最低位置,Relation
是指设定的距离之间的关系,Constant
是约束值,Priority
是约束等级,当有相同的约束作用于两个视图之间时,等级高的约束优先 -
使用堆视图
StackView:
两个方向的堆视图还可以任意嵌套,堆视图中子视图的布局是由堆视图管理的,子视图不需要添加约束,但是堆视图本身是要添加约束的 -
资源分辨率--Ul设计人员 :资源图片的大小, 单位是"像素"
-
设计分辨率--开发人员:逻辑上的屏幕大 小 ,单位是“点”
-
屏幕分辨率--一般用户:渲染到屏幕上以展示给用户
-
Any
(任意)是默认情况,但通常情况下很少使用 ,因此Size Class
九宫格可以简化为Size Class
四个象限 -
选择可用的屏幕空 间 ,点击
Vary for Traits
按钮,提示Varying 4 CompactHeight Devices
, 说明这个变化会影响4个高度”紧凑"的设备,即hCompact
-
枚举类型有一个很大的作用,就是用来代替程序中的魔法数字
-
如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化
-
使用
performSelector:
是运行时系统负责去找方法,在编译时候不做任何校验;因此在使用时必须先使用respondsToSelector:
检查对象是否能调用方法,否则可能出现运行崩溃 -
OC中可以用点语法直接调用方法,但是有一个前提条件就是该方法调用不需要传参,这也是在
Masonry
框架中链式语法的主要原因 -
使用
@class
仅仅是告诉编译器这是一个类,并不会因入该类的其他信息,可以提升编译性能。为了避免两个类之间循环引用,我们在某一个类的.h
文件中用@class
进行导入,一个用#import
一个用@class
,或者两个都用@class
都可以避免报错。 -
self.xx
是调用的xx
属性的get/set
方法,而_xx
则只是使用成员变量_xx
,并不会调用get/set
方法 -
如果点表达式出现在等号
=
左边,调用该属性名称的setter
方法。如果点表达式出现在=
右边,调用该属性名称的getter
方法。 -
实际上返回的是子类的实例,这一系列的类被称为一个类簇
(cluster)
,这个父类就模拟了抽象类的功能 -
PCH文件(Precompile Prefix Header File)
,也就是预编译头文件,其作用就是,方便你一次性导入在多个文件中同时用到的头文件、宏或者URL地址等(全局使用),可以有效的帮你节约时间,提高开发效率 -
plist
只能放在根目录下,否则报错 -
给父类
view
添加透明度子类也变得透明,用如下方式给父类view
设置透明度不要使用alpha
设置
self.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5];
- 函数结构在百行内,太多逻辑结构就忘了。常量防止拼写错误系统补全,多处使用。
-
@synthesize
用在实现文件中告诉编译器实现成员变量的的访问器(getter/setter)
方法, 这样的好处是:免去我们手工书写getter
和setter
方法繁琐的代码。@synthesize age = _age;
-
objc_msgSend
会通过判断self来决定是否发送消息,如果self
为nil
,那么selector
也会为空,直接返回,不会出现问题。向nil
发消息可能会返回nil
(返回值为对象),0(返回值为一些基础数据)但对于[NSNull null]
对象发送消息时,是会crash
的,因为NSNull
类只有一个null
方法。 - 同一个
UIButton
可以多次addTarget:
添加事件,前面添加的并不会失效, 两次添加的事件均可执行,互不影响。事件执行的顺序为添加事件的顺序。 -
UIViewController
视图控制器、UIApplication
都继承自UIResponder
。 -
Storyboard
事实上是由XML
可扩展标记语言构成的文本文件
-XCTest
框架可以进行单元测试,但是无法进行性能测试。Xcode的UI测试功能能够自动记录你在应用程序界面中的每一个操作步骤, 它可以将每一步的操作自动生成对应的代码。 - Git和SVN等其它版本控制系统的一个重要不同之处,就是Git有暂存区
- Git版本控制有哪三种状态:
committed
、modified
、staged
-
Instruments
中的Allocations
工具,可以显示内存中的对象占用曲线,内存当前分配给了哪些对象,被分配内存的对象数量,以及由哪些函数进行对象的创建。 - GCD的API很大程度上是和以下哪种技术配合使用的?
block
-
Thread
多线程技术是基于什么来实现多线程的?Thread
线程 -
Operation
多线程技术是基于什么来实现多线程的?Queue
队列 -
Grand Central Dispatch
多线程技术是基于什么来实现多线程的?Task
任务 - 死锁有哪些必要条件? 互斥、请求保持、不可剥夺、循环等待
- 根类和根类协议:
NSObject
不但是个类名,NSObject
也是个协议的名称。根类的主要方法:分配、初始化、复制。 - 分配:
alloc
和allocWithZone:
方法用于从某内存区域中分配一个对象内存,并使对象指向其运行时的类定义。 - 初始化:
init
方法是对象初始化。new
是一个将简单的内存分配和初始化结合起来的方法。 - 复制:
copy
和copyWithZone
-retain
方法增加对象的保持次数。release
方法减少对象的保持次数。autorelease
方法也是减少对象的保持次数,但是以推迟的方式。retainCount
方法返回对当前的保持次数。 -
dealloc
方法由需要释放对象的实例变量以及释放动态分配的内存的类实现。
-isKindOfClass:
和isMemberOfClass:
方法来确定对象属于哪个类。后者用于测试接收者是否为指定类的实例。isSubclassOfClass:
类方法则用于测试类的继承性。 -
respondsToSelector:
方法用于测试接收者是否实现由选择器参数标识的方法。instancesRespondToSelector:
类方法则用于测试给定类的实例是否实现指定的方法。 -
conformsToProtocol:
方法用于测试接收者(对象或类)是否遵循给定的协议。 -
description
方法允许对象返回一个内容描述字符串;这个方法的输出经常用于调试(“print object”命令)
,以及在格式化字符串中和“%@”
指示符一起表示对象。 -
encodeWithCoder:
和initWithCoder:
是NSCoding
协议仅有的方法。前者使对象可以对其实例变量进行编码,后者则使对象可以根据解码过的实例变量对自身进行初始化。
网友评论