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

 

2015/10/10

Day 14

装箱和拆箱

数组和字典中只能存储对象类型,其他基本类型和结构体是没有办法放到数组和字典中的,当然你也是无法给它们发送消息的(也就是说有些NSObject的方法是无法调用的),这个时候通常会用到装箱(boxing)和拆箱(unboxing)。其实各种高级语言基本上都有装箱和拆箱的过程,就像Java中有基本数据类型包装类

在ObjC中我们一般将基本数据类型装箱成NSNumber类型(当然它也是NSObject的子类,但是NSNumber不能对结构体装箱),调用其对应的方法进行转换:

+(NSNumber *)numberWithChar:(char)value;

+(NSNumber *)numberWithInt:(int)value;

+(NSNumber *)numberWithFloat:(float)value;

+(NSNumber *)numberWithDouble:(double)value;

+(NSNumber *)numberWithBool:(BOOL)value;

+(NSNumber *)numberWithInteger:(NSInteger)value;

拆箱的过程就更加简单了,可以调用如下方法:

-(char)charValue;

-(int)intValue;

-(float)floatValue;

-(double)doubleValue;

-(BOOL)boolValue;

//包装类NSNumber,可以包装基本类型但是无法包装结构体类型

NSNumber *number1=[NSNumber numberWithChar:‘a‘];//‘a‘是一个C语言的char类型我们无法放倒NSArray中,但是我们可以通过NSNumber包装

NSArray *array1=[NSArray arrayWithObject:number1];

NSLog(@"%@",array1);

/*结果:

(

97

)

*/

NSNumber *number2= [array1 lastObject];

NSLog(@"%@",number2);//返回的不是基本类型,结果:97

char char1=[number2 charValue];//number转化为char

NSLog(@"%c",char1); //结果:a

上面我们看到了基本数据类型的装箱和拆箱过程,那么结构体呢?这个时候我们需要引入另外一个类型NSValue,其实上面的NSNumber就是NSValue的子类,它包装了一些基本数据类型的常用装箱、拆箱方法,当要对结构体进行装箱、拆箱操作我们需要使用NSValue,NSValue可以对任何数据类型进行装箱、拆箱操作。

事实上对于常用的结构体Foundation已经为我们提供好了具体的装箱方法:

+(NSValue *)valueWithPoint:(NSPoint)point;

+(NSValue *)valueWithSize:(NSSize)size;

+(NSValue *)valueWithRect:(NSRect)rect;

对应的拆箱方法:

-(NSPoint)pointValue;

-(NSSize)sizeValue;

-(NSRect)rectValue;

//NSNumber是NSValue的子类,而NSValue可以包装任何类型,包括结构体

CGPoint point1=CGPointMake(10, 20);

NSValue *value1=[NSValue valueWithPoint:point1];//对于系统自带类型一般都有直接的方法进行包装

NSArray *array1=[NSArray arrayWithObject:value1];//放倒数组中

NSLog(@"%@",array1);

/*结果:

(

"NSPoint: {10, 20}"

)

*/

NSValue *value2=[array1 lastObject];

CGPoint point2=[value2 pointValue];//同样对于系统自带的结构体有对应的取值方法(例如本例pointValue)

NSLog(@"x=%f,y=%f",point2.x,point2.y);//结果:x=10.000000,y=20.000000

那么如果是我们自定义的结构体类型呢,这个时候我们需要使用NSValue如下方法进行装箱:

