iOS开发系列--IOS程序开发概览

概览

终于到了真正接触IOS应用程序的时刻了,以前咱们花了不少时间去讨论C语言、ObjC等知识,对于不少朋友而言开发IOS第一天就想直接看到成果,看到能够运行的IOS程序。可是这里我想强调一下,前面的知识是你往后开发IOS的基础,没有那些知识你开发IOS会很痛苦,如今不少开发人员作开发都是只知其一;不知其二,程序质量确实使人担心,因此仍是但愿你们可以熟练掌握前面的内容,开发过程当中多思考,完全理解程序运行的原理、机制。好了言归正传,无论怎么样正式进入IOS开发仍是使人兴奋的,今天的内容虽说是开发预览,其实仍是有大量内容要说的:html

  1. 第一个iOS程序
  2. iOS程序运行过程
  3. 文件结构
  4. Storyboard
  5. 纯代码实现iOS开发
  6. 补充知识点

第一个iOS程序

首先打开Xcode—Create a new Xcode project—Single View Application--输入项目名称,同时选择使用Objective-C语言,设备选择iPhone--接下来系统默认生成一个IOS项目模板。项目目录结构以下:ios

firstios

此时什么也不用作,直接运行看一下(注意这里已经切换模拟器为iPhone5),没错咱们看到了一个iOS应用程序:json

firstIOS-iPhone5

程序的运行过程

在几乎全部的程序开发中程序通常都是从main函数开始运行的,那么IOS程序也不例外,在上图中咱们能够看到Xcode为咱们生成了一个main.m文件:windows

//
//  main.m
//  FirstIOS
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

这个默认的iOS程序就是从main函数开始执行的,可是在main函数中咱们其实只能看到一个方法,这个方法内部是一个消息循环(至关于一个死循环),所以运行到这个方法UIApplicationMain以后程序不会自动退出,而只有当用户手动关闭程序这个循环才结束。这个方法有四个参数:微信

  • 第一个参数和第二个参数其实就是main函数的参数,分别表明:参数个数、参数内容;
  • 第三个参数表明UIApplication类(或子类)字符串,这个参数默认为nil则表明默认为UIApplication类,用户能够自定义一个类继承于这个类;若是为nil则等价于NSStringFromClass([UIApplication class]),你们能够本身试验,效果彻底同样;UIApplication是单例模式,一个应用程序只有一个UIApplication对象或子对象;
  • 第四个参数是UIApplication的代理类字符串,默认生成的是AppDelegate类,这个类主要用于监听整个应用程序生命周期的各个事件(其实相似于以前咱们文章中提到的事件监听代理),当UIApplication运行过程当中引起了某个事件以后会调用代理中对应的方法;

小技巧:app

其实在Xcode中若是要看一些系统方法的解释或者参数说明,能够直接鼠标放到这个方法上,在Xcode右侧面板中就会给出帮助提示,以下图当咱们放到UIApplicationMain上以后:ide

quickHelp

也就是说当执行UIApplicationMain方法后这个方法会根据第三个参数建立对应的UIApplication对象,这个对象会根据第四个参数AppDelegate建立并指定此对象为UIApplication的代理;同时UIApplication会开启一个消息循环不断监听应用程序的各个活动,当应用程序生命周期发生改变UIApplication就会调用代理对应的方法。函数

既然应用程序UIApplication是经过代理和外部交互的,那么咱们就有必要清楚AppDelegate的操做细节,下面是UIApplication详细的代码:工具

AppDelegate.h布局

//
//  AppDelegate.h
//  
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

AppDelegate.m

//
//  AppDelegate.m
//  
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

这个类中定义了应用程序生命周期中各个事件的执行方法:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;程序启动以后执行,只有在第一次程序启动后才执行,之后再也不执行;

- (void)applicationWillResignActive:(UIApplication *)application;程序将要被激活时(得到焦点)执行,程序激活用户才能操做;

- (void)applicationDidEnterBackground:(UIApplication *)application;程序进入后台后执行,注意进入后台时会先失去焦点再进入后台;

- (void)applicationWillEnterForeground:(UIApplication *)application;程序将要进入前台时执行;

- (void)applicationDidBecomeActive:(UIApplication *)application;程序被激活(得到焦点)后执行,注意程序被激活时会先进入前台再被激活;

- (void)applicationWillTerminate:(UIApplication *)application;程序在终止时执行,包括正常终止或异常终止,例如说一个应用程序在后太运行(例如音乐播放软件、社交软件等)占用太多内存这时会意外终止调用此方法;

为了演示程序的生命周期,不妨在每一个事件中都输出一段内容,简单调整上面的代码:

AppDelegate.m

//
//  AppDelegate.m
//  FirstIOS
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
            

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"程序已经启动...");
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@"程序将要失去焦点...");
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"程序已经进入后台...");
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"程序将要进入前台...");
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"程序已经得到焦点...");
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"程序将要终止...");
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
    
}

@end

下面是各个不一样操做的运行结果:

runProgress

相信经过上面运行过程你们会对整个运行周期有个大概了解。比较容易混淆的地方就是应用程序进入前台、激活、失去焦点、进入后台,这几个方法你们要清楚。若是一个应用程序失去焦点那么意味着用户当前没法进行交互操做,所以通常会先失去焦点再进入后台防止进入后台过程当中用户误操做;若是一个应用程序进入前台也是相似的,会先进入前台再得到焦点,这样进入前台过程当中未彻底准备好的状况下用户没法操做。另一般若是应用程序要保存用户数据会在注销激活中进行(而不是在进入后台方法中进行),由于若是用户双击Home不会进入后台只会注销激活;若是用户恢复应用状态通常在进入激活状态时处理(而不是在进入前台方法中进行),由于用户多是从任务栏直接返回应用,此时不会执行进入前台操做。

固然,上面的事件并非全部AppDelegate事件,而是最经常使用的一些事件,其余事件你们能够查阅官方文档,例如-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application;用于在内存占用过多发出内存警告时调用并通知对应的ViewController调用其内存回收方法。这里简单以图形方式描述一下应用程序的调用过程:

 image

文件结构

这里对于Xcode默认为咱们生产的项目结果文件作一下简单介绍:

  1. AppDelegate(.h/.m):应用程序代理,主要用于监听整个应用程序生命周期中各个阶段的事件;
  2. ViewController(.h/.m):视图控制器,主要负责管理UIView的生命周期、负责UIView之间的切换、对UIView事件进行监听等;
  3. Main.storyboard:界面布局文件,承载对应UIView的视图控件;
  4. Images.xcassets:应用程序图像资源文件;
  5. Info.plist:应用程序配置文件;
  6. main.m:应用程序入口函数文件;
  7. xxx-prefix.pch:项目公共头文件,此文件中的导入语句在编译时会应用到全部的类文件中,至关于公共引入文件(注意在Xcode6中没有提供此文件)

Images.xcassets

关于AppDelegate、main.m前面已经介绍过了,ViewController和Main.storyboard在后面介绍,这里先说一下Image.xcassets文件。在Xcode中打开这个文件会发现里面有两个设置项:AppIcon和LaunchImage

AppIcon

AppIcon

在AppIcon中能够看到三个图标设置,当咱们勾选了右侧ios6.1 and Prior Sizes或者其余选项这个图标会自动增多,也就是说能够设计的图标跟应用程序准备支持的设备系统有关,这里咱们就以默认的ios7为例(如今基本上设备都升级到ios7了):

a.iPhone Spotlight-iOS5,6 Settings-iOS 5-7 29pt:用于设置iOS5或者iOS6的搜索图标以及iOS五、iOS六、iOS7的设置图标,大小是58*58。

iOS搜索图标:

 Spotlight

iOS设置图标:

settingicon

b.iPhone Spootlight iOS 7 40pt:设置iOS7的搜索图标,大小是80*80。具体参见上图。

c.iPhone App iOS7 60pt:设置iOS7的应用图标,大小是120*120。

iOS应用图标:

 IconSettings

LaunchImage

在LaunchImage中两个图标设计主要用于竖屏启动图

LaunchImage

a.iPhone Portraint iOS7 2x:大小为640*1136的启动图片;

b.iPhone Portraint iOS7 R4:大小为640*960的启动图片;

其实上面的图片并非全部图片都必须设置,具体要求能够直接查看苹果官方要求,例如这里咱们设置应用图标和R4启动图片后具体效果以下(这里使用的图标取材来自微信):

appico

launch

上面咱们添加了一个应用图标和一个启动图片,在Images.xcassets上右键在Fiddler中查看文件内容并进入Images.xcassets文件夹,能够看到两个子文件夹:AppIcon.appiconset和LaunchImage.launchimage,以下图:

ImagesXcassets

两个文件夹中分别存放了咱们前面设置的图片资源,除此以外还各有一个Contents.json文件,在这个文件中记录的资源信息,例如AppIcon.appiconset文件夹中的Contents.json内容以下,这里记录了每一个图标的大小名称等信息:

ContentsJson 

Info.plist

Info.plist文件记录了应用程序的配置信息,以下图:

InfoPlist

