← 全部文章

一个前端工程师的ios学习(1)

学习资料存档:

  1. 着手开发ios应用程序
  2. developer
  3. cocoachina

笔记

每个应用程序都会有一个main.m的文件。这个文件相当于程序的入口文件,其中的@autoreleasepool是自动释放池(目前只知道是用于内存管理计数),会在其中调用UIApplicationMain函数。

调用UIApplicationMain会创建两个组件:

  1. XXApplication类的实例,称为应用程序对象

  2. 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,导航控制器就可以自动控制其视图之间的关系。

  • 串联图

    所谓串联图,由一系列场景组织起来的过程。每个场景表示一个视图控制器及其视图层次,场景则由过渡连接。过渡表示两个视图控制器之间的切换:源视图控制器和目的视图控制器。

    可以使用以下几种类型的过渡:

    1. Push:Push 过渡将目的视图控制器添加到导航栈。只有当源视图控制器与导航控制器连接时,才可以使用 Push 过渡
    2. Modal:Modal 过渡就是一个视图控制器以模态方式显示另一个控制器,需要用户在显示的控制器上执行某种操作,然后返回到应用程序的主流程。Modal 视图控制器不会添加到导航栈;相反,它通常被认为是所显示的视图控制器的子视图控制器。显示的视图控制器的作用是关闭它所创建和显示的 Modal 视图控制器。
    3. Custom:可以通过将UIStoryboardSegue子类化来定义自定过渡
    4. 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会出现意外报错。

    数组提供了很多方法可供调用:

    1. 查询数组长度:NSUInteger numberOfItems = [array count]

    2. 查询数组中是否含有某元素:

       if ([array containsObject:item]) {
       	...
       }
      
    3. 获取某个索引值对应的元素:[array objectAtIndex:0]或者array[0]

    4. 数组排序:

       NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
       NSArray *sortedStrings = [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];
      

      因为NSArray不可变,所以排序之后返回的是一个新的数组。

    5. 数组变化(只有在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文件中声明,那么该方法就可以被称为私有方法。私有方法只可以在对象内部被调用,而不能被其他对象调用。

写于 2014.08.06继续阅读 ↗