+(NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;

调用下面的方法进行拆箱:

-(void)getValue:(void *)value;

typedef struct {

int year;

int month;

int day;

} Date;

//如果我们自己定义的结构体包装

Date date={2014,2,28};

char *[email protected](Date);

NSValue *value3=[NSValue value:&date withObjCType:type];//第一参数传递结构体地址,第二个参数传递类型字符串

NSArray *array2=[NSArray arrayWithObject:value3];

NSLog(@"%@",array2);

/*结果:

(

"<de070000 02000000 1c000000>"

)

*/

Date date2;

[value3 getValue:&date2];//取出对应的结构体,注意没有返回值

//[value3 objCType]//取出包装内容的类型

NSLog(@"%i,%i,%i",date2.year,date2.month,date2.day); //结果:2014,2,28

NSNull

通过前面的介绍大家都知道无论在数组还是在字典中都必须以nil结尾,否则数组或字典无法判断是否这个数组或字典已经结束(与C语言中的字符串比较类似,C语言中定义字符串后面必须加一个”\0”)。但是我们有时候确实想在数据或字典中存储nil值而不是作为结束标记怎么办呢?这个时候需要使用NSNull,这个类是一个单例,只有一个null方法。

NSNull *nl=[NSNull null];//注意这是一个对象,是一个单例,只有一个方法null创建一个对象

NSNull *nl2=[NSNull null];

NSLog(@"%i",nl==nl2);//由于是单例所以地址相等,结果:1

NSArray *array1=[NSArray arrayWithObjects:@"abc",nl,@123, nil];

NSLog(@"%@",array1);

/*结果:

(

abc,

"<null>",

123

)

*/

@符号

我们知道在ObjC中很多关键字前都必须加上@符号,例如@protocol、@property等,当然ObjC中的字符串必须使用@符号,还有就是%@可以表示输出一个对象。其实@符号在新版的ObjC中还有一个作用:装箱。

/*装箱*/

NSNumber *[email protected];

NSArray *array1=[NSArray arrayWithObjects:number1,@"abc",@16,@‘A‘,@16.7,@YES, nil];

NSLog(@"%@",array1);

/*结果:

(

100,

abc,

16,

65,

"16.7"

1

)

*/

NSNumber *[email protected](1+2*3);

NSLog(@"%@",number2); //结果:7

NSNumber *[email protected](autumn);

NSLog(@"%@",number3); //结果:2

NSArray *[email protected][@"abc",@16,@‘A‘,@16.7,@YES];//使用这种方式最后不用添加nil值了

NSLog(@"%@",array2[2]); //结果:65

NSMutableArray *array3=[NSMutableArray arrayWithArray:array2];

array3[0][email protected]"def";

NSLog(@"%@",array3[0]); //结果:def

NSDictionary *[email protected]{@"a":@123,@"b":@‘c‘,@"c":@YES};

NSLog(@"%@",dic1);

/*结果:

{

a = 123;

b = 99;

c = 1;

}

*/

NSMutableDictionary *dic2=[NSMutableDictionary dictionaryWithDictionary:dic1];

dic2[@"a"][email protected];

NSLog(@"%@",dic2[@"a"]);//结果:456

反射

//动态生成一个类

NSString *[email protected]"Person";

Class myClass=NSClassFromString(className);//根据类名生成类

Person *person2=[[myClass alloc]init]; //实例化

[email protected]“yu3”;

NSLog(@"%@",person2);//结果:name=yu3

//类转化为字符串

NSLog(@"%@,%@",NSStringFromClass(myClass),NSStringFromClass([Person class])); //结果:Person,Person

//调用方法

NSString *[email protected]"showMessage:";

SEL mySelector=NSSelectorFromString(methodName);

Person *person3=[[myClass alloc]init];

[email protected]"Rosa";

[person3 performSelector:mySelector withObject:@"Hello,world!"]; //结果:My name is Rosa,the infomation is "Hello,world!".

//方法转化为字符串

NSLog(@"%@",NSStringFromSelector(mySelector)); //结果:showMessage:

拷贝

对象拷贝操作也比较常见,在ObjC中有两种方式的拷贝:copy和mutablecopy,这两种方式都将产生一个新的对象,只是后者产生的是一个可变对象。在ObjC中如果要想实现copy或者mutablecopy操作需要实现NSCopy或者NSMutableCopy协议,拷贝操作产生的新的对象默认引用计数器是1,在非ARC模式下我们应该对这个对象进行内存管理。在熟悉这两种操作之前我们首先需要弄清两个概念:深复制(或深拷贝)和浅复制(或浅拷贝)。

  • 浅复制:在执行复制操作时,对于对象中每一层(对象中包含的对象,例如说属性是某个对象类型)复制都是指针复制(如果从引用计数器角度出发,那么每层对象的引用计数器都会加1)。
  • 深复制:在执行复制操作时,至少有一个对象的复制是对象内容复制(如果从引用计数器角度出发,那么除了对象内容复制的那个对象的引用计数器不变,其他指针复制的对象其引用计数器都会加1)。

注:

指针拷贝:拷贝的是指针本身(也就是具体对象的地址)而不是指向的对象内容本身。

对象复制:对象复制指的是复制内容是对象本身而不是对象的地址。

完全复制:上面说了深复制和浅复制,既然深复制是至少一个对象复制是对象内容复制,那么如果所有复制都是对象内容复制那么这个复制就叫完全复制。

对比copy和mutablecopy其实前面我们一直还用到一个操作是retain,它们之间的关系如下:

retain:始终采取浅复制,引用计数器会加1,返回的对象和被复制对象是同一个对象1(也就是说这个对象的引用多了一个,或者说是指向这个对象的指针多了一个);

copy:对于不可变对象copy采用的是浅复制,引用计数器加1(其实这是编译器进行了优化,既然原来的对象不可变,复制之后的对象也不可变那么就没有必要再重新创建一个对象了);对于可变对象copy采用的是深复制,引用计数器不变(原来的对象是可变,现在要产生一个不可变的当然得重新产生一个对象);

mutablecopy:无论是可变对象还是不可变对象采取的都是深复制,引用计数器不变(如果从一个不可变对象产生一个可变对象自然不用说两个对象绝对不一样肯定是深复制;如果从一个可变对象产生出另一个可变对象,那么当其中一个对象改变自然不希望另一个对象改变,当然也是深复制)。

注:

可变对象:当值发生了改变,那么地址也随之发生改变;

不可变对象:当值发生了改变,内容首地址不发生变化;

引用计数器:用于计算一个对象有几个指针在引用(有几个指针变量指向同一个内存地址);

文件操作

//文件管理器是专门用于文件管理的类

NSFileManager *manager=[NSFileManager defaultManager];

//获得当前程序所在目录

NSString *currentPath=[manager currentDirectoryPath];

//创建目录

NSString *[email protected]"/Users/yu3/Desktop/myDocument";

BOOL result= [manager createDirectoryAtPath:myPath withIntermediateDirectories:YES attributes:nil error:nil];

if(result==NO){

NSLog(@"Couldn‘t create directory!");

}

//目录重命名,如果需要删除目录只要调用removeItemAtPath:<#(NSString *)#> error:<#(NSError **)#>

NSError *error;

NSString *[email protected]"/Users/yu3/Desktop/myNewDocument";

if([manager moveItemAtPath:myPath toPath:newPath error:&error]==NO){

NSLog(@"Rename directory failed!Error infomation is:%@",error);

}

//改变当前目录

if([manager changeCurrentDirectoryPath:newPath]==NO){

NSLog(@"Change current directory failed!");

}

NSLog(@"current path is :%@",[manager currentDirectoryPath]);

//结果:current path is :/Users/yu3/Desktop/myNewDocument

//遍历整个目录

NSString *path;

NSDirectoryEnumerator *directoryEnumerator= [manager enumeratorAtPath:newPath];

while (path=[directoryEnumerator nextObject]) {

NSLog(@"%@",path);

}

/*结果:

documents

est.txt

*/

//或者这样遍历

NSArray *paths= [manager contentsOfDirectoryAtPath:newPath error:nil];

NSObject *p;

for (p in paths) {

NSLog(@"%@",p);

}

/*结果:

documents

est.txt

*/

//判断文件是否存在,这个方法也可以判断目录是否存在,这要后面的参数设置位YES

if ([manager fileExistsAtPath:filePath isDirectory:NO]) {

NSLog(@"File exists!");

}

//文件是否可读

if([manager isReadableFileAtPath:filePath]){

NSLog(@"File is readable!");

}

//判断两个文件内容是否相等

if ([manager contentsEqualAtPath:filePath andPath:filePath2]) {

NSLog(@"file1 equals file2");

}

//文件重命名,方法类似于目录重命名

if (![manager moveItemAtPath:filePath toPath:newPath error:nil]) {

NSLog(@"Rename file1 failed!");

}

//文件拷贝

NSString *[email protected]"/Users/kenshincui/Desktop/test3.txt";

if(![manager copyItemAtPath:newPath toPath:filePath3 error:nil]){

NSLog(@"Copy failed!");

}

//读取文件属性

NSDictionary *attributes;

if ((attributes=[manager attributesOfItemAtPath:newPath error:nil])==nil) {

NSLog(@"Read attributes failed!");

}

for (NSObject *key in attributes) {

NSLog(@"%@=%@",key,attributes[key]);

}

//删除文件

[manager removeItemAtPath:newPath error:nil];

//文件操作--文件内容操作(NSData,非结构化字节流对象,有缓冲区管理机制,可用于网络传输)

NSData *data=[manager contentsAtPath:filePath];

NSLog(@"%@",data);//存储的是二进制字节流

//NSData转化成字符串

NSString *str1=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"%@",str1);

