一个前端工程师的ios学习(1)
学习资料存档:
笔记
每个应用程序都会有一个main.m的文件。这个文件相当于程序的入口文件,其中的@autoreleasepool是自动释放池(目前只知道是用于内存管理计数),会在其中调用UIApplicationMain函数。
调用UIApplicationMain会创建两个组件:
-
XXApplication类的实例,称为应用程序对象
-
XXAppDelegate类的实例,称为应用程序委托
XYAppDelegate类会在两个文件中被定义,这两个文件分别是,接口文件:
XYAppDelegate.h和实现文件:XYAppDelegate.m。个人理解,
.h文件应该是定义可接收的事件,和触发之后的回调,.m文件中具体实现回调的内容。
MVC
Model
View
位于视图层次顶部的是窗口对象,由UIWindow的实例表示,它是一个最基本的容器对象,但不会显示任何东西。需要将视图对象添加到其中。
视图对象通常用UIKit表示,UIKit是UIView类或其子类的实例。
Controller
在IOS程序中,可以使用UIViewController来管理视图及其分视图层次。
通过Action和Outlet来定义view和controller之间的关系。
-
定义Action
使用 IBAction 返回类型和 sender 参数来创建并实现方法
- (IBAction)restoreDefaults:(id)sender; -
操作对象Outlet
可以通过直接拖动视图元素到控制器文件(
.h)来创建。Outlet 被定义为 IBOutlet 属性。
@property (weak, nonatomic) IBOutlet UITextField *textField; -
导航控制器(视图router)
导航控制器使用
UINavigationController类,用于管理在一系列视图中的向前或者向后操作。导航控制器使用一种叫做导航栈的方式管理视图,添加到堆栈的第一个视图将作为根视图,永远不会从堆栈中被删除;而其他视图可以被push或者pop。
导航控制器会控制程序的导航栏,包括一个返回按钮和其他自定义按钮。添加到导航栈中的每个视图都会显示这个导航栏。一般来说,不用单独去控制导航控制器,只需要将视图push或者pop,导航控制器就可以自动控制其视图之间的关系。
-
串联图
所谓串联图,由一系列场景组织起来的过程。每个场景表示一个视图控制器及其视图层次,场景则由过渡连接。过渡表示两个视图控制器之间的切换:源视图控制器和目的视图控制器。
可以使用以下几种类型的过渡:
- Push:Push 过渡将目的视图控制器添加到导航栈。只有当源视图控制器与导航控制器连接时,才可以使用 Push 过渡
- Modal:Modal 过渡就是一个视图控制器以模态方式显示另一个控制器,需要用户在显示的控制器上执行某种操作,然后返回到应用程序的主流程。Modal 视图控制器不会添加到导航栈;相反,它通常被认为是所显示的视图控制器的子视图控制器。显示的视图控制器的作用是关闭它所创建和显示的 Modal 视图控制器。
- Custom:可以通过将
UIStoryboardSegue子类化来定义自定过渡 - Unwind:Unwind 过渡通过向后移动一个或多个过渡,让用户返回到视图控制器的当前实例。使用 Unwind 过渡可以实现反向导航
通过向目的视图控制器添加操作方法,可以创建unwind过渡。可以跳转到的方法必须返回一个操作IBAction,并在串联过渡图UIStoryboardSegue中作为参赛使用。
消息机制
在 Objective-C 术语中,一个对象通过调用另一个对象的方法来向该对象发送消息。
例如:
[somePerson sayHi]
就是调用somePerson实例的sayHi方法。
事件
segue
Object-C
数据类型:
Foundation框架是一个用于定义数据类型的框架,Foundation包括了基本数据的值类(字符串、数字等),以及用于存储其他对象的集合类(例如数组、字典等)。
值对象:
-
字符串:字符串可以通过使用单个字符使用单引号,多个字符使用双引号的方式创建,但是在object-c中,更推荐使用
NSString对象。NSString类为字符串提供了一个对象包装器,要使用此NSString字面常量,只需在双引号字符串前面添加 (@) 符号,可以通过以下几种方法来创建NSString对象:NSString *myString = @"My String"; // 感觉有点像Python啊! NSString *otherString = [NSString stringWithFormat:@"%d %@",1,@"String"] // 以C的string方式创建 NSString *fromCString = [NSString StringWithCString:"A String" encoding:NSUTF8StringEncoding] -
数字:有了字符串的基础,数字的创建看起来跟字符串很相似,也可以通过
@这个字符来快速创建。NSNumber *myInt = @3; NSNumber *myDoubleValue = @3.1415926甚至可以使用 NSNumber 字面常量来创建封装的 Boolean 值和字符值:
NSNumber *myBoolValue = @YES; NSNumber *myCharValue = @'V';还可以创建
NSNumber对象表示无符号整型,长整型,长长整型和浮点值,创建方法就是分别在数字的后面加上U,L,LL和F,例如:NSNumber *myFloat = @3.1F;
集合对象:
-
数组:包含有序的对象集。通过在数组中指定对象的位置(即索引)来访问对象。数组中首个元素的索引是0。数组的类型包括两种
NSArray和NSMutableArray,分别为固定数组和可变数组。创建数组对象可以通过
arrayWithObject和initWithObject创建,如果使用这两种方法进行创建的话,最后一个元素需要为nil。如果数组中间的某个元素为nil,那么该数字将在此处结束。NSArray *myArray = [NSArray arrayWithObject:firstItem,secondItem,nil]除此之外,还可以使用
@来定义数组,如下所示:NSArray *myArray = @[firstItem,secondItem];使用
@方法时,不需要定义nil,如果在数组中定义了nil会出现意外报错。数组提供了很多方法可供调用:
-
查询数组长度:
NSUInteger numberOfItems = [array count] -
查询数组中是否含有某元素:
if ([array containsObject:item]) { ... } -
获取某个索引值对应的元素:
[array objectAtIndex:0]或者array[0] -
数组排序:
NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"]; NSArray *sortedStrings = [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];因为
NSArray不可变,所以排序之后返回的是一个新的数组。 -
数组变化(只有在
NSMutableArray类型的数组中,才具有此特性):// 添加元素 [mutableArray addObject:@"String"] // 替换元素 [mutableArray replaceObjectAtIndex:0 withObject:@"String"] // 本数组内排序 [mutableArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
-
-
集合:集合与数组很相似,分为
NSSet和NSMutableSet两种。采用initWithObject或者setWithObject创建时,都会以nil作为结束。但是不同的是集合首先是无序的,其次集合中不会包括重复元素。 -
字典:字典就是
key-value类型的数据集合。字典的创建可以通过
initWithObjectAndKeys和dictionaryWithObjectsAndKeys创建:NSDictionary *myDic = [NSDictionany dictionaryWithObjectsAndKeys: value : key, nil ]另外,还可以通过
@来创建(这种方法要简单很多啊!):NSDictionary *myDic = @{ key : value }字典的查询可以通过两种方法:
NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"]; NSNumber *storedNumber = dictionary[@"magicNumber"];很明显,直接使用key查询是最方便的。
-
NSNull:在object-c中,
nil表示的是无对象,不能插入到集合当中。要在集合中表示无对象的概念,应该使用NSNull类,例如:NSArrray *array = @[firstItem,[NSNull null],thirdItem];
自定义类:
类的接口和实现放在单独的文件中,分别是.h和.m文件。
接口:
接口的实现方式通常如下:
@interface className : fatherClass
@end
其中fatherClass即为继承的类。
实现:
实现文件中,需要引入对应的接口文件,如下所示:
#import className.h
@implementation className
@end
如果在接口中声明了任何方法,那么在实现文件中,都需要将其实现。
属性:
属性定义在接口文件中,如下所示:
@interface className : fatherClass
@property NSString *name = @"MyClass";
@property BOOL complete;
@property (readonly) NSDate *completionDate;
@end
属性是对所有对象公开的,任何调用此对象的其他对象都可以查看或者修改其属性,如果想让属性不可修改,可以加上(readonly)标志,标明只读。
另外,如果想让属性完全私有化,对对象外的其他地方都不可见,那么可以在实现文件中定义该属性:
#import "className.h"
@interface XYZToDoItem ()
@property NSDate *completionDate;
@end
方法:
方法定义对象的行为,类具有哪些方法,需要在接口文件中声明:
@interface className : fatherClass
- (void)markAsCompleted:(BOOL)isComplete;
+ (NSString)returnClassName;
@end
在接口文件中使用-声明的,标明该方法是实例方法,使用+声明的,标明该方法是类方法。
声明符号后面跟着的括号(void),标明该方法不会返回任何值,如果需要返回值,那么该括号中填写的就是返回值的类型。
再返回值类型声明的后面,是方法名称,也就是在.m文件中,需要对此方法进行实现。
在:后面跟着的是参数。参数需要定义类型和名称,在.m文件中,调用参数就需要使用声明中的参数名称,多个参数之间使用空格分割。
方法的具体实现放在.m文件中,如下所示;
#import "className.h"
@implementation className
-(void)markAsCompleted:(BOOL)isComplete {
// 实现的具体内容
}
@end
在实现方法中self表示该对象本身。
另外,在.m文件中,可以定义对象本身的私有方法。如果一个方法在.m文件中定义,但是没有在.h文件中声明,那么该方法就可以被称为私有方法。私有方法只可以在对象内部被调用,而不能被其他对象调用。