黑马程序员--10 OC Foundation框架

本文详细介绍了Objective-C中的几种主要集合类,包括NSArray、NSSet、NSDictionary及其可变版本,探讨了它们的创建、使用及遍历方法。同时,文章还涉及了NSNumber、NSValue、NSDate等基础类的使用技巧。

                                                            ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


集合(有序数组NSArray,无序数组NSSet,无序字典NSDictionary 

NSMUtableArray  是 NSArray 的子类;

NSArray 

NSArrayOC的数组,以面向对象的形式操作数组.

NSArrayOC的有序数组,可以存储任何类型的OC对象,但是不能储存nilintfloatenumstruct等类型的数据

NSArray是不可变数组.数组元素在创建数组时就被确定.数组创建后不可添加/修改/删除元素.除非把指针指向个新数组

创建

创建一个空数组

NSArray *array = [NSArray array];

创建一个有一个元素的数组

array = [NSArrayarrayWithObject:@"123"];

创建一个有多个元素的数组

array = [NSArrayarrayWithObjects:@"A", @"B", nil];

使用nil来标记数组的结束.这个数组有两个元素.注意不要写两个nil.

任何OC对象都可以放到NSArray中,不需要是同一类型的对象

array = [NSArray arrayWithObjects:person, dog, book, nil];

使用编译器特性来方便快速的创建数组

NSArray *array =@[@"Jack", @"Rose", @"123"];

NSArray *array =@[person, dog, book];

注意

1 使用@开头   

2 末尾不加nil 

3上面的数组创建好之后就不可以再修改内容了,比如第一个创建的array只能是空数组,不能够往里面存放内容。


遍历数组


1 for循环
count = array.count;
for (int i = 0; i < count; i++) 
{
        id obj = [array objectAtIndex:i];

        NSLog(@"%d: %@", i, obj);
}

2快速遍历
for (id obj in array) 
{
            unsigned long i = [array indexOfObject:obj];
            NSLog(@"%lu: %@", i, obj);
}

3 使用block:
[array enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) { ... }];


这个方法对每一个元素都调用一次block,可以在block内写代码对元素进行运算。

非常方便,既有obj,又有index,而且还可以设置stop随时终止遍历.

如何在for循环中终止遍历?使用break;

如何在block遍历中终止遍历?修改stop的值.


为什么stop要使用星号, BOOL指针类型呢?

因为在函数内部需要修改这个*stop的值.也就是说,本来*stop的值是NO,如果需要停止,就需要修改*stop的值为YES.既然要修改外部参数的值,就需要使用指针才能修改.


使用举例:

使用block输出数组中前两个元素的值

[array enumerateObjectsUsingBlock:

^(id obj, NSUInteger idx, BOOL *stop) {      //遍历数组

            NSLog(@"%lu: %@", idx, obj);

            if (idx == 1) {  

*stop = YES;                 //修改*stop的值退出遍历

}

}];


// 数组的建立,数元素,打印某个元素,某个数组,数组遍历
int main()
{
    Person *p = [Person new];
    
    NSArray *array = [NSArray arrayWithObjects:@"jack",@"rose",p,nil]; // 多元素必须以nil结束
    
    NSArray *array1 = @[@"m1",@"m2",@"m3"]; // 另外一种快速建立数组的方式
    
    NSLog(@"%ld",array.count); //数数数组有多少元素
    
    NSLog(@"%@",array[1]); // 取出某个元素
    
    // 遍历数组,对象打印出来是类名+对象地址
    for (int i = 0;i<array.count;i++)
    {
        NSLog(@"%@",array[i]);
    }
    // 快速遍历1
    for (id obj in array)
    {
       int i = (int)[array indexOfObject:obj];
        NSLog(@"%d-%@",i,obj);
    }
    // 快速遍历2
    // 遍历一个元素就调用一次block,然后把元素和索引当作参数传给block
    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"%ld,,,%@",idx,obj);
        // 停止遍历
        if (idx == 1)
        {
            *stop = YES;
        }
    }];
    return 0;
}



NSMutableArray