//字符串转化成NSData

NSString *[email protected]“yu3”;

NSData *data2=[str2 dataUsingEncoding:NSUTF8StringEncoding];

NSLog(@"%@",data2);

//当然一般如果仅仅是简单读取文件内容,直接用户NSString方法即可

NSString *content=[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

NSLog(@"%@",content);

//文件操作--细粒度控制文件,文件操作柄

//以只读方式打开文件

NSFileHandle *fileHandle=[NSFileHandle fileHandleForReadingAtPath:filePath];//注意这个方法返回类型为instancetype,也就是说对于上面的NSFileHandle它的返回类型也是NSFileHandle

NSData *data= [fileHandle readDataToEndOfFile];//完整读取文件

NSString *[email protected]"/Users/yu3/Desktop/test4.txt";

[manager createFileAtPath:newPath contents:nil attributes:nil];

NSFileHandle *fileHandle2=[NSFileHandle fileHandleForWritingAtPath:newPath];//以可写方式打开文件

[fileHandle2 writeData:data];//写入文件内容

[fileHandle2 closeFile];//关闭文件

//定位到指定位置,默认在文件开头

[fileHandle seekToFileOffset:12];

NSData *data2= [fileHandle readDataToEndOfFile];

NSLog(@"data2=%@",[[NSString alloc]initWithData:data2 encoding:NSUTF8StringEncoding]);

[fileHandle seekToFileOffset:6];

NSData *data3=[fileHandle readDataOfLength:5];

NSLog(@"data3=%@",[[NSString alloc]initWithData:data3 encoding:NSUTF8StringEncoding]);

[fileHandle closeFile];

//文件操作--NSURL

NSURL *url=[NSURL URLWithString:@"http://developer.apple.com"];

NSString *str1=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

NSLog(@"%@",str1);

//文件操作--NSBundle,程序包,一般用于获取Resource中的资源(当然由于当前并非IOS应用没有程序包,只是表示当前程序运行路径)

//ios中经常用于读取应用程序中的资源文件,如图片、声音、视频等

//利用NSBundle在程序包所在目录查找对应的文件

NSBundle *bundle=[NSBundle mainBundle];//主要操作程序包所在目录

//如果有test.txt则返回路径,否则返回nil

NSString *path=[bundle pathForResource:@"test" ofType:@"txt"];//也可以写成:[bundle pathForResource:@"instructions.txt" ofType:nil];

NSLog(@"%@",path);

//结果:/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug/test.txt

NSLog(@"%@",[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]);

//结果:Hello,world!

//假设我们在程序运行创建一个Resources目录,并且其中新建pic.jpg,那么用下面的方法获得这个文件完整路径

NSString *path1= [bundle pathForResource:@"pic" ofType:@"jpg" inDirectory:@"Resources"];

NSLog(@"%@",path1);

//结果:/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug/Resources/pic.jpg

归档

归档,在其他语言中又叫“序列化”,就是将对象保存到硬盘;解档,在其他语言又叫“反序列化”就是将硬盘文件还原成对象。其实归档就是数据存储的过程,在IOS中数据的存储有五种方式:

  1. xml属性列表(plist归档)
  2. NSUserDefaults(偏好设置)
  3. NSKeyedArchiver归档(加密形式)
  4. SQLite3(嵌入式数据库)
  5. Core Data(面向对象方式的嵌入式数据库)

首先我们先来看一下xml属性列表,xml属性列表进行归档的方式是将对象存储在一个plist文件中,这个操作起来比较简单,其实相当于xml序列化。但是同时它也有缺点:一是这种方式是明文保存的;二是这种方式操作的对象有限,只有NSArray、NSMutableArray、NSDictionary、NSMutableDictionary支持(归档时只要调用对应的writeToFile方法即可,解档调用arrayWithContentsOfFile或dictionaryWithContentsOfFile,注意像NSString、NSNumber、NSData即使有这个方法它存储的也不是xml格式)。

系统对象的简单归档

//NSString归档

NSString *[email protected]"Hello,world!";

NSString *[email protected]"/Users/kenshincui/Desktop/archiver1.arc";

if(![NSArchiver archiveRootObject:str1 toFile:path1]){

NSLog(@"archiver failed!");

}

//NSString解档

NSString *str2= [NSUnarchiver unarchiveObjectWithFile:path1];

NSLog(@"str2=%@",str2);//结果:str2=Hello,world!

//NSArray归档

NSString *[email protected]"/Users/kenshincui/Desktop/archiver2.arc";

NSArray *[email protected][@"Kenshin",@"Kaoru",@"Rosa"];

if(![NSArchiver archiveRootObject:array1 toFile:path2]){

NSLog(@"archiver failed!");

}

//NSArray解档

NSArray *array2=[NSUnarchiver unarchiveObjectWithFile:path2];

[array2 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

NSLog(@"array2[%lu]=%@",idx,obj);

}];

