转载

一个java程序员自学IOS开发之路(七)

一个 java 程序员自学 IOS 开发之路(七)

2015/11/2

Day 30

今天学习UIPickerView ,UIDatePicker

他们的使用方法与 UITableView及其类似,实现数据源方法,代理方法就能显示数据

一.UIPickerView

1.UIPickerView 的常见属性

// 数据源( 用来告诉UIPickerView 有多少列多少行)

@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;

// 代理( 用来告诉UIPickerView 每1 列的每1 行显示什么内容, 监听UIPickerView 的选择)

@property(nonatomic,assign) id<UIPickerViewDelegate>   delegate;

// 是否要显示选中的指示器

@property(nonatomic)        BOOL                       showsSelectionIndicator;

// 一共有多少列

@property(nonatomic,readonly) NSInteger numberOfComponents;

2.UIPickerView 的常见方法

// 重新刷新所有列

- (void)reloadAllComponents;

// 重新刷新第component

- (void)reloadComponent:(NSInteger)component;

// 主动选中第component 列的第row

- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;

// 获得第component 列的当前选中的行号

- (NSInteger)selectedRowInComponent:(NSInteger)component;

3. 数据源方法(UIPickerViewDataSource)

//  一共有多少列

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;

//  第component 列一共有多少行

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;

4. 代理方法(UIPickerViewDelegate)

//  第component 列的宽度是多少

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;

//  第component 列的行高是多少

- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;

//  第component 列第row 行显示什么文字

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;

//  第component 列第row 行显示怎样的view( 内容)

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;

//  选中了pickerView 的第component 列第row

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

二.UIDatePicker

1.常见属性

// datePicker 的显示模式

@property (nonatomic) UIDatePickerMode datePickerMode;

// 显示的区域语言

@property (nonatomic, retain) NSLocale   *locale;

2. 监听UIDatePicker 的选择

* 因为UIDatePicker 继承自UIControl, 所以通过addTarget:... 监听

2015/11/3

Day 31

今天学习程序启动原理

  • 建立一个工程后,会在 Supporting files文件夹下看到一个 “工程名 -Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除
  • 在现在 Xcode7创建的工程中,这个配置文件的名字就叫 “Info.plist”
  • 项目中其他 Plist文件不能带有 “Info”这个字眼,不然可能会被错认为是传说中非常重要的 “Info.plist”

一个java程序员自学IOS开发之路(七)

常见属性

Localiztion native development region(CFBundleDevelopmentRegion) - 本地化相关

Bundle display name(CFBundleDisplayName) - 程序安装后显示的名称, 限制在10 -12 个字符,如果超出,将被显示缩写名称

Icon file(CFBundleIconFile) -app 图标名称, 一般为Icon.png

Bundle version(CFBundleVersion) - 应用程序的版本号,每次往App Store 上发布一个新版本时,需要增加这个版本号

Main storyboard file base name(NSMainStoryboardFile) - 主storyboard 文件的名称

Bundle identifier(CFBundleIdentifier) - 项目的唯一标识,部署到真机时用到

Xcode6 之前,创建一个新工程 xcode 会在 Supporting files 文件夹下面自动创建一个 工程名 -Prefix.pch” 文件,也是一个头文件, pch 头文件的内容能被项目中的其他所有源文件共享和访问。是一个预编译文件。

首先说一下 pch的作用:

1.存放一些全局的宏 (整个项目中都用得上的宏 )

2.用来包含一些全部的头文件 (整个项目中都用得上的头文件 )

3.能自动打开或者关闭日志输出功能

Xcode6以后就不能自动创建了,苹果为什么要这么做呢,原因可能是因为大家把大量的头文件和宏定义放到 pch里边,导致编译时间过长。苹果去掉他可能是要加快编译时间增加用户体验。虽然失去了编程的便利性。不得不佩服苹果的以用户为中心的思考方式

UIApplication

UIApplication 对象是应用程序的象征

每一个应用都有自己的 UIApplication对象,而且是单例的

通过[UIApplication sharedApplication] 可以获得这个单例对象

一个 iOS程序启动后创建的第一个对象就是 UIApplication对象

利用 UIApplication对象,能进行一些应用级别的操作

  • 设置应用程序图标右上角的红色提醒数字

@property(nonatomic) NSInteger applicationIconBadgeNumber;

  • 设置联网指示器的可见性

@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;