NSMutableArrayNSArray的子类,是可变数组,可以修改存放的内容。


创建

NSMutableArray *mArray = [NSMutableArray arrayWithObject:@"1"];


修改元素

添加:
[mArray addObject:@"2"];
[mArray insertObject:@"3" atIndex:0];
 删除:
[mArray removeObject:@"2"];   
[mArray removeObject:@"2" inRange:range];
[mArray removeObjectAtIndex:1];
[mArray removeLastObject]
[mArray removeAllObjects];
[mArray removeObjectsInRange:range];
[mArray removeObjectsInArray:array];  //删除和array共有的元素
 替换:
[mArray replaceObjectAtIndex:0 withObject:@"100"];
[mArray replaceObjectsInRange:range withObjectesFromArray:array];
[mArray exchangeObjectAtIndex:1 withObjectAtIndex:3];

int main()
{
    NSMutableArray *array = [NSMutableArray arrayWithObjects:@"jack",@"milk",@"like",nil];
    
   // NSMutableArray *array1 = @[@"apple",@"juice"]; // 这样写不对,因为,只有不可变数组有这种方法,可变的只能用上边这种发方法
    
    [array addObject:@"love"];
    
    [array removeObject:@"milk"];
    
    NSLog(@"%ld",array.count);
    
    NSLog(@"%@",array);
    
    return 0;
}


NSSet

NSSetNSArray的最大区别是,NSArray的数据是有序存放的,NSSet的数据是无序存放的。
NSSet
中也只能存放OC对象类型,不能存放基本类型的数据,不能存放nil,仅仅使用nil作为元素结束的标记

创建

NSSet *set = [NSSet set];  //空的set
set = [NSSet setWithObject:@"Jack"];  //有一个元素的set
set = [NSSet setWithObjects:@"Jack", @"Rose", nil];  //有多个元素的set
set = [NSSet setWithSet:set2];  //一个和另一个set一样的set
set = [NSSet setWithArray:myArray];  //使用一个数组中的元素来创建set


常用方法

unsigned long n = set.count;  //获得元素的个数

id anyObj = [set anyObject];  // 随机获取某个元素



NSMutableSet


添加数据

[set addObject:@"Jim"];

移除数据

[set removeObject:@"Jim"];

[set removeAllObjects]




NSDictionary

 创建

      1空字典   NSDictionary *dict = [NSDictionary dictionary]; 

      2有一组数据的字典  dict = [NSDictionary dictionaryWithObject:@"apple(obj)"forKey:@"red(key)"]; 

      3有多组数据的字典:

方法一:

NSArray *objectArray = @[@"apple", @"banana", @"orange"];

NSArray *keyArray = @[@"red", @"yellow", @"orange"];

dict = [NSDictionary dictionaryWithObjects: objectArray forKeys:keyArray];

第一个参数是objects数组,第二个是keys数组,二者的内容一一对应。


方法二:

dict = [NSDictionary dictionaryWithObjectsAndKeys:

@"obj1apple", @"k1red",

@"obj2banana", @"k2yellow",

@"obj3orange", @"k3orange", nil];

对每一组数据,先写value再写key,要以nil结束。


使用编译器特性快速创建:


dict = @{@"name":@"jack", @"address":@"beijing"};

格式: @{ key1 : obj1, key2 : obj2, ...};末尾不用添加nil

注意:这样创建的字典是不可变字典



字典的遍历


1经典遍历

因为字典不能通过index取出key或者value,可以提前把allKeys取出来放在一个数组中,再进行遍历:

NSArray *keys = [dict allKeys];

for (int i = 0; i < dict.count; i++) 

{

            NSLog(@"%@ = %@", keys[i], dict[key[i]]);

}


2快速遍历

for (id key in dict) 

{

            id obj = [dict objectForKey:key];

            NSLog(@"%@ = %@", key, obj);

}

遍历的是字典的所有keys,因为每个key都是不同的,根据key可以找到对应的object。但是object可能是相同的,不能根据object找到唯一对应的key


3 Block遍历

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){

           NSLog(@"%@ = %@", key obj);

}

];