/*结果:

array2[0]=Kenshin

array2[1]=Kaoru

array2[2]=Rosa

*/

系统复杂对象归档(多对象归档)

/*归档*/

NSString *[email protected]"/Users/kenshincui/Desktop/archiver3.arc";

int int1=89;

CGSize size1={12.5,16.8};

NSNumber *[email protected];

NSString *[email protected]"Hello,world!";

NSArray *[email protected][@"Kenshin",@"Kaoru",@"Rosa"];

NSDictionary *[email protected]{@"name":@"Kenshin",@"age":@28,@"height":@172.5};

//同时对多个对象进行归档

NSMutableData *data1=[[NSMutableData alloc]init];//定义一个NSMutableData用于临时存放数据

NSKeyedArchiver *archiver=[[NSKeyedArchiver alloc]initForWritingWithMutableData:data1];//定义归档对象

[archiver encodeInt:int1 forKey:@"int"];//对int1归档并指定一个key以便以后读取

[archiver encodeSize:size1 forKey:@"size"];

[archiver encodeObject:number1 forKey:@"number"];

[archiver encodeObject:str1 forKey:@"string"];

[archiver encodeObject:array1 forKey:@"array"];

[archiver encodeObject:dic1 forKey:@"dic"];

[archiver finishEncoding];//结束归档

