2018-01-17 10:14:10 shihuboke 阅读数 3142

 联系人:石虎 QQ:1224614774  昵称: 嗡嘛呢叭咪哄

                      QQ群:807236138  群称: iOS 技术交流学习群

 

一、概念

 1.Objective-C数据类型可以分为:基本数据类型、对象数据类型和id类型。

 2.基本数据类型有:int、float、double和char类型。

二、基本数据类型——int类型

 int类型代表整数,它的十六进制表示方式:OxFFED0D.

 在使用NSLog函数中格式化字符串使用%i表示十进制的整数,%o(字母o)表示8进制整数,%#x表示十六进制整数,它的取值范围是与设备相关的,无法一概而论。

 

三、基本数据类型——float类型

  1.float类型表示代表双精度浮点数,与float类型很相似,可以在数值后面加上f或者F,例如:13.5f。float浮点数也可以用科学计数法表示,例如:1.7e4。

 2.NSLog函数中格式化字符串:%f表示浮点数(会保留后面6位小数),%e表示科学计数法,%g表示浮点数。

 

四、基本数据类型——double类型

 1.double类型代表双精度浮点数,与float数相似,占用的字节空间double类型大体上是float类型的两倍。大多数计算机是使用64位,表示double类型。

 2.NSLog函数中格式化字符串,与float的%f、%e和%g相同。

 

五、基本数据类型——char类型(在计算机内部以int类型存储)

 1.char类型代表字符类型,存放点个字符,用单引号引用起来。如:’A’,如果要表示一些特殊字符,要使用转义字符“\”。

 2.NSLog函数中格式化字符串:%c。

 

谢谢!!!

2015-10-12 12:15:01 ZhouHZ351 阅读数 2517

iOS开发遇到的一个问题
对服务器返回的价格数据,直接转为字符串保存展示,服务器转过来的价格 如9.89,保存为字符串之后 变为了9.890000000000001。

处理过程为:

服务器返回的json 数据 为 responseString = {“code”:200000,”msg”:”ok”,”data”:[{“id”:34,”name”:”补胎”,”serviceParts”:[],”timeFeePrice”:9.89,”timeFeeOriginalPrice”:50.0}]}

我们看到json 数据里面 浮点数据 timeFeePrice = 9.89

responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];

经过系统json 转化为 NSDictionary* responseObject 后,打印responseObject 为

code = 200000;
    data =     (
                {
            id = 34;
            name = "\U8865\U80ce";
            serviceParts =             (
            );
            timeFeeOriginalPrice = 50;
            timeFeePrice = "9.890000000000001";
        }
    );
    msg = ok;

我们看到打印出来的 timeFeePrice = “9.890000000000001”;

因为 十进制数字“9.89”不能完全代表一个二进制浮点数等float或double。所以“舍入浮9.89”没有意义,因为没有完全等于9.89浮动。

你只能指定一个精度将浮点数转换为十进制输出字符串。您可以使用一个NSNumberFormatter或printf-format像”%.f

所以处理服务器返回的浮点数数据时,需要设置小数点位数。

价格数据处理,建议服务器统一使用分作为单位,传整形价格数据过来,客户端统一%100转元处理。

2013-01-22 15:19:40 marujunyy 阅读数 1191

首先看一下效果:


我定义了一个timer类,通过调用它来实现这样的效果。下面来看代码:

//  timer.h

#import <UIKit/UIKit.h>

@interface timer : UIView

- (id)initWithFrame:(CGRect)frame arcWidth:(double)width current:(double)current total:(double)total;

@end


//  TimeProportion.m


#import "TimeProportion.h"
#define PI 3.14159265358979323846


@implementation TimeProportion
static float arcWidth; //圆弧的宽度
static double pieCapacity;  //角度增量值

static inline float radians(double degrees) {
    return degrees * PI / 180;
}