其实这些信息咱们能够在项目属性中进行配置,效果和编辑这个文档是同样的,你们能够对照查看:

GeneralSetting 

Storyboard

到目前为止咱们尚未解释咱们的程序是如何显示默认视图界面的。作过WinForm程序的朋友都知道每一个Window窗口界面都有一个设计器(对应一个设计文件),其实在IOS中也能够经过设计工具设计界面不用编写代码,这个工具就是Interface Builder。用Interface Builder编辑的文件在iOS5以前是一个“.xib”文件,从IOS5开始进行了改进,使用“.storyboard”文件进行设计。其实在上面咱们已经看到这个文件,这里重点说明一下Storyboard文件的使用。

首先咱们打开Main.storyboard,此时能够看到一个Interface Builder界面设计器出如今咱们眼前:

storyboard

在这个界面中整个核心就是右侧视图控制器ViewController,在ViewController中有一个视图UIView,这个视图用来放置其余用户操做控件。视图控制器左侧的箭头表示这个视图控制器是个主视图控制器,程序启动以后默认就会直接显示这个视图控制器的视图。咱们能够在项目属性中经过修改“Main Interface”属性来修改主视图控制器。

这里咱们不妨从Xcode右侧工具栏Object Library中拖放一些组件在上面简单完成一个登陆布局。

layout

要实现这个登陆,那么接下来就是事件和属性绑定的问题,你们应该能够猜到登陆的逻辑代码确定在ViewController.m中编写,那么storyboard文件是如何关联到这个类的呢?若是咱们在storyboard界面选中ViewController在Xcode右侧切换到Identity Inspector视图就会发现里面当前设置的是ViewController类,经过这个设置Main.storyboard和ViewController关联在一块儿。

那么如何在代码中读取两个TextField的值并经过点击按钮触发相关事件验证登陆合法性呢?要想在代码中使用UITextField,而且添加按钮点击事件,则必须在ViewController.h中定义两个UITextField属性和一个登陆方法。

ViewController

上面代码咱们须要解释一下IBOutlet、IBAction,其他代码和咱们以前写的ObjC没有任何区别。

  • IBOutlet:IBOutlet没有作任何操做,它的惟一做用就是告诉Interface Builder这个属性能够被关联到其中某个控件(在代码中能够看到代码前面多了空心圆点)。
  • IBAction:其实就是void,只是当你定义为IBAction在Interface Builder中能够关联到某个控件的事件方法(后面的关联操做将会看到,并且咱们在代码中也能够看到代码前面多了空心圆点);

下面看一下storyboard中的控件和代码中定义的属性和事件如何关联。Xcode为咱们提供了几种方式来实现代码和storyboard控件的关联:

1.拖拽控件到代码中(首先点击Xcode右上方“Show the Assistant editor”切换对应视图,而后在代码中打开.h文件,同时打开Interface Builder,按住ctrl键拖拽控件到代码中相应的位置进行关联),关联后属性或方法前的空心圆变成实心表示已经关联到具体控件(注意:事实上,从控件拖拽到代码时若是代码中没有定义对应的属性和方法Interface Builder会自动生成代码)。

controlToCode

2.从控件场景中拖拽控件到代码,关联后属性或方法前的空心圆变成实心表示已经关联到具体控件。(在Interface Builder中点击左下角“Show Document outline”显示控件结构树,选中相应的控件按住Ctrl键拖拽到代码中的属性或方法上)

controlSceneToCode

3. 在控件上右键找到对应的属性或方法关联到代码中对应的属性或方法便可,关联后属性或方法前的空心圆变成实心表示已经关联到具体控件。

propertyToCode.gif

4.与方法3相似,再也不截图,只是经过View Control Scene中的控件右键来关联,关联后属性或方法前的空心圆变成实心表示已经关联到具体控件。(在Interface Builder中点击左下角Show Document outline显示控件结构树,选中相应的控件右键拖拽到代码中的属性或方法上)

5.对于前面几种方法其实咱们还能够直接从代码拖拽到控件上面,这里简单演示一种,其余状况你们能够本身试验。

codeToControl.gif

 

若是要删除关联,能够采用第3、第四种方式在控件上右键,在关联菜单中找到对应的关联删除便可。此外须要注意对于一个控件而言可能有多个事件,当咱们使用第三种或第四种方式直接选择具体某个事件关联到login:方法天然没有问题,可是第1、第2、第五种方式没有提示咱们关联到哪一个事件而是使用一个控件的默认事件(对于UIButton就是Touch Up Inside事件)。

既然控件和代码属性或方法已经作了关联,这里咱们看一下具体效果,这里简单修改一下ViewController.m

