id ,NSObject, id<NSObject>区别

Wed, 05 Nov 2014 14:24:55 GMT

我们经常会混淆以下三种申明(我是没有留意过):
    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对象,而更常用的情况是,你只想知道某个对象遵守了哪个协议,而不用关心它是什么类型。

 

更具体的:

 

1. 我们来看看id的定义,它就是一个指针,它可以指向的类型不仅限于NSObject

[代码]c#/cpp/oc代码:

1 typedef struct objc_class *Class;
2 typedef struct objc_object {
3     Class isa;
4 } *id;
 
2. NSObject*就是 NSObject类型的指针了,它范围较小。
 
3. id<NSObject>是指针,它要求它指向的类型要实现NSObject protocol,
iOS中很多类定义很奇葩,类名叫NSObject,定义个接口也叫NSObject,但是它俩不是一个东东。
 
而NSObject类实现了NSOject接口,所以id<NSObject>可以指向NSObject的对象。
NSObject实现类似这样:

[代码]c#/cpp/oc代码:

1 @interface NSObject <NSObject> {
2     Class isa;
3 }
4
 
如果我们来看看NSProxy的定义,你会发现,它不是继承自NSObject,但是却实现了NSObjecct接口,
NSProxy定义类似这样:

[代码]c#/cpp/oc代码:

1 @interface NSProxy <NSObject> {
2     Class   isa;
3 }
4
所以id<NSObject>可以指向NSProxy的对象。
...
浏览 : 6840 阅读全文

NSDate常用代码范例

Wed, 05 Nov 2014 14:22:22 GMT

NSDate常用代码范例  NSDate类用于保存时间值,同时提供了一些方法来处理一些基于秒级别时差(Time Interval)运算和日期之间的早晚比较等。

 

1. 创建或初始化可用以下方法

用于创建NSDate实例的类方法有

+ (id)date;

返回当前时间

+ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;  

返回以当前时间为基准,然后过了secs秒的时间

+ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs;

返回以2001/01/01 GMT为基准,然后过了secs秒的时间

+ (id)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;

返回以1970/01/01 GMT为基准,然后过了secs秒的时间

+ (id)distantFuture;

返回很多年以后的未来的某一天。(比如你需要一个比现在(Now)晚(大)很长时间的时间值,则可以调用该方法。测试返回了4000/12/31 16:00:00)

+ (id)distantPast;

返回很多年以前的某一天。(比如你需要一个比现在(Now)早(小)大很长时间的时间值,则可以调用该方法。测试返回了公元前0001/12/31 17:00:00)

 

...
浏览 : 6110 阅读全文

ios 目录 & 备份

Wed, 05 Nov 2014 14:20:06 GMT

 [1] 一些重要的 app 目录 
   <Application_Home>/AppName.app 
   这个是存放 app bundle 文件的目录,不要往这个目录中写入其他内容。在 iOS2.1 之后 ituns 同步时不会备份这个目录。ituns 在第一从 app store 购买应用并安装时会做一次同步备份,之后的同步不会备份。 

   <Application_Home>/Documents 
   这个目录存放用户 documents 和 app data files. 这个目录中的内容可以通过共享给用户。 ituns 同步时会备份此目录中的内容。 

   <Application_Home>/Library 
   这个目录是一个用来存放非用户文件的顶级目录,Library 目录下会有一些标准的子目录,你也可以添加自定义的子目录。这个目录下的内容,除 Caches 子目录外,会在ituns 同步时备份。 

   <Application_Home>/Library/Preferences 
   这个目录用来存放 app 指定的 preferences files.需要使用 NSUserDefaults 类 或者 CFPreferences API 来设置/获取 app preferences. 这个目录中的内容会被 ituns 备份。 

   <Application_Home>/Library/Caches 
   这个目录用来写入一些  app 的支持文件,比如app 启动后需要持久化的一些data,你的app 负责写入和移除此目录中的内容。在 iOS2.2 之后,这个目录内容不会被 ituns 备份。 

   <Application_Home>/tmp/ 
   这个目录用来写入临时文件,而不是应用需要持久化的data. 当文件不再使用你的 app 应该负责删除这些内容。如果你的应用不再运行,系统会删除这个文件夹中的内容。iOS 2.1 
