Android开发对于iOS基础的对比学习

  Android开发使用的是Java语言进行编写,当然最近Google的kotlin逐渐变成Android的官方认可的语言。虽然kotlin的语法模式跟Java有些区别但对于一个多年Android开发经验的开发者来说上手比较快,Java和kotlin在Android开发中很多相关的知识点多能套用。出于对移动端开发的热爱,要了解两大移动系统的开发,iOS开发还是挺吸引人的。

  大学时的C基础基本快要到忘光的程度,现在想学习iOS开发用到类C的Objective-C。现在对Java C OC三种语言基础的对比学来更快的入门iOS开发,给自己的的技能树添枝加叶。

  一.语法基础:

      1.标识符/变量/常量:

            类型 变量 = 初始值;

        标识符与Java/C中命名方式类似,标识符可以用字母/数字/美元符$/下划线组成,标识符开头只能以字母/美元符下划线。

            类型说明符 变量 a = 值1;

         常量分为:整型常量(12345)/实例常量(1.2345)/常量('a')/字符串常量("abc")/逻辑常量(true/false)

       2.局部变量和实例变量:

         大致与Java/C中的局部变量/实例标量类似。

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

    @autoreleasepool {
        int a = 10,b,c = 8;
        b = a + c;
      }
      NSLog(@ "a = %d, b = %d, c = %d", a, b, c);
      return 0;

}

       3.基本数据类型:

           oc中基本数据类型跟Java的基本数据类型一致。特殊的类型id,id类型的数据可以储存任何类型的对象属于一般的对象类型。

           char,short int,int,long int,float,double,long double,id。

           NSNumber类似Java中Integer的数据对象,与Java中的数据类型的解封类似。

           NSString对比于Java中String:

NSString *MyString = @"abcd";   //oc
String string = "abcd";    //java

NSString *MyString1 = [[NSString alloc] intWhithString:@"abcd"];    //oc
String string1 = new String("abcd");    //java

NSString *SubString = [MySrting substringToIndex:2];    //oc
String subString = string.subString(0,2);    //java

      4.循环与选择结构:与Java,C中一样

二.数组和字典:

      在Foundation framework的框架中提供三种收集NSObject对象的集合:数组(NSArray),集合(NSSet),字典(NSDictionary);NSArray用于储存有序的对象集合,NSSet用于存储无序的对象集合,NSDictionary用于储存键值对的集合。在iOS中这三类集合类只能储存cocoa对象(NSObject对象,如要保存一些原始C数据,int)就需要将int类型转换为NSObject对象。

     1.NSArray固定数组,NSMutableArray可变数组:

NSArray *array = [[NSArray alloc]initWithObjects:@"1",@"2",@"4",nil];  
int[] array = new int[1,2,3,4];    //java 

NSMutableArray mArray = [[NSMutableArray alloc] initWithObject:@"hello",@"world"];
String[] mString = new String[]{"hello","world"};

     NSArray,NSSet,NSDictionary跟Java中的Array,Set,Map集合类型一致:

    //数组实例初始化方法
-(instancetype)initWithObjects:(id)fristObj;    //直接将数组元素添加到数组中的初始化方法
-(instancetype)initWithArray:(NSArray *)array;  //通过拷贝另一个数组的方法初始化一个数组
-(NSArray *)initWithContentsOfFile:(NSString *)path;    //使用一个文件来创建数组
-(NSArray *) initWithContentsOfURL:(NSURL *)url;    //使用一个url链接来创建数组

NSArray *array = [[NSArray alloc]initWithObjects:@"1",@"2",@"4",nil];  //oc类方法创建

    //数组类初始化方法
+(instancetype)arrayWithObject:(id)object;    //直接将数组中的元素添加到数组中的初始化方法
+(instancetype)arrayWithArray:(NSArry *)array;//通过拷贝另一个数组的方法初始化一个数组
+(NSArray *) arrayWithContentsOfFile:(NSString *)path    //使用一个文件来创建数组
+(NSArray *) arrayWithContentsOfURL:(NSURL *)url;    //使用一个url链接来创建数组

    //打印数组