iOS7 开始,系统提供了 2 种管理状态栏的方式

  • 通过UIViewController 管理(每一个UIViewController 都可以拥有自己不同的状态栏)
  • 通过 UIApplication管理(一个应用程序的状态栏都由它统一管理)
  • iOS7中,默认情况下,状态栏都是由 UIViewController管理的, UIViewController实现下列方法就可以轻松管理状态栏的可见性和样式
  • 状态栏的样式

- (UIStatusBarStyle)preferredStatusBarStyle; 

  • 状态栏的可见性

- (BOOL)prefersStatusBarHidden;

UIApplication 有个功能十分强大的 openURL: 方法

- (BOOL)openURL:(NSURL*)url;

openURL: 方法的部分功能有

  • 打电话

UIApplication *app = [UIApplication sharedApplication];

[app openURL:[NSURL URLWithString:@"tel://10086"]];

  • 发短信

[app openURL:[NSURL URLWithString:@"sms://10086"]];

  • 发邮件

[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];

  • 打开一个网页资源

[app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];

  • 打开其他 app程序

所有的移动操作系统都有个致命的缺点: app很容易受到打扰。比如一个来电或者锁屏会导致 app进入后台甚至被终止

还有很多其它类似的情况会导致 app受到干扰,在 app受到干扰时,会产生一些系统事件,这时 UIApplication会通知它的 delegate对象,让 delegate代理来处理这些系统事件

delegate可处理的事件包括:

应用程序的生命周期事件 (如程序启动和关闭 )

系统事件 (如来电 )

内存警告

… …

一个java程序员自学IOS开发之路(七)

  • 每次新建完项目,都有个带有 “AppDelegate”字眼的类,它就是 UIApplication的代理
  • AppDelegate 默认已经遵守了UIApplicationDelegate 协议,已经是UIApplication 的代理

IOS 程序启动过程

一个java程序员自学IOS开发之路(七)

UIApplicationMain

main 函数中执行了一个UIApplicationMain 这个函数

int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);

argc 、argv :直接传递给UIApplicationMain 进行相关处理即可

principalClassName :指定应用程序类名(app 的象征),该类必须是UIApplication( 或子类) 。如果为nil, 则用UIApplication 类作为默认值

delegateClassName :指定应用程序的代理类,该类必须遵守UIApplicationDelegate 协议

UIApplicationMain 函数会根据principalClassName 创建UIApplication 对象,根据delegateClassName 创建一个delegate 对象,并将该delegate 对象赋值给UIApplication 对象中的delegate 属性

接着会建立应用程序的Main Runloop (事件循环),进行事件的处理( 首先会在程序完毕后调用delegate 对象的application:didFinishLaunchingWithOptions: 方法)

程序正常退出时UIApplicationMain 函数才返回

UIWindow

UIWindow 是一种特殊的UIView ,通常在一个app 中只会有一个UIWindow

iOS程序启动完毕后,创建的第一个视图控件就是 UIWindow,接着创建控制器的 view,最后将控制器的 view添加到 UIWindow上,于是控制器的 view就显示在屏幕上了

一个 iOS程序之所以能显示到屏幕上,完全是因为它有 UIWindow

也就说,没有 UIWindow,就看不见任何 UI界面

添加UIView 到UIWindow 中两种常见方式:

  • - (void)addSubview:(UIView *)view;

直接将view 添加到UIWindow 中,但并不会理会view 对应的UIViewController

  • @property(nonatomic,retain) UIViewController *rootViewController;

自动将rootViewController 的view 添加到UIWindow 中,负责管理rootViewController 的生命周期

常用方法

  • - (void)makeKeyWindow;

让当前UIWindow 变成keyWindow (主窗口)

  • - (void)makeKeyAndVisible; 

让当前UIWindow 变成keyWindow ,并显示出来

UIWindow 的获得

  • [UIApplication sharedApplication].windows

在本应用中打开的 UIWindow列表,这样就可以接触应用中的任何一个 UIView对象

(平时输入文字弹出的键盘,就处在一个新的 UIWindow中 )

  • [UIApplication sharedApplication].keyWindow

用来接收键盘以及非触摸类的消息事件的 UIWindow,而且程序中每个时刻只能有一个 UIWindow是 keyWindow。如果某个 UIWindow内部的文本框不能输入文字,可能是因为这个 UIWindow不是 keyWindow

  • view.window

获得某个UIView 所在的UIWindow

四大对象的关系

一个java程序员自学IOS开发之路(七)

程序启动的完整过程