对每组键值对调用一次block


NSMutableDictionary

NSMutableDictionaryNSDictionary的子类,它创建的字典可以添加/修改数据。

添加元素

[dict setObject:stu forKey:@"stu"];

如果字典中已经有这个key了,就会把它的值修改为stu。如果字典中没有这个key,就会添加这组数据。

[dict addEntriesFromDictionary:dict2];

把另一个字典中的所有内容添加到这个字典中。


删除元素

[dict removeAllObjects];  //删除所有数据

[dict removeObjectForKey:@"red"];  //删除这个key对应的这组数据。如果字典中没有这个key,不会报错

[dict removeObjectsForKeys:keysArray];  //删除数组中所有keys对应的数据

 

/*
 集合
 1.NSArray\NSMutableArray
 * 有序
 * 快速创建(不可变):@[obj1, obj2, obj3]
 * 快速访问元素:数组名[i]
 
 2.NSSet\NSMutableSet
 * 无序
 
 3.NSDictionary\NSMutableDictionary
 * 无序
 * 快速创建(不可变):@{key1 : value1,  key2 : value2}
 * 快速访问元素:字典名[key]
 */

#import <Foundation/Foundation.h>

int main()
{
    NSArray *persons = @[
    @{@"name" : @"jack", @"qq" : @"432423423", @"books": @[@"5分钟突破iOS编程", @"5分钟突破android编程"]},
    @{@"name" : @"rose", @"qq" : @"767567"},
    @{@"name" : @"jim", @"qq" : @"423423"},
    @{@"name" : @"jake", @"qq" : @"123123213"}
    ];
    
    // 
    // NSDictionary *jim = persons[2];
    
    
    // 
    NSString *bookName = persons[0][@"books"][1];
    NSLog(@"%@", bookName);
    //NSArray *array = persons[0][@"books"];
    
    //NSLog(@"%@", array);
    
    // 先取出1位置对应的字典
    // 再取出字典中qq这个key对应的数据
    //NSLog(@"%@", persons[1][@"qq"]);
    
    // NSLog(@"%@", jim);
    return 0;
}

void use4()
{
    // 字典不允许有相同的key,但允许有相同的value(Object)
    // 字典的无序的
    NSDictionary *dict = @{
    @"address" : @"北京",
    @"name" : @"jack",
    @"name2" : @"jack",
    @"name3" : @"jack",
    @"qq" : @"7657567765"};
    
    //    NSArray *keys = [dict allKeys];
    //
    //    for (int i = 0; i<dict.count; i++)
    //    {
    //        NSString *key = keys[i];
    //        NSString *object = dict[key];
    //
    //
    //        NSLog(@"%@ = %@", key, object);
    //    }
    
    
    [dict enumerateKeysAndObjectsUsingBlock:
     ^(id key, id obj, BOOL *stop) {
         NSLog(@"%@ - %@", key, obj);
         
         // *stop = YES;
     }];
}

void use3()
{
    NSMutableDictionary *dict = @{@"name" : @"jack"};
    
    
    [dict setObject:@"rose" forKey:@"name"];
}

void use2()
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    
    // 添加键值对
    [dict setObject:@"jack" forKey:@"name"];
    
    
    [dict setObject:@"北京" forKey:@"address"];
    
    [dict setObject:@"rose" forKey:@"name"];
    
    
    // 移除键值对
    // [dict removeObjectForKey:<#(id)#>];
    
    
    NSString *str = dict[@"name"];
    
    
    //NSLog(@"%@", str);
    
    NSLog(@"%@", dict);
    
    
    //NSLog(@"%@", @[@"jack", @"rose"]);
}