NSLog(@"array:%@",array1);    
for(int i = 0;i < array.count;i++) {
    NSLog(@"第%d个元素是:%@",i  ,[array] objectAtIndex:i );
}
for(id obj in array){
    NSLog(@"%@",obj);
}

    //数组排序
NSArray *sortArray = [sortedArrayUsingComparator:^NSComparisonResult(id obj1,obj2){
    if([obj1 intValue] > [obj2 intValue]){
        return NSOrderedDescending;
    }
    if([obj1 intValue] < [obj2 intValue]){
        return NSOrderedAscending;
    }
}]

     在oc中实例方法用"-",类方法用"+"表示。类方法不需要实例化对象就可以使用,直接通过类调用,类似Java中static修饰的方法;实例方法,必须通过类创建一个实例对象才能使用。

    2.NSSet/NSMutableSet与Java中Set集合用法和定义一致,集合是一种哈希表,运用散列算法,查找集合数据比数组快,但是无序的,存储对象是唯一的不能重复。

NSSet *set = [[NSSet alloc] initWithObjects:@"name",@"age",@"sex",nil];//oc
NSSet *set1 = [NSSet setWithObjects:@"name",@"age",@"sex",nil];

Set set2 = new HsshSet();
set2.add("name");
set2.add("age");
set2.add("set");

   3.字典(NSDictionary/NSMutableDictionary)是一种以键值对(key-value)的形式进行存储的存储结构与Java中的Map类似,通过key属性名称来获取与key对应的value,value是一个对象指针,通过valueForKey访问相应的值。

NSDictionary *dic = [[NSDictionary alloc]initWithObjectsAndKeys:@"name",@"wang",@"age",@"28",nil];    //oc中的NSDictionary初始化以键值对成对出现

NSLog[@"键值对的个数:%ld",[dic count]];    //查看键值对数量

NSArray *keys = [dic allKeys];    // 查看所有键
NSLog[@"键为:%@",keys];

NSLog[@"name:%@",[dic vauleForKey:@"name"]];    //查看特定键对应的值

NSDictionary *dic1 = [[NSDictionary alloc]init];
dic1 =@{@"name",@"wang",@"age",@"28"};
NSArray *array = [NSArray arrayWithObjects:dic1];
NSLog(@"age:%@",[array vauleForKey:@"age"]);

三.循环与选择结构:

    for,while,do while,return,break,continue与Java中的用法一样。

四.面向对象方法实现:

   1.对象/类/方法:

      对象就是一个实体,能感受到具体事物。类是对对象的抽象,方法是将动作进行定义和使用。

     @interface申明接口,@implementation用于实现接口

     接口部分的申明:

@interface NewClassName : ParentClassName
{
    memberDeclarations;    
}
memberDeclarations;
@end

   类和实例方法:

     oc中有两种方法类型,开头是符号"-"代表该方法是一个实例方法,而开头是符号"+"则代表该方法是类方法。

//方法类型(返回值) 方法名称 (参数类型) 参数名
-(void) setNumber: (int) n;
-(void) intWithNumber: (int) n andAge:(int) a;

void setNumber(int n);    //java
void intWithNumber(int n,int a);

  2.继承(@Property)属性和点语法:

     @Property点语法调用方法:

     声明@Property属性之后,在.m实现文件中要使用@synthesize方法来完成这个方法。

    @Property属性中有多种参数可供选择:

        readonly:只产生简单的getter方法,没有setter方法;

        retain:setter方法对参数进行release旧值,再retain新值;

        nonatomaic:禁止多线程,保护变量;

        assign:默认类型,setter方法直接赋值,而不进行retain操作。