1.main 函数

2.UIApplicationMain

* 创建UIApplication 对象

* 创建UIApplication 的delegate 对象

3.delegate 对象开始处理( 监听) 系统事件( 没有storyboard)

* 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions: 方法

* 在application:didFinishLaunchingWithOptions: 中创建UIWindow

* 创建和设置UIWindow 的rootViewController

* 显示窗口

3. 根据Info.plist 获得最主要storyboard 的文件名, 加载最主要的storyboard( 有storyboard)

* 创建UIWindow

* 创建和设置UIWindow 的rootViewController

* 显示窗口

2015/11/4

Day 32

今天开始学习多控制器

控制器常见的创建方式有以下几种

  • 通过storyboard 创建
  • 直接创建

ViewController *vc = [[ViewController alloc] init];

  • 指定 xib文件来创建

ViewController *vc = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];

通过 storyboard 创建控制器

  • 先加载storyboard 文件(Test 是storyboard 的文件名)

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];

  • 接着初始化 storyboard中的控制器

初始化 “初始控制器 ”(箭头所指的控制器)

MJViewController *mj = [storyboard instantiateInitialViewController];

  • 通过一个标识初始化对应的控制器

MJViewController *mj = [storyboard instantiateViewControllerWithIdentifier:@”mj"];

控制器 view的创建

一个java程序员自学IOS开发之路(七)  

控制器的 view是延迟加载的:用到时再加载

可以用isViewLoaded 方法判断一个UIViewController 的view 是否已经被加载

控制器的view 加载完毕就会调用viewDidLoad 方法

一个 iOS的 app很少只由一个控制器组成 ,除非这个 app极其简单

app中有多个控制器的时候 ,我们就需要对这些控制器进行管理

有多个 view时,可以用一个大的 view去管理 1个或者多个小 view

控制器也是如此,用 1个控制器去管理其他多个控制器

比如,用一个控制器 A去管理 3个控制器 B、 C、 D

控制器 A被称为控制器 B、 C、 D的 “父控制器

控制器 B、 C、 D的被称为控制器 A的 “子控制器

为了便于管理控制器, iOS提供了 2个比较特殊的控制器

UINavigationController

UITabBarController

利用 UINavigationController,可以轻松地管理多个控制器,轻松完成控制器之间的切换,典型例子就是系统自带的 “设置 ”应用

一个java程序员自学IOS开发之路(七)

UINavigationController 的使用步骤

初始化UINavigationController

设置UIWindow 的rootViewController 为UINavigationController

根据具体情况,通过 push方法添加对应个数的子控制器

注意:xcode6 之后push 和modal 就被废弃了。只能用于ios8 之前

一个java程序员自学IOS开发之路(七)

这两个方法被废弃了,我们需要找到合适的方法来代替,这时候我们发现 show 和 Present Modally 方法,这个一般可以满足使用要求。

  • UINavigationController 以栈的形式保存子控制器

@property(nonatomic,copy) NSArray *viewControllers;

@property(nonatomic,readonly) NSArray *childViewControllers;

  • 使用 push方法能将某个控制器压入栈

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

  • 使用 pop方法可以移除控制器
  • 将栈顶的控制器移除

- (UIViewController *)popViewControllerAnimated:(BOOL)animated;

  • 回到指定的子控制器

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;

  • 回到根控制器(栈底控制器)

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated;

导航栏的内容由栈顶控制器的 navigationItem属性决定

UINavigationItem 有以下属性影响着导航栏的内容

  • 左上角的返回按钮

@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;

  • 中间的标题视图

@property(nonatomic,retain) UIView          *titleView;

  • 中间的标题文字

@property(nonatomic,copy)   NSString        *title;

  • 左上角的视图

@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;

  • UIBarButtonItem *rightBarButtonItem  右上角的视图

@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;

数据存取

iOS应用数据存储的常用方式

XML 属性列表(plist )归档

Preference( 偏好设置)

NSKeyedArchiver 归档(NSCoding)

SQLite

Core Data

应用沙盒

每个 iOS应用都有自己的应用沙盒 (应用沙盒就是文件系统目录 ),与其他文件系统隔离。应用必须待在自己的沙盒里,其他应用不能访问该沙盒

应用沙盒的文件系统目录,如下图所示(假设应用的名称叫 Layer)

一个java程序员自学IOS开发之路(七)

应用程序包: (上图中的 Layer)包含了所有的资源文件和可执行文件

Documents :保存应用运行时生成的需要持久化的数据, iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

tmp :保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。 iTunes同步设备时不会备份该目录

Library/Caches :保存应用运行时生成的需要持久化的数据, iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据

Library/Preference :保存应用的所有偏好设置, iOS的 Settings(设置 )应用会在该目录中查找应用的设置信息。 iTunes同步设备时会备份该目录

应用沙盒目录的常见获取方式

  • 沙盒根目录:NSString *home = NSHomeDirectory ();
  • Documents :(2 种方式)
  • 利用沙盒根目录拼接”Documents” 字符串

NSString *home = NSHomeDirectory ();

NSString *documents = [home stringByAppendingPathComponent :@" Documents "];

// 不建议采用,因为新版本的操作系统可能会修改目录名

  • 利用NSSearchPathForDirectoriesInDomains 函数

// NSUserDomainMask 代表从用户文件夹下找

// YES 代表展开路径中的波浪字符 “~”

NSArray *array =  NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, NO);