- (id)initWithFrame:(CGRect)frame arcWidth:(double)width current:(double)current total:(double)total
{
    self = [super initWithFrame:frame];
    if (self) {
        arcWidth=width;
        pieCapacity=360*current/total;
        NSLog(@"pieCapacity->>%f",pieCapacity);
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();//获得当前view的图形上下文(context)
    //设置填充颜色
    CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    //设置画笔颜色
//    CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
    //设置画笔线条粗细
//    CGContextSetLineWidth(context, 0);
    
    //扇形参数
    double radius; //半径
    if(self.frame.size.width>self.frame.size.height){
        radius=self.frame.size.height/2-self.frame.size.height/10;
    }else{
        radius=self.frame.size.width/2-self.frame.size.width/10;
    }
    int startX=self.frame.size.width/2;//圆心x坐标
    int startY=self.frame.size.height/2;//圆心y坐标
    double pieStart=270;//起始的角度
    int clockwise=1;//0=逆时针,1=顺时针
    
    //顺时针画扇形
    CGContextMoveToPoint(context, startX, startY);
    CGContextAddArc(context, startX, startY, radius, radians(pieStart), radians(pieStart+pieCapacity), clockwise);
    CGContextClosePath(context);
//    CGContextDrawPath(context, kCGPathEOFillStroke);
    CGContextFillPath(context);
    
    clockwise=0;//0=逆时针,1=顺时针
    CGContextSetRGBStrokeColor(context, 255, 153, 0, 1);
    CGContextSetRGBFillColor(context, 255, 153, 0, 1);
    //逆时针画扇形
    CGContextMoveToPoint(context, startX, startY);
    CGContextAddArc(context, startX, startY, radius, radians(pieStart), radians(pieStart+pieCapacity), clockwise);
    CGContextClosePath(context);
//    CGContextDrawPath(context, kCGPathEOFillStroke);
    CGContextFillPath(context);
    
    //    画圆
    CGContextBeginPath(context);
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
    CGRect circle = CGRectInset(self.bounds, arcWidth, arcWidth);
    CGContextAddEllipseInRect(context, circle);
    CGContextFillPath(context);
    
}

@end


调用时候的代码:

    首先引入这个类: #import"timer.h"

    然后再调用这个类:

    CGRect frame = CGRectMake(60, 120, 200, 200);
    
    timer *timerView = [[timer alloc] initWithFrame:frame arcWidth:20 current:1 total:4];
    timerView.backgroundColor=[UIColor whiteColor];//设置背景色:白色
    [self.view addSubview: timerView];

2015-05-22 14:35:15 object_c_key 阅读数 432


(一)关于 id

在Objective-C,object有一个通用类型:id

id anObject;


上面这个定义仅仅只是标明了变量 anObject 是一个object(而不是int,double等基础类型),除此之外提供不了任何关于该object的类型信息(如果要得到该对象的更多信息,就要借助于 isa 指针)。

在C或C++中,函数的返回值默认为int,而在Objective-C中,函数的返回值默认为id

id的定义如下:

typedef struct objc_object {
 Class isa;
} *id;

因此每一个object都有一个isa,用于标明该object属于什么class。Class的定义如下:

typedef struct objc_class *Class;


编译器记录了每一个class的定义信息,runtime system会在运行时根据isa找到这些信息,比如:某个object属于哪个class,或者某个object能不能perform某个selector,或者找到它superclass的名字等。


(二)Object Messaging

1.奇怪的叫法:消息selector

在C语言中,我们说“调用某个函数”

int a = foo();

在C++中,我们说“某个object调用其某个成员方法”

int a = anObject.methodFunction();

在Object-C中,我们说 “给object发消息”

int a = [receiver message];

实际上,在Object-C中,所有的消息(也就是调用对象的方法)都是在运行时动态绑定的(C语言是编译时就确定好了函数地址)
[receiver message]


编译器会修改成对 objc_msgSend 的调用:

objc_msgSend(receiver, selector)


如果有参数,会是这样:

objc_msgSend(receiver, selector, arg1, arg2, ...)

注意:这个时候在叫法上,已经由 message 转换成 selector 了。

为什么叫 selector 呢?那是因为objc_msgSend会在这时候通过message 的名称,在一个叫做 dispatch table 的表里 选择 message 对应的函数地址,找到这个函数地址后,将参数传递给该函数,并将该函数的返回值作为 objc_msgSend 的返回值返回给调用者。所以这里有一个“选择”的意味,于是乎被称作 selector 了。

因为可以继承,所以通过 selector 进行函数搜索时,可能会沿着继承链一直往上找,直到NSObject,如下图(来自apple官方):



当给object发送message后,objc_msgSend 会通过该object的isa指针找到自己的dispatch table如果没有找到对应的函数地址,会一直沿着继承链往上搜索。


2. Sending Messages to nil

The keyword nil is defined as a null object, an id with a value of 0. (按照 id 的定义,nil 就是一个空指针喽~)

在Object-C中,给nil发message是合法的,且不会产生任何效果。但是对于返回值,还是有一些说法的:

1)如果message的返回值是object类型,那么当receiver为nil 时,返回值也是 nil