//
//  ViewController.m
//  FirstIOS
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
            
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)login:(UIButton *)btn{
    if ([_phoneNumber.text isEqual:@"123"]&&[_password.text isEqual:@"456"]) {
        NSLog(@"登陆成功!");
    }
}

@end

这里实现了login:方法模拟登陆的过程,能够发现当在手机号码中输入“123”,在密码中输入“456”点击登陆会输出”登陆成功!“。

纯代码实现iOS开发

storyboard进行界面设计当然不错,特别是对于初学者常常会使用设计器进行界面设计,可是实际开发过程当中咱们不少状况下会直接使用代码进行界面布局,特别是对于复杂的界面布局更是如此。下面咱们就从一个空项目创建一个相似于前面的登陆界面。

直接在Xcode中建立“Empty Application”(注意在Xcode6中这个选项已经没有了,这里采用Xcode5.1),此时会发现已经没有ViewController和storyboard文件,咱们须要手动建立一个视图控制器(在项目中右键选择Objective-c class,默认继承自UIViewController,输入类名:KCMainViewController便可)。

新建的视图控制器默认状况下是没法加载到程序运行界面上的,此时须要在应用程序代理的程序加载完毕事件中手动加载并显示咱们的视图。修改以前KCAppDelegate.m代码以下:

//  KCAppDelegate.m
//  IOSByCode
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "KCAppDelegate.h"

@implementation KCAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

咱们修改上面- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions的代码以下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //设置window属性(在KCAppDelegate中定义的window属性),初始化windows的大小和位置
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    //设置window的背景
    self.window.backgroundColor = [UIColor whiteColor];
    
    //初始化KCMainViewController
    KCMainViewController *mainController=[[KCMainViewController alloc]init];
    //设置自定义控制器的大小和window相同,位置为(0,0)
    mainController.view.frame=self.window.bounds;
    //设置此控制器为window的根控制器
    self.window.rootViewController=mainController;
    
    //设置window为应用程序主窗口并设为可见
    [self.window makeKeyAndVisible];
    return YES;
}

而后在咱们自定义的KCMainViewController.m中添加一个UIImageView、两个控件UITextField和一个UIButton控件,而且实现具体的登陆方法。

KCMainViewController.h

//
//  KCMainViewController.h
//  IOSByCode
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface KCMainViewController : UIViewController

#pragma mark logo
@property (nonatomic,strong) UIImageView *logo;
#pragma mark 手机号码
@property (nonatomic,strong) UITextField *phoneNumber;
#pragma mark 密码
@property (nonatomic,strong) UITextField *password;
#pragma mark 登陆按钮
@property (nonatomic,strong) UIButton *loginButton;

#pragma mark 点击事件
-(void)login:(UIButton *)btn;

@end

KCMainViewController.m

//
//  KCMainViewController.m
//  IOSByCode
//
//  Created by Kenshin Cui on 14-2-23.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import "KCMainViewController.h"

@interface KCMainViewController ()

@end

@implementation KCMainViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //self.view.backgroundColor=[UIColor redColor];
    
    //添加图片
    CGRect logoRect=CGRectMake(100, 50, 100, 200);
    _logo=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"LoginBackground.png"]];//设置图片
    _logo.contentMode=UIViewContentModeScaleAspectFit;//设置内容填充模式
    _logo.frame=logoRect;//设置控件大小和位置(相对于父控件的位置)
    [self.view addSubview:_logo];//添加到KCMainViewController的View中
    
    //添加手机号码输入框
    CGRect phoneNumberRect=CGRectMake(20, 320, 280, 30);
    _phoneNumber=[[UITextField alloc]initWithFrame:phoneNumberRect];
    _phoneNumber.borderStyle=UITextBorderStyleRoundedRect;//设置文本框的边框样式
    [self.view addSubview:_phoneNumber];
    
    //添加密码输入框
    CGRect passwordRect=CGRectMake(20, 380, 280, 30);
    _password=[[UITextField alloc]initWithFrame:passwordRect];
    _password.borderStyle=UITextBorderStyleRoundedRect;
    [self.view addSubview:_password];
    
    //添加登陆按钮
    CGRect loginButtonRect=CGRectMake(10, 440, 300, 25);
    _loginButton=[[UIButton alloc]initWithFrame:loginButtonRect];
    [_loginButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];//设置标题内容颜色
    [_loginButton setTitle:@"登陆" forState:UIControlStateNormal];//设置按钮标题
    [_loginButton addTarget:self action:@selector(login:) forControlEvents:UIControlEventTouchUpInside];//添加点击事件
    [self.view addSubview:_loginButton];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)login:(UIButton *)btn{
    if ([_phoneNumber.text isEqual:@"123"]&&[_password.text isEqual:@"456"]) {
        NSLog(@"登陆成功!");
    }else{
        NSLog(@"登陆失败!");
    }
}