// 在 iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素

NSString *documents = [array objectAtIndex:0];

tmp :NSString *tmp = NSTemporaryDirectory ();

Library/Caches :( 跟Documents 类似的2 种方法)

利用沙盒根目录拼接 ”Caches”字符串

利用NSSearchPathForDirectoriesInDomains 函数( 将函数的第2 个参数改为:NSCachesDirectory 即可)

Library/Preference :通过NSUserDefaults 类存取该目录下的设置信息

属性列表

属性列表是一种 XML格式的文件,拓展名为 plist

如果对象是NSString 、NSDictionary 、NSArray 、NSData 、NSNumber 等类型,就可以使用writeToFile:atomically: 方法直接将对象写到属性列表文件中

属性列表 - 归档 NSDictionary

  • 将一个 NSDictionary对象归档到一个 plist属性列表中

// 将数据封装成字典

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

[dict setObject:@" 母鸡" forKey:@"name"];

[dict setObject:@"15013141314" forKey:@"phone"];

[dict setObject:@"27" forKey:@"age"];

// 将字典持久化到Documents/stu.plist 文件中

[dict writeToFile:path atomically:YES];

属性列表 - 恢复 NSDictionary

  • 读取属性列表,恢复 NSDictionary对象

// 读取Documents/stu.plist 的内容,实例化NSDictionary

NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];

NSLog(@"name:%@", [dict objectForKey:@"name"]);

NSLog(@"phone:%@", [dict objectForKey:@"phone"]);

NSLog(@"age:%@", [dict objectForKey:@"age"]);

偏好设置

  • 很多 iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置, iOS提供了一套标准的解决方案来为应用加入偏好设置功能
  • 每个应用都有个 NSUserDefaults实例,通过它来存取偏好设置
  • 比如,保存用户名、字体大小、是否自动登录

NSUserDefaults*defaults = [NSUserDefaults standardUserDefaults ];

[defaults setObject :@“yu3” forKey:@"username"];

[defaults setFloat :18.0f forKey:@"text_size"];

[defaults setBool :YES forKey:@"auto_login"];

  • 读取上次保存的设置

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSString *username = [defaults stringForKey :@"username"];

float textSize = [defaults floatForKey :@"text_size"];

BOOL autoLogin = [defaults boolForKey :@"auto_login"];

  • 注意: UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了 set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用 synchornize方法强制写入

[defaults synchornize];

NSKeyedArchiver

  • 如果对象是NSString 、NSDictionary 、NSArray 、NSData 、NSNumber 等类型,可以直接用NSKeyedArchiver 进行归档和恢复
  • 不是所有的对象都可以直接用这种方法进行归档,只有遵守了 NSCoding协议的对象才可以
  • NSCoding协议有 2个方法:
  • encodeWithCoder :

每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用 encodeObject:forKey:方法归档实例变量

  • initWithCoder :

每次从文件中恢复 (解码 )对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用 decodeObject:forKey方法解码实例变量

  • 归档一个NSArray 对象到Documents/array.archive

NSArray *array = [NSArray arrayWithObjects:@”a”,@”b”,nil];

[ NSKeyedArchiver archiveRootObject :array toFile :path];

  • 恢复( 解码)NSArray 对象

NSArray *array = [ NSKeyedUnarchiver unarchiveObjectWithFile :path];

对象的归档解档

@interface Person : NSObject< NSCoding >

@property (nonatomic, copy) NSString *name;