@interface Number1 : NSObject
{
    int Mynumber1;
    float Mynumber2;
}
@property(nonatomic) int Mynumber1;
@property(nonatomic) float Mynumber2;
- (void)print;
@end


#import "Number1.h"

@implementation Number1 
@synthesize Mynumber1,Mynumber2;
-(void)print
{
    NSLog(@"Mynumber1 is %d,Mynumber2 is %.lf",Mynumber1,Mynumber2);
}
@end

//调用
 Number1 *number = [[Number1 alloc]init];
 number.Mynumber1 = 10;
 number.Mynumber2 = 12.090;
 [number print];

   2.类的继承:

     NSObject类是所有类的父类(与Java中Object定义类似),子类能够继承父类的实例变量和方法,子类可以直接访问这些方法和实例变量,就像直接在类中定义了一样。private与Java中一样定义为私有变量及方法;@public定义的实例变量不仅可以在本类的方法使用;@Property实例变量(默认情况下)可被该类及任何子类中定义的方法直接访问。

   3.多态:

       多态的表现:有继承关系,有方法重写,父类的申明变量指向子类对象(与Java的多态一致)。

  4.动态类型:

       oc 中除了基本的数据类型之外,还有一种特殊的数据类型,那就是动态类型。id类型可以存储任何类型的对象,在声明了id类型的变量后,Number可以存储任何类型的对象,可以声明一个具体有id类型返回值的方法,用于创建实例。id类型不仅仅可以定义变量,也可以定义方法,使方法的返回值是动态的。 

id Number;
-id NewNumbers : (int)number;

    id 声明对象类型时没有使用“*”。因为id类型,其可以来保存程序中任何类型的对象。oc的系统总是跟踪对象所属的类,运行时先判定对象的所属的类,然后在运行时再确定需要动态调用的方法,而不是在编译的时候。

   5.对象的复制:

       假设一个对象中拥有一个数组对象,现在又需要生成一个对象,同时将现有的对象赋值给这个新对象,那么这两个对象中的数组对象是同一个,也就是说,当一个对象中对数组进行修改时,那么另一个对象的数组对象也会同时被修改,也就是说这两个对象中的数组对象是共享的。

       retain的概念与copy类似,retain可以快速创建对象,但retain只是使原对象的引用计数+1,并没有创建新的对象,两个对象指针相同,指向同一个对象。copy方法用于不可变数值,mutableCopy方法用于可变数组。

NSMutableArray *myArray = [NSMutableArray arrayWithObjects:@"one",@"two", nil];
        NSMutableArray *myArray1 = [myArray retain];
        if (myArray == myArray1) {
            NSLog(@"myArray == myArray1");
            NSLog(@"myArray引用计数为:%ld",myArray.retainCount);
        }
        
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"three"@"four", nil];
        NSMutableArray *array2 = [array1 copy];
        if (array1 != array2) {
            NSLog(@"array1 != array2");
            NSLog(@"array1引用计数为:%ld",array1.retainCount);
        }

       深拷贝与浅拷贝:

        深拷贝:拷贝属性对象的所有内容;

        浅拷贝:只拷贝所有属性对象的指针。

   6.iOS中的内存管理:

  • Java中为用户提供了自动内存管理的机制,但在iPhone开发中需要开发者手动管理内存。当程序运行时占有的内存都是取决于RAM的,操作系统启动应用时,会为应用保留一部分空闲的RAM,称为堆区。在创建实例时,会从堆区中取出一小块供其使用,当不需要使用对应的对象时,应该及时释放分配给它的内存。
  •  在oc中使用alloc方法为所有的Objective-C类创建实例,但是当为实例分配内存之后,还不能使用,要通过init方法将实例化对象进行初始化。init方法是一个实例方法,一个类中会包含有多个init方法,这些方法都是以init开头的。在Objective-C中局部变量时放在栈区中,而alloc的内存区域时在堆区中。

       在重写init方法时,会调用父类的初始化方法,通过“[super init]”,init方法返回的值时id类型,描述了被初始化的对象。