[data1 writeToFile:path1 atomically:YES];//写入文件

/*解档*/

int int2;

CGSize size2;

NSNumber *number2;

NSString *str2;

NSArray *array2;

NSDictionary *dic2;

NSData *data2=[[NSData alloc]initWithContentsOfFile:path1];//读出数据到NSData

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

int2= [unarchiver decodeInt64ForKey:@"int"];

size2=[unarchiver decodeSizeForKey:@"size"];

number2=[unarchiver decodeObjectForKey:@"number"];

str2=[unarchiver decodeObjectForKey:@"string"];

array2=[unarchiver decodeObjectForKey:@"array"];

dic2=[unarchiver decodeObjectForKey:@"dic"];

[unarchiver finishDecoding];

NSLog(@"int2=%i,size=%@,number2=%@,str2=%@,array2=%@,dic2=%@",int2,NSStringFromSize(size2),number2,str2,array2,dic2);

/*结果:

int2=89,

size={12.5, 16.800000000000001},

number2=60.5,

str2=Hello,world!,

array2=(

Kenshin,

Kaoru,

Rosa

),

dic2={

age = 28;

height = "172.5";

name = Kenshin;

}

*/

接下来看一下自定义的对象如何归档,上面说了如果要对自定义对象进行归档那么这个对象必须实现NSCoding协议,在这个协议中有两个方法都必须实现:

-(void)encodeWithCoder:(NSCoder *)aCoder;通过给定的Archiver对消息接收者进行编码;

-(id)initWithCoder:(NSCoder *)aDecoder;从一个给定的Unarchiver的数据返回一个初始化对象;

这两个方法分别在归档和解档时调用。

Person.h文件

#import <Foundation/Foundation.h>

@interface Person : NSObject<NSCoding>

@property (nonatomic,copy) NSString *name;

@property (nonatomic,assign) int age;

@property (nonatomic,assign) float height;

@property (nonatomic,assign) NSDate *birthday;

@end

Person.m文件

#import "Person.h"

@implementation Person

#pragma mark 解码

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

NSLog(@"decode...");

if (self=[super init]) {

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

self.age=[aDecoder decodeInt64ForKey:@"age"];

self.height=[aDecoder decodeFloatForKey:@"heiht"];

self.birthday=[aDecoder decodeObjectForKey:@"birthday"];

}

return self;

}

#pragma mark 编码

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

NSLog(@"encode...");

[aCoder encodeObject:_name forKey:@"name"];

[aCoder encodeInt64:_age forKey:@"age" ];

[aCoder encodeFloat:_height forKey:@"height"];

[aCoder encodeObject:_birthday forKey:@"birthday"];

}

#pragma mark 重写描述

-(NSString *)description{

NSDateFormatter *formater1=[[NSDateFormatter alloc]init];

[email protected]"yyyy-MM-dd";

return [NSString stringWithFormat:@"name=%@,age=%i,height=%.2f,birthday=%@",_name,_age,_height,[formater1 stringFromDate:_birthday]];

}

@end

main.m文件

#import <Foundation/Foundation.h>

#import "Person.h"

int main(int argc,char *argv[]){

//归档

Person *person1=[[Person alloc]init];

[email protected]"Kenshin";

person1.age=28;

person1.height=1.72;

NSDateFormatter *formater1=[[NSDateFormatter alloc]init];

[email protected]"yyyy-MM-dd";

person1.birthday=[formater1 dateFromString:@"1986-08-08"];

NSString *[email protected]"/Users/kenshincui/Desktop/person1.arc";

[NSKeyedArchiver archiveRootObject:person1 toFile:path1];

//解档

Person *person2= [NSKeyedUnarchiver unarchiveObjectWithFile:path1];

NSLog(@"%@",person2);

/*结果:

name=Kenshin,age=28,height=0.00,birthday=1986-08-08

*/

return 0;

}

今天都是基础知识,有点枯燥,就像当初学Java的API一样= =

时间: 2024-10-05 05:42:03

一个java程序员自学IOS开发之路(三)的相关文章

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

根据上图,由于我是一个Java程序员,前面两个阶段还是学的比较快的,但是由于电脑配置不行,光是开启虚拟机登陆OS系统就卡的不要不要的了,在那里面写代码简直是煎熬= =,后面的UI学习又要启动ios模拟器,根本无法进行. 于是下定决心,入手一台Macbook pro,告别我用了四年的联想~今天本本到货啦,哈哈^_^,可以愉快的继续了 2015/10/14 Day 15 为了便于开发者打造各式各样的优秀app,UIKit框架提供了非常多功能强大又易用的UI控件 2015/10/16 Day 16 第

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