Person *motherInLaw = [[aPerson spouse] mother];

如果 [aPerson spouse] 返回nil,那么 [[aPerson spouse] mother] 返回nil

2)If the method returns any pointer type, any integer scalar of size less than or equal to sizeof(void*),a float, a double, a long double, or a long long, then a message sent to nil returns 0.

3)If the method returns a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, then a message sent to nil returns 0.0 for every field in the struct. Other struct data types will not be filled with zeros.

4)If the method returns anything other than the aforementioned value types, the return value of a message sent to nil is undefined.

示例:

id anObjectMaybeNil = nil;
// this is valid
if ([anObjectMaybeNil methodThatReturnsADouble] == 0.0)
{
 // implementation continues...
}



2015-12-13 09:48:17 daliandianzi0 阅读数 957
本文章为译文,并非原创 :)
    我们经常会混淆以下三种申明(我是没有留意过):
    1. id foo1;
    2. NSObject *foo2;
    3. id<NSObject> foo3;

    第一种是最常用的,它简单地申明了指向对象的指针,没有给编译器任何类型信息,因此,编译器不会做类型检查。但也因为是这样,你可以发送任何信息给id类型的对象。这就是为什么+alloc返回id类型,但调用[[Foo alloc] init]不会产生编译错误。

    因此,id类型是运行时的动态类型,编译器无法知道它的真实类型,即使你发送一个id类型没有的方法,也不会产生编译警告。

    我们知道,id类型是一个Objective-C对象,但并不是都指向继承自NSOjbect的对象,即使这个类型和NSObject对象有很多共同的方法,像retain和release。要让编译器知道这个类继承自NSObject,一种解决办法就是像第2种那样,使用NSObject静态类型,当你发送NSObject没有的方法,像length或者count时,编译器就会给出警告。这也意味着,你可以安全地使用像retain,release,description这些方法。

    因此,申明一个通用的NSObject对象指针和你在其它语言里做的类似,像java,但其它语言有一定的限制,没有像Objective-C这样灵活。并不是所有的Foundation/Cocoa对象都继承息NSObject,比如NSProxy就不从NSObject继承,所以你无法使用NSObject*指向这个对象,即使NSProxy对象有release和retain这样的通用方法。为了解决这个问题,这时候,你就需要一个指向拥有NSObject方法对象的指针,这就是第3种申明的使用情景。

    id<NSObject>告诉编译器,你不关心对象是什么类型,但它必须遵守NSObject协议(protocol),编译器就能保证所有赋值给id<NSObject>类型的对象都遵守NSObject协议(protocol)。这样的指针可以指向任何NSObject对象,因为NSObject对象遵守NSObject协议(protocol),而且,它也可以用来保存NSProxy对象,因为它也遵守NSObject协议(protocol)。这是非常强大,方便且灵活,你不用关心对象是什么类型,而只关心它实现了哪些方法。

    现在你知道你要用什么类型了不?

    如果你不需要任何的类型检查,使用id,它经常作为返回类型,也经常用于申明代理(delegate)类型。因为代理类型通常在运行时,才会检查是否实现了那些方法。

    如果真的需要编译器检查,那你就考虑使用第2种或者第3种。很少看到NSObject*能正常运行,但id<NSObject>无法正常运行的。使用协议(protocol)的优点是,它能指向NSProxy对象,而更常用的情况是,你只想知道某个对象遵守了哪个协议,而不用关心它是什么类型。

iOS strong weak

阅读数 184

没有更多推荐了,返回首页