-(id)init 
{
    self = [super init];
    if(self) {
        //初始化代码
    }
}

      如果父类初始化失败,则会返回nil,就无法进行当前类的初始化操作。我们也可以这样理解上述代码,init方法完成对子类对象的初始化,可以将此工作分为两个部分:继承父类的对象的初始化,子类对象本身对象的初始化,所以“[super init]”其实就是父类对象的初始化,而在中括号内才是对子类自身的对象进行初始化。

      在分配内存之后如果想将内存还给堆区,可以通过dealloc方法来实现,当对象收到dealloc消息时,会将其占用的内存还给堆区。在oc中不能直接向对象发送dealloc方法,只能由对象自己向自己发送dealloc消息。

  • 引用计数:

        Cocoa Touch框架采用手动引用计数(mrc)来管理内存,对象不知道具体的拥有方,只是知道拥有方的个数,当拥有方(引用计数)为零时,就调用deallloc方法来释放内存。

        retain计数和release管理内存:

           对象通过retain计数知道拥有方的个数,当用户创建一个实例后,对象将得到一个拥有方,此时retain计数值为1;如果又有一个拥有方加入,则retain计数加1;当对象失去一个拥有方时,会收到release消息,此时的retain计数减1;当retain计数为0时,对象就会向自己发送一个dealloc消息,释放相应的内存,还有重要一点,当引用计数为0时,对象就不能使用release和其他方法,否则系统会出现内存方法的错误。

        实例变量的属性:

            (1).assign:对基础数据类型(NSInteger)和c类型数据(int/float/char)使用assign属性只是简单的赋值,不会改变引用计数;

            (2).copy:copy属性用NSString对象,它将创建一个引用计数为1的对象,然后释放原先的旧对象;

            (3).retain:用于其他NSObject和NSObject子类。当添加retain属性时,将释放旧的对象,将对象的值赋予输入对象,再提高输入对象的引用计数为1。

NSString *myString = [[NSString alloc]initWithString:@"hello"];

       以上代码执行时会完成两个操作,因为alloc了一块内存区域,所以会在堆区分配一段内存来存储字符串(例如内存地址为OX1234,内容为"hello")。同时会在栈区分配一段内存来存储字符串对象myString(例如地址OXABCD,内容为堆区地址OX1234)。

NSString *myString1 = [myString assign];

     当用assign属性时,myString和myString1完全相同,地址都是OXABCD,内容为OX1234,对这两任何一个进行操作均相当于对另一个进行操作,所以引用计数不改变。

NSString *myString2 = [myString retain];

    当使用retain属性时,myString和myString2地址不再一样,但内容一样,为OX1234。myString和myString2都是共用@"hello"所在的内容,因此引用计数要加1。

NSString *myString3 = [myString copy];

    此时会在堆区分配一段内存存储字符串@"hello",为myString3字符串对象和@''hello"重新分配地址,引用计数要加1。

  • 自动释放池

      autoreleasepool提供一种延迟释放的功能,实际上是把堆release的延迟调用,对于每一个autorelease,系统只是把该对象放入当前的autoreleasepool中,当自动释放池北释放是,pool中的所有对象会调用release。它的作用就是可以做到是每一个函数对自己申请的对象负责,即自己申请,自己释放,该函数的调用者不需要关心其内部申请对象的管理。

    要使用autorelease命令,首先要手动创建一个自动释放池:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

Person *person = [[[Person alloc]init]autorelease];//设置了autorelease,不需要对person进行release了。

    当autorelease销毁时,会遍历其内部release数组中的每一个成员,如数组中某元素的引用计数为1,那么经过[pool drain]后的值变为0,则该元素被销毁。在代码中标记autorelease的对象只有在程序结束时才会被销毁,它体现了延迟释放的特点。

你可能感兴趣的:(iOS开发基础)