之后这个文件夹的内容不会被 ituns 备份。 

  [2] 大小写敏感的文件系统 
   iOS 系统大小写敏感 Case-Sensitive 

  [3] 与 desktop 计算机共享文件 
   文件共享可以使你的 app 和 desktop 计算机之间共享文件。 

  (5) 备份和恢复 Backup and Restore 
   ituns 会自动处理 app 数据的备份和恢复,但你需要了解哪些目录中的内容会被备份 

   [1] 备份什么 
    你的 app 不需要为备份/恢复做什么特殊准备。在 iOS 2.2 之后,当设备连接到一个计算机并同步后,ituns 会自动增量备份所有文件,除了以下目录中的内容不会备份 

  • <Application_Home>/AppName.app
  • <Application_Home>/Library/Caches
  • <Application_Home>/tmp

  

  尽管 ituns 会备份 app bundle 内容 (<Application_Home>/AppName.app),但是只是在第一次从 app store 上下载安装时备份,之后的连接同步不会备份这目录的内容。为了防止同步时间过长,你应该选择保存data 的目录, <Application_Home>/Documents 用来存放用户文档和 app data, 这些内容会被备份。对于临时产生的文件需要存放在 <Applicaiton_Home>/tmp 中,他不会被 ituns 备份。 如果你的 app 需要保存数据为下次 app 启动时使用,而且这些数据也不需要 ituns 备份,保存到文件<Application_Home>/Library/Caches 目录中。 

...
浏览 : 6748 阅读全文

ios 正则表达式

Wed, 05 Nov 2014 14:19:30 GMT

1 【-100,100】之间最多带两位小数的数,例如:-100, -100.0, -99.1, ...

 

NSString *string = <...your source string...>;
NSError  *error  = NULL;

NSRegularExpression *regex = [NSRegularExpression 
  regularExpressionWithPattern:@"\\W-?1?[0-9]{2}(\\.[0-9]{1,2})?\\W"
                       options:0
                         error:&error];

NSRange range   = [regex rangeOfFirstMatchInString:string
                              options:0 
                              range:NSMakeRange(0, [string length])];