void use()
{
    /*
     字典:
     
     key ----> value
     索引 ----> 文字内容
     
     里面存储的东西都是键值对
     
     
     */
    
    // NSDictionary *dict = [NSDictionary dictionaryWithObject:@"jack" forKey:@"name"];
    
    
    // NSArray *keys = @[@"name", @"address"];
    // NSArray *objects = @[@"jack", @"北京"];
    
    // NSDictionary *dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
    
    
    /*
     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
     @"jack", @"name",
     @"北京", @"address",
     @"32423434", @"qq", nil];*/
    
    
    NSDictionary *dict = @{@"name" : @"jack", @"address" : @"北京"};
    
    // id obj = [dict objectForKey:@"name"];
    
    id obj = dict[@"name"];
    
    NSLog(@"%@", obj);
    
    
    
    // 返回的是键值对的个数
    NSLog(@"%ld", dict.count);
}


int main()
{
   NSArray *array = @[
      @{@"name":@"jack",@"book":@[@"5fenzhong",@"6fenzhong"]}, // 数组里边包含字典,字典里再来个数组
      @{@"name":@"milk"},
      @{@"name":@"sike"}
      ];
    NSLog(@"%@",array[0][@"book"][1]);
}



类(NSNumber  NSValue  NSDate


NSNumber 


 把基本数据类型包装成NSNumber对象

      各种基本数据类型的数据都可以包装成NSNumber对象

[NSNumber numberWithBool];

[NSNumber numberWithChar];

[NSNumber numberWithInt];

[NSNumber numberWithLong];

[NSNumber numberWithFloat];

[NSNumber numberWithDouble];




使用编译器特性快速包装基本数据类型

编译器特性:可以使用 @快速把基本数据类型转换成NSNumber类型

比如:

@20    -  int类型转换成NSNumber类型的对象

@10.5  -  double类型转换成NSNumber类型的对象

@YES   -  BOOL类型转换成NSNumber类型的对象

@'A'   -  char类型转换成NSNumber类型的对象

@"A"   -  注意区分,这个是NSString类型的对象


如果使用变量,要使用小括号把变量名括起来(否则会被误当成关键字)

比如:

int age = 20;

NSNumber *n = @(age);


 


NSNumber对象还原成基本数据类型


可以把NSNumber对象转换成各种的基本数据类型

[num boolValue];

[num charValue];

[num intValue];

[num shortValue];

[num longValue];

[num unsignedIntValue];

[num unsignedLongValue];

[num floatValue];

[num doubleValue];


字符串转换成基本数据类型


字符串其实也有类似的方法:

NSString *str = [NSString stringWithFormat:@"%d", 10];

int a = [str intValue];

NSString *str2 = @"3.5";

double d = [str2 doubleValue];


NSValue 

NSValue能够把各种类型的数据包装为对象,NSNumber其实是它的子类。


系统自带结构体包装成NSValue类型的对象

如果我们想把结构体放到集合中,就需要把结构体包装成OC对象:

[NSValue valueWithPoint: ];

[NSValue valueWithRect: ];

[NSValue valueWithSize: ];

[NSValue valueWithRange: ];


NSValue对象还原成结构体

[value pointValue];

[value rectValue];

[value sizeValue];

[value rangeValue];


任何类型包装成NSValue类型的对象

举例:

typedef struct {int year, month, day;} Date;

Date date = {2014, 3, 5};  //要包装的数据

char *type = @encode(Date);  //把数据的类型转换为字符串

NSValue *myDate = [NSValue value:&date withObjCType:type];  //包装成NSValue对象

它的第一个参数的类型是void *,表示可以接受任何指针类型,id == void *

 

如何解包

Date date1;  // 存储数据的变量

[myDate getValue:&date1];  //取出包装的结构体,并赋值给date1


 

NSDate 

NSDate是用来表示日期和时间的类。

 创建

 当前时间:

NSDate *date = [NSDate date];  // date是执行这行代码时的时间

NSLog(@"%@", date);   //打印date时默认打印格林尼治时区的时间


以当前时间为基准,n秒后的时间:

date = [NSDate dateWithTimeIntervalSinceNow:10];

比现在的时间快10秒的时间(未来的时间)


 1970年初零点为基准,n秒后的时间:

date = [NSDate dateWithTimeIntervalSince1970:1000];


以最近年初零点为基准,n秒后的时间:

date = [NSDate dateWithTimeIntervalSinceReferenceDate:1000];


 以某个时间为基准,n秒后的时间:

NSDate *date2 = [NSDate dateWithTimeInterval:10 sinceDate:date]

表示比date这个时间晚10秒钟的那个时间(未来的时间)


遥远未来的某一天:

date= [NSDate distantFuture];

调试时貌似总是固定的一天,但是运行时也有可能是随机的一天。


遥远过去的某一天:

date2= [NSDate distantPast];


 


日期格式的字符串


在手机上显示日期需要转换成字符串,可以按照指定的格式转换

需要一个日期格式类:

NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];