首先自我介绍吧,南昌大学软件工程专业2015界毕业生,从大学牲变到程序猿,由于在学校里只学了Java语言和B/S架构开发,于是乎出来实习和工作也是搞Java网页开发. 但是作为一名果粉,现阶段想转IOS开发,最近也开始自学了,写点东西记下来吧 2015/9/17 Day 1 安装虚拟机并安装Mac OS X系统(苦逼的我还在用联想Y-470) 开始看C语言基础,由于大学里学过一点,还是比较轻松的 2015/9/19 Day 2 由于Java中没有指针,开始看指针的相关知识 2015/9/20 D

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

2015/11/26 Day 41 今天开始学起触摸事件 在用户使用app过程中,会产生各种各样的事件 iOS中的事件可以分为3大类型 响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication.UIViewController.UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件 UIResponder内部提供了以下方法来处理事件 触摸事件 - (void)t

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

上个月实在是太忙了,在系统上线的前几天,业务人员还在不停的提新需求,真是醉了.上线那天晚上一直在出问题,熬到2点才搞定 2015/12/12 Day 47 今天开始学习网络编程 在移动互联网时代,移动应用,只有通过网络进行数据交互,才能保持活力!缺少了数据变化,无论多么华丽的应用,终将变成一潭死水 移动网络应用(良好的UI+良好的用户体验): 即时通讯:QQ 新闻:网易.凤凰新闻 视频:优酷.百度视频 音乐:虾米.QQ音乐 照片:Facebook.Flickr LBS(基于位置服务):高德.大众

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

2015/12/09 Day 46 今天学习多线程 多线程的优缺点 优点 充分发挥多核处理器优势,将不同线程任务分配给不同的处理器,真正进入“并行运算”状态 将耗时的任务分配到其他线程执行,由主线程负责统一更新界面会使应用程序更加流畅,用户体验更好 当硬件处理器的数量增加,程序会运行更快,而程序无需做任何调整 缺点 新建线程会消耗内存空间和CPU时间,线程太多会降低系统的运行性能 iOS的三种多线程技术 NSThread  使用NSThread对象建立一个线程非常方便 但是!要使用NSThrea

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

2015/9/28 Day 8 最近工作上比较忙,加上虚拟机里mac把Xcode起来电脑就很卡了,更别提在虚拟机的mac系统里再开iPhone虚拟机了. 另外乘着中秋国庆好好休息下~过后准备大出血入手Macbook pro PS:同事居然在公司发的月饼里吃出来虫子= =,幸好我没打算吃,因为我讨厌月饼 2015/10/1 Day 9 开始学习OC内存管理 OC中的内存是要程序员来管的,因为并没有Java中的垃圾回收机制. 及时释放内存是我们要时刻考虑的,同时还是注意野指针 堆空间的对象需要手动代

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

2015/11/8 Day 34 UITabBarController 跟UINavigationController类似,UITabBarController也可以轻松地管理多个控制器,轻松完成控制器之间的切换,典型例子就是QQ.微信等应用 UITabBarController的使用步骤 ? 初始化UITabBarController ? 设置UIWindow的rootViewController为UITabBarController ? 根据具体情况,通过addChildViewContro

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

2015/10/28 Day 27 今天学习了即时通讯应用的UI布局,只是简单的利用UITableView展示数据 第一步 先利用storyboard把页面的框架搭起来 显示的数据是存在plist文件里的,所以要把他们转成模型 typedef enum { YUMessageTypeMe = 0, // 自己 YUMessageTypeOther // 其他人 }   YUMessageType; @interface YUMessage : NSObject @property (nonato

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

最近学习的进度慢了点,因为年底之前有个新项目要上线,而且每次业务人员过来一次,需求就有变动,于是不停的改改改= =!唉~不说了心好累 2015/11/29 Day 43 事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中 UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow) 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的