@end

运行效果以下,与以前使用storyboard建立的界面相似,同时也能点击登陆:

runUI

UIView

在这里咱们须要对上面的代码同样解释,在弄清上面的代码以前咱们不得不熟悉一个UIKit中最重要的类UIView。

  1. UIView就是指界面可见的控件元素,全部的控件最终都继承自UIView,UIView中还能够添加其余UIView(经过addSubView方法);
  2. 在一个iOS应用中必须有一个主窗口UIWindow(理论上也能够有多个UIWindow可是只有一个是主Window,并且只有主Window能够和用户交互),UIWindow也是继承自UIView,它拥有UIView的全部属性、方法;
  3. 在UIWindow中必须有一个根控制器,这个控制器距离UIWindow是最近的;设置一个控制器为根控制器和直接经过addSubView添加控制器的视图(view属性)到window并不彻底同样(例如若是仅仅添加控制器视图那么应用虽然能够显示可是不支持旋转);
  4. UIViewController是视图控制器,主要用来控制UIView,在UIViewController内部有一个UIView(view属性);

在上面的代码中咱们首先在应用程序加载完毕以后加载一个UIWindow对象,同时把咱们的视图控制器KCMainController设置为UIWindow的根视图控制器,而后设置这个UIWindow为主窗口并可见。当主窗口设置为可见过程当中会调用视图控制器的loadView方法来加载视图(注意视图控制器的loadView方法是延迟加载的,第一次调用视图控制器的view属性才会调用此方法;因为makeKeyAndVisible方法中会使用视图控制器的view属性因此此时会调用视图控制器的loadView方法),视图加载完以后调用viewDidLoad方法,在这个方法中咱们添加登陆相关控件并将这些控件加载到视图控制器KCMainViewController的视图view中。

下面咱们看一下应用程序最终的布局,相信经过这张图你们对于iOS的布局会有一个大体了解:

iOSLayout

补充知识点

1.iOS尺寸设置--在iOS中尺寸的单位是点不是像素,在retina屏幕中一个点有两个像素。此外在retina屏幕中图片通常采用”xxx@2x.png”命名,在代码中使用时只须要写成“xxx.png”程序会自动根据屏幕类型在retain屏幕下使用”xxx@2x.png”图片,在非retain屏幕下采用”xxx.png”图片。                                                   

ScreenSize

2.应用程序图像资源尺寸--其实关于图片尺寸规定咱们能够直接查看Xcode自带帮助文档,例如能够查看“Icon and Image Sizes”一节得到图片大小说明:

IconSize

关于iOS图标命名这里再也不赘述,苹果官方也给出了具体的代码示例:Application Icons and Launch Images for iOS

3.模拟器文件存储的位置--模拟器中为何能够运行咱们的程序,程序到底在什么位置?

这些文件其实在Mac中 OS X中是隐藏的,首先经过“defaults write com.apple.finder AppleShowAllFiles -bool true”命令显示隐藏文件(关闭隐藏文件显示经过“defaults write com.apple.finder AppleShowAllFiles -bool false”命令),而后到“/Users/kenshincui/Library/Application Support/iPhone Simulator/7.1/Applications”文件夹中会看到不少GUID命名的文件夹,只要一个一个查看就能够找到咱们的程序。模拟器运行时会加载这个文件夹中的应用程序包显示到模拟器中。

bundle

能够看到在上图中有一个IOSByCode的应用程序包,咱们能够经过“显示包内容”查看具体程序资源:

bundleContent

4.UIApplication--前面一直提到UIApplication对象,这个对象在iOS中是一个单例,咱们经过[UIApplication sharedApplication]得到(注意在iOS开发中通常以shared开头的对象都是单例)。这里列举一些UIApplication的经常使用方法:

UIApplicationMethods

例如调用applicationIconBadgeNumber方法以后效果以下:

badgeNumber

5.组织标示--前面咱们在新建项目中有一个“Organization Identifier”是作什么的呢?它是组织惟一标示,通常咱们会使用公司的域名形式(这个域名通常会倒序书写,例如公司域名为:www.cmjstudio.com,咱们这里就写成com.cmjstudio),和项目名称共同组成一个程序的惟一标示“Bundle Identifier”,这个标示在整个App Store中是惟一的,若是两个应用程序标示彻底同样,那么安装时会先卸载前面的程序再安装新程序。

相关文章
相关标签/搜索