NSString *result = [string substringWithRange:range];
(\b|-)(100(\.0+)?|[1-9]?[0-9](\.[0-9]{1,2})?\b

 

Explanation:

(\b|-)      # word boundary or -
(           # Either match
 100        #  100
 (\.0+)?    #  optionally followed by .00....
|           # or match
 [1-9]?     #  optional "tens" digit
 [0-9]      #  required "ones" digit
 (          #  Try to match
  \.        #   a dot
  [0-9]{1,2}#   followed by one or two digits
 )?         #   all of this optionally
)           # End of alternation
\b          # Match a word boundary (make sure the number stops here).
...
浏览 : 7626 阅读全文

XCode debug 常用命令

Wed, 05 Nov 2014 14:17:52 GMT
  1. 命 令                        解释  
  2. break NUM               在指定的行上设置断点。  
  3. bt                      显 示所有的调用栈帧。该命令可用来显示函数的调用顺序。  
  4. clear                   删 除设置在特定源文件、特定行上的断点。其用法为:clear FILENAME:NUM。  
  5. continue                继续执行正在调试的程序。该命令用在程序 由于处理信号或断点而  
  6.                         导致停止运行 时。  
  7. display EXPR            每次程序停止后显示表达式的值。表达式由程序定 义的变量组成。  
  8. file FILE               装载指定的可执行文件进行调试。  
  9. help NAME               显 示指定命令的帮助信息。  
  10. info break              显 示当前断点清单,包括到达断点处的次数等。  
  11. info files              显 示被调试文件的详细信息。  
  12. info func               显示所有的函数名称。  
  13. info local              显 示当函数中的局部变量信息。  
  14. info prog               显示被调试程序的执行状 态。  
  15. info var                显示所有的全局和静态变量名称。  
  16. kill                    终 止正被调试的程序。  
  17. list                    显示源代码段。  
  18. make                    在 不退出 gdb 的情况下运行 make 工具。  
  19. next                    在 不单步执行进入其他函数的情况下,向前执行一行源代码。  
  20. print EXPR              显 示表达式 EXPR 的值。  
  21.   
  22. print- object            打印一个对象  (简称为po)
  23. print (intname      打印一个类型  
  24. print- object [artist description]   调用一个函数  (artist是一个对象)
  25. set artist @"test"    设置变量值  
  26. whatis                      查 看变理的数据类型  
...
浏览 : 8254 阅读全文

ios 内存管理(2)

Wed, 05 Nov 2014 14:15:24 GMT

集中与iOS的多核编程和内存管理,大家完全可以使用苹果的多核编程框架来写出更加responsive的应用。

 

多核运算

    在iOS中concurrency编程的框架就是GCD(Grand Central Dispatch), GCD的使用非常简单。它把任务分派到不同的queue队列来处理。开发者把任务代码装到一个个block里面,操作系统把这些任务代码分派到不同的资源里去处理,一个简单的例子来说,为什么初学者写tableview的时候,滑动列表时总会很卡,因为很多初学者把图片装载放到main thread主线程去执行,例如我们要滑动畅顺的话,iOS最快可以1秒内刷新60次,如何你的一个cell的文字和图片装载超过1/60秒的话,自然就会卡。所以一般我们会把图片装载这些需要多点时间的移出main thread来处理,对于用GCD来说,就是把图片载入放到另外一个queue队列中来异步执行,当资源准备好了后,放回到main thread中显示出来。main thread在GCD中就是main queue。

...
浏览 : 6316 阅读全文

ios 内存管理(1)

Wed, 05 Nov 2014 14:14:52 GMT

此文涉及的内存管理是针对于继承于NSObject的Class。

一 基本原理

Objective-C的内存管理机制与.Net/Java那种全自动的垃圾回收机制是不同的,它本质上还是C语言中的手动管理方式,只不过稍微加了一些自动方法。

1           Objective-C的对象生成于堆之上,生成之后,需要一个指针来指向它。

ClassA *obj1 = [[ClassA alloc] init];

 

2           Objective-C的对象在使用完成之后不会自动销毁,需要执行dealloc来释放空间(销毁),否则内存泄露。

[obj1 dealloc];

         这带来了一个问题。下面代码中obj2是否需要调用dealloc?

ClassA *obj1 = [[ClassA alloc] init];

ClassA *obj2 = obj1;

[obj1 hello]; //输出hello

[obj1 dealloc];

[obj2 hello]; //能够执行这一行和下一行吗?

[obj2 dealloc];

         不能,因为obj1和obj2只是指针,它们指向同一个对象,[obj1 dealloc]已经销毁这个对象了,不能再调用[obj2 hello]和[obj2 dealloc]。obj2实际上是个无效指针。

         如何避免无效指针?请看下一条。

 

3           Objective-C采用了引用计数(ref count或者retain count)。对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count为2。需要销毁对象的时候,不直接调用dealloc,而是调用release。release会让retain count减1,只有retain count等于0,系统才会调用dealloc真正销毁这个对象。

...
浏览 : 7210 阅读全文

Object-C 类,对象,运行时,isa

Wed, 05 Nov 2014 14:12:59 GMT

   如果不是Apple,不是App Store,Object-C恐怕早就淡出人们的视线了。大部分编程语言都是基于C语法风格的,所以初次接触这个非C风格的语言,会看不懂它那怪异的语法。但如果掌握了它之后,也并不会觉得它又太多的不同。今天记录一下它的底层运作。
       1: 类Class:
      
 typedef struct objc_class * Class;
     从Class的定义可以看出,它是一个 objc_class 结构类型的指针,objc_class又是什么呢?
   

struct objc_class
{
    struct objc_class* isa;
    struct objc_class* super_class;  //root的为null
    const char* name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list* ivars;
    struct objc_method_list** methodLists;  //方法列表
    struct objc_cache* cache;     //缓存最近使用的方法,以提高效率;
    struct objc_protocol_list* protocols;
};
      为什么Class的第一个成员也是Class呢,它的内存布局岂不是和底下的object一样了?其实这就是类对象(class object)与实例对象(instance object)的区别了。
     Object-C对类对象与实例对象中的 isa 所指向的类结构作了不同的命名:类对象中的 isa 指向类结构被称作 metaclass,metaclass 存储类的static类成员变量与static类成员方法(+开头的方法);实例对象中的 isa 指向类结构称作 class(普通的),class 结构存储类的普通成员变量与普通成员方法(-开头的方法).
  
     2:对象id:
     typedef struct objc_object {
         Class isa;
     } *id;
    可以发现, id可以用来表示任意一个对象,它是一个 objc_object 结构类型的指针,其第一个成员是一个 objc_class 结构类型的指针。
    我们的根类NSObject也同样是只有一个Class成员:
   @interface NSObject <NSObject> {
       Class       isa;
    }
    这个isa到底是什么呢?官方介绍是这样的:

    Every object is connected to the run-time system through its isa instance variable, inherited from the NSObject class.isa identifies the object's class; it points to a structure that's compiled from the class definition. Through isa, an object can find whatever information it needs at run timesuch as its place in the inheritance hierarchy, the size and structure of its instance variables, and the location of the method implementations it can perform in response to messages.
    可见,一个对象(Object)的isa指向了这个对象的类(Class),而这个对象的类(Class)的isa指向了metaclass。这样我们就可以找到静态方法和变量了。


       3: 运行时: 
     Objective-C的运行时是动态的,它能让你在运行时为类添加方法或者去除方法以及使用反射。这在其它语言是不多见的。
       

     类的实例对象的 isa 指向它的类;类的 isa 指向该类的 metaclass;
     类的 super_class 指向其父类,如果该类为根类则值为 NULL;
     metaclass 的 isa 指向根 metaclass,如果该 metaclass 是根 metaclass 则指向自身;
     metaclass 的 super_class 指向父 metaclass,如果该 metaclass 是根 metaclass 则指向该 metaclass 对应的类;
     Object-C 为每个类的定义生成两个 objc_class ,一个普通的 class,另一个即 metaclass。我们可以在运行期创建这两个 objc_class 数据结构,然后使用 objc_addClass将 class 注册到运行时系统中,以此实现动态地创建一个新的类。
 
...
浏览 : 7096 阅读全文

NSFileHandle 大数据量读写操作

Wed, 05 Nov 2014 14:11:37 GMT

NSBundle *mainBundle = [NSBundle mainBundle];
    NSString *txtPath = [mainBundle pathForResource:@"output" ofType:@"rtf"];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL exist = [fileManager fileExistsAtPath:txtPath];
    
    if(!exist)
    {
        [fileManager createFileAtPath:txtPath contents:nil attributes:nil];
    }
        

...
浏览 : 10658 阅读全文

NSString && NSMutableString 常见用法

Wed, 05 Nov 2014 14:09:06 GMT

--实例化方法-------------- 
NSString *str = [[NSString alloc] init]; 
NSString *str = [[[NSString alloc] init] autorelease];   

注意:在NSString 中存在自己的实例化和初始化的方法 例如: 
NSString *str1 = [NSString stringWithCString:"new String" enconding: NSACIIStringEncoding]; 
NSString *str2 = [NSString alloc] initWithCString:"new String" enconding: NSACIIStringEncoding]; 
str1和str2两个对象是相同的。 

--NSStringEncoding 中常用的字符编码---------------- 
     NSASCIIStringEncoding 
     NSUTF8StringEncoding 
     NSUnicodeStringEncoding 

--NSString创建实例---------------- 
带“@”符号的方法只能定义含有英文和数字的NSString实例,例如: 
NSString *str = "Hello money~"; 
--生成含有中文的NSString方法------------- 
//此方法自动释放内存 
+ (id)stringWithCString:(const char*)cString encoding:(NSStringEncoding)encoding; 
//进行alloc后进行初始化 
- (id)initWithCString:(const char*)cString encoding:(NSStringEncoding)encoding; 
例如: 
NSString *string = [NSString stringWithCString:"您好" encoding:NSUTF8StringEncoding]; 
NSString *string = [[NSString alloc] initWithCString:"您好" encoding:NSUTF8StringEncoding]; 

...
浏览 : 7023 阅读全文

ios开发入门级实例

Sat, 08 Nov 2014 03:06:13 GMT

关于如何创建第一个 iOS 应用

本篇“第一个 iOS 应用”教程将向你介绍 iOS 应用开发中的“三个T”:

  • Tools(工具)如何利用 Xcode 创建和管理工程。
  • Technologies(技术)如何创建能够响应用户输入的应用。
  • Techniques(技巧)如何充分利用 iOS 应用开发的基础设计模式。

当你完成本教程的所有步骤之后,你的应用看起来会和下边图中的差不多:

appSimulator

从图中可以看到,你创建的应用界面上有三个主要的元素:

  • 一个文本框(用户把文字输入到这里)
  • 一个标签(这里可以用来显示信息)
  • 一个按钮(它能够让应用在标签处显示信息)
...
浏览 : 7173 阅读全文