设置格式

formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

大写M代表月,小写m代表分钟

大写H代表24小时制时间,小写h代表12小时制时间


根据格式把日期转换成字符串:

NSString *str = [formatter stringFromDate:date];  //date转换成字符串

 

根据格式把字符串转换成日期:

NSDate *date = [formatter dateFromString:str];  //把符合格式的字符串转换成日期


如果字符串的日期格式不同,就设置一个相应的dateFormat

NSString *s = @"2011/09/10 18:56";  //某种格式的日期和时间

formatter.dateFormat = @"yyyy/MM/dd HH:mm";  //设置对应的格式

NSDate *date = [formatter dateFromString:s];  //就可以转换成NSDate对象了

NSLog(@"%@", date);  //查看返回的日期


 结构体 

 NSRange

1.概况

NSRange用来表示AB中所占的范围。

它有两个成员, location length,它们的类型都是NSUInteger (unsigned long)

比如:字符串@"Hello world!", "world"这几个字符的范围: location = 6, range = 5


2.创建NSRange类型的变量

NSRange r;   r.location = 2;   r.length = 3;  //定义变量后分别给成员赋值

NSRange r1 = {2, 3};               //初始化,前面是location,后面是length

NSRange r2 = {.location = 2, .length = 3};  //初始化,顺序无所谓

NSRange range = NSMakeRange(2, 3);     //使用函数创建)最常用的方式,前面是location,后面是length

注意:NSRange是使用了typedef结构体类型,不是类,所以定义变量时不用加星号。


3.查看子字符串在主字符串中的位置

举例:

NSString *str = @"hello world!";

NSRange range = [str rangeOfString:@"world"];

NSLog(@"Range: %@", NSStringFromRange(range));


4.快速方便的打印属性值

使用点属性打印属性值很不方便,尤其是当属性很多时

NSLog(@"location: %zi", range.location);

NSLog(@"length: %zi", range.length);

可以转为字符串再打印,可以方便的查看所有属性的值:

NSString *str_range = NSStringFromRange(range);

NSLog(@"%@", str_range);       //打印结果为 {8, 10}



CGPointCGSizeCGRect

前述

CGPoint, CGSize, CGRect NSPoint, NSSize, NSRect是完全等价的.

CG代表CoreGraphics. NS代表NextStep.

通常使用CGXxxx,因为它跨平台 (iOSMac平台).使用它的类和方法时需要链接CoreGraphics框架. Foundation里有它们的声明,但是函数的实现是在CoreGraphics框架里.


1简介

CGPoint代表图像中一个元素的位置,它有两个成员 x y,类型都是 CGFloat (double)

CGSize代表一个元素的尺寸,它有两个成员 width height,类型都是 CGFloat

CGRect代表一个矩形,它有两个成员 CGPoint origin  CGSize size,前者代表矩形左上角的坐标位置,后者表示矩形的宽和高。


2创建变量

1>使用创建一般结构体的方式创建:

CGPoint p = {10, 20};    CGPoint p2;   p2.x = 10;   p2.y = 20;

CGSize  s = {30, 50};     CGSize s2;   s2.width = 30;   s2.height = 50;

CGRect  r = {{10, 20}, {30, 50}};

CGRect r2;  r2.origin.x = 10;  r2.origin.y = 20;  r2.size.width = 30;  r2.size.height = 50;

CGRect r3 = {p, s};


2>使用函数快速创建:

CGPoint p1 = CGPointMake(10, 20);         CGPoint p2 = NSMakePoint(10, 20);