@property (nonatomic, assign) int age;

@property (nonatomic, assign) float height;

@end

@implementation Person

- (void)encodeWithCoder:(NSCoder *)encoder {

[encoder encodeObject :self.name forKey:@"name"];

[encoder encodeInt :self.age forKey:@"age"];

[encoder encodeFloat :self.height forKey:@"height"];

}

- (id)initWithCoder:(NSCoder *)decoder {

self.name = [decoder decodeObjectForKey :@"name"];

self.age = [decoder decodeIntForKey :@"age"];

self.height = [decoder decodeFloatForKey :@"height"];

return self;

}

- (void)dealloc {

[super dealloc];

[_name release];

}

@end

  • 归档 (编码 )

Person *person = [[[Person alloc] init] autorelease];

person.name = @“yu3”;

person.age = 22;

person.height = 1.75f;

[NSKeyedArchiver archiveRootObject:person toFile:path];

  • 恢复 (解码 )

Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

  • 如果父类也遵守了 NSCoding协议,请注意:
  • 应该在encodeWithCoder: 方法中加上一句

[super encodeWithCode:encode];

确保继承的实例变量也能被编码,即也能被归档

  • 应该在initWithCoder: 方法中加上一句

self = [super initWithCoder:decoder];

确保继承的实例变量也能被解码,即也能被恢复

NSData

使用 archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用 NSData来进行归档对象

NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用 [NSMutableData data]创建可变数据空间

NSData- 归档 2 Person 对象到同一文件中

  • 归档(编码)

// 新建一块可变数据区

NSMutableData*data = [ NSMutableData data];

// 将数据区连接到一个NSKeyedArchiver 对象

NSKeyedArchiver*archiver = [[[ NSKeyedArchiver alloc] initForWritingWithMutableData :data] autorelease];

// 开始存档对象,存档的数据都会存储到 NSMutableData中

[archiver encodeObject :person1 forKey:@"person1"];

[archiver encodeObject :person2 forKey:@"person2"];

// 存档完毕 (一定要调用这个方法 )

[archiver finishEncoding ];

// 将存档的数据写入文件

[data writeToFile :path atomically:YES];

  • 恢复(解码)

// 从文件中读取数据

NSData *data = [NSData dataWithContentsOfFile :path];

// 根据数据,解析成一个NSKeyedUnarchiver 对象

NSKeyedUnarchiver*unarchiver = [[ NSKeyedUnarchiver alloc] initForReadingWithData :data];

Person *person1 = [unarchiver decodeObjectForKey :@"person1"];

Person *person2 = [unarchiver decodeObjectForKey :@"person2"];

// 恢复完毕

[unarchiver finishDecoding ];

利用归档实现深复制

  • 比如对一个 Person对象进行深复制

// 临时存储person1 的数据

NSData *data = [ NSKeyedArchiver archivedDataWithRootObject :person1];

// 解析data ,生成一个新的Person 对象

Student *person2 = [ NSKeyedUnarchiver unarchiveObjectWithData :data];

// 分别打印内存地址

NSLog(@"person1:0x%x", person1); // person1:0x7177a60

NSLog(@"person2:0x%x", person2); // person2:0x7177cf0

2015/11/5

Day 33

今天做了一个多控制器跳转的小项目

storyboard 设计如下

一个java程序员自学IOS开发之路(七)

页面的搭建和之间的跳转都是比较简单的,主要练习了一下利用偏好设置来实现记住密码以及自动登录功能  

首先在监听登录按钮点击方法下加入

// 利用preferences 存储数据

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject:self.userNameText.text forKey:@"username"];

[defaults setObject:self.pwdText.text forKey:@"pwd"];

[defaults setBool:self.rememberPwdSwich.isOn forKey:@"rememberPwd"];

[defaults setBool:self.autoLoginSwich.isOn forKey:@"autoLogin"];

[defaults synchronize];

这样就将数据存到偏好设置中了

然后在主控制器的 viewDidLoad方法中加入

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

self.rememberPwdSwich.on = [defaults boolForKey:@"rememberPwd"];

self.autoLoginSwich.on = [defaults boolForKey:@"autoLogin"];

if (self.rememberPwdSwich.isOn) {

self.userNameText.text = [defaults stringForKey:@"username"];

self.pwdText.text = [defaults stringForKey:@"pwd"];

}

if (self.autoLoginSwich.isOn) {

[self loginBtnClick];

}

正文到此结束
Loading...