CGSize  s1 = CGSizeMake (30, 50);         CGSize  s2 = NSMakeSize (30, 50); 

CGRect  r1 = CGRectMake (10, 20, 30, 50);      CGRect  r2 = NSMakeRect (10, 20, 30, 50);


CGPointZero  等价于  CGPointMake(0, 0)

CGSizeZero  等价于  CGSizeMake(0, 0)

CGRectZero  等价于  CGRectMake(0, 0, 0, 0)


3  常用函数

CGPointEqualToPoint(p1, p2);     //比较两个点的位置是否相同.

CGSizeEqualToSize(s1, s2);      //比较两个尺寸是否相同

CGRectEqualToRect(r1, r2);      //比较两个矩形是否占据同样的位置

CGRectContainsPoint(r, p);      //判断r这个矩形范围内是否包含p这个点.


 4快速查看所有属性


查看结构体内部的成员值,如果使用点成员名非常麻烦.比如,

NSLog(@"Origin (%d, %d). Size (%d, %d).", rect,origin,x, rect,origin,y, rectysize.x, rect.size.y);

注意

rect.origin.x里的点不是点语法,因为rect不是对象而是结构体,这里的点是访问结构体的成员.


最常使用的方式是,结构体转成字符串,可以快速打印所有属性的值

NSString *str_p = NSStringFromPoint(p);      //字符串 {10, 20}

NSString *str_s = NSStringFromSize(s);      //字符串 {30, 50}

NSString *str_r = NSStringFromRect(r);      //字符串 {{10, 20}, {30, 50}}

NSLog(@"%@", str_r);





 NSString


字符串的创建

直接创建字符串

NSString *s = @"hello";

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

 NSString *s = [[NSString alloc] initWithFormat:@"hello, %@!", @"jack"];


 C语言字符串和OC字符串的相互转换

NSString *s = [[NSString alloc] initWithUTF8String:"hello"];  //用于把C语言字符串转为OC字符串

const char *c = [s UTF8String];  //OC字符串转为C语言字符串


把文件内容读取为字符串

NSString *s = [[NSString alloc] initWithContentsOfFile:@"/Users/apple/Desktop/test.txt"encoding:NSUTF8StringEncoding error:nil]; 


把链接内容读取为字符串

URL就是资源路径,格式:协议头://路径

网络资源的协议头通常是http, 

本地资源通常是file, ftp资源是ftpURL字符串必须有协议头

NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop/test.txt"]; 

注意前面有三个斜杠,前两个是固定写法,第三个是表示绝对路径 /Users。另外, [NSURLfileURLWithPath:@"/Users/..."];  这种已经说了是 fileURL了就可以不加 file:// 了。

NSString *s = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:nil];


使用URL也可以读取远程文件,比如网页文件:

NSURL *baiduURL = [NSURL urlWithString:@"http://www.baidu.com"];  //可以查看源代码,发现编码是UTF8

NSString *s = [NSString stringWithContentsOfURL:baiduURL encoding:NSUTF8StringEncoding error:nil];     //读取的是网页的代码



使用类方法

NSString *s = [NSString stringWithFormat:@"%d", 5];

NSString *s = [NSString stringWithContentsOfURL: ...];

注意:NSString的类方法通常都以string开头。




 NSMutableString


 创建

NSMutableString继承NSString,创建可变字符串。

NSMutableString *ms = [NSMutableString stringWithFormat:@"age is 10"];

NSString *us = [NSString stringWithFormat:@"age is 10"];

注意:决定这个字符串是可变的还是不可变的,取决于右边调用方法的类,而不是左边对象指针的类型。


内容修改

1添加内容:

[ms appendString:@"ABC"];  //拼接内容到字符串后面

[ms appendFormat:@"%d", 5];

2替换内容:

range = [ms rangeOfString:@"no"]

[ms replaceCharactersInange:range withString:@"yes"];

3插入内容:

[ms insertString:@"hello" atIndex:3];  //在这个index前面插入

4删掉内容:

NSRange range = [ms rangeOFString:@"10"];

[ms deleteCharactersInRange:range];  //删掉部分内容


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值