zoukankan      html  css  js  c++  java
  • 内存相关

    内存管理


    在 Objective-C中,NSObject 定义了release和dealloc函数,一般来说,如果你的类中包含有对象,需要重载dealloc函数,在dealloc中释放类成员变量所占用的 内存,下面的代码演示了,当给一个对象发送release消息,或者这个对象被自动释放池回收时,dealloc会得到调用,这种行为使用dealloc 有点像C++中的析构函数。

    为什么释放时用release而不是dealloc?原因是需要由release判断引用计数,当引用计数为0时release才会调用dealloc执行实际的释放内存操作。

    文件 MyClass.h:

    #import <Foundation/Foundation.h>
    @interface MyClass: NSObject {
    }
    -(void) dealloc;
    -(void) release;
    +(MyClass*) createObj;
    @end

    文件 MyClass.m:

    #import "MyClass.h"

    @implementation MyClass
    -(void) release {
       NSLog(@"MyClass release");
       [super release];
    }
    - (void) dealloc {
       NSLog(@"MyClass dealloc");
       [super dealloc];
    }
    +(MyClass*) createObj {
       MyClass* pClass = [MyClass alloc];
       /* 给返回值发送了autorelease消息,表示该函数的调用者不需要手动释放返回值所指向的对象,这个对象会由自动释放池自动释放。*/
       return [pClass autorelease];
    }
    @end


    文件 main.m:

    #import <Foundation/Foundation.h>  
    #import "MyClass.h"

    int main( int argc, const char *argv[] ) {  
       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       MyClass* pClass = [MyClass createObj];
       [pool emptyPool];
       NSLog(@"exit.");
       [pool release];
        return 0;
    }




    如上面的代码所示,可以使用自动释放池会释放内存,但是如果有一部分内存要立即释放,即可以嵌套另一个自动释放池来实现,如下面的示例所示:

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

    {

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

    int i, j;

    for (i = 0; i < 100; i++ )

    {

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

    for (j = 0; j < 100000; j++ )

        [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。

    [loopPool release];

    }

    [pool release];

    return (0);

    } // main


    以上示例来自:http://www.cocoachina.com/bbs/read.php?tid-15963-page-1.html,这篇文章也推荐初学者读一读。


    Selector语法

    Selector的概念可参考以下两篇博文:
    http://ocen.javaeye.com/blog/518534
    http://blogold.chinaunix.net/u3/105675/showart_2459210.html

    简言之,Selector的作用是,可通过“方法名称”得到方法在类中的编号,然后用这个编号来调用方法(进行消息的发送)。

    Selector支持延时发送消息,例如:

    [self performSelector:@selector(showButton) withObject:nil afterDelay:1.5];

    Selector只关心方法的原型,而不关心它所属的类。

    文件 MyClass.h:

    #import <Foundation/Foundation.h>
    @interface Bird : NSObject {    /* 超类: 鸟 */  
    }  
    -(void) fly;
    -(void) fly: (NSNumber*) height;
    -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed;
    @end

    @interface Glede : Bird {}      /* 子类:老鹰 */  
    -(void) fly;
    -(void) fly: (NSNumber*) height;
    -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed;
    @end


    文件 MyClass.m:

    #import "MyClass.h"

    @implementation Bird
    -(void) fly               { NSLog(@"Bird.fly void"); }
    -(void) fly: (NSNumber*) height { NSLog(@"Bird.flyWithHeight %@", height); }
    -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed {
       NSLog(@"Bird.flyWithHeight %@, andSpeed %@", height, speed);
    }
    @end

    @implementation Glede
    -(void) fly               { NSLog(@"Glede.fly void"); }
    -(void) fly: (NSNumber*) height { NSLog(@"Glede.flyWithHeight %@", height); }
    -(void) fly: (NSNumber*) height withSpeed: (NSNumber*) speed {
       NSLog(@"Glede.flyWithHeight %@, andSpeed %@", height, speed);
    }
    @end


    文件 main.m:

    #import <Foundation/Foundation.h>  
    #import "MyClass.h"

    int main( int argc, const char *argv[] ) {
       Glede* pGled = [Glede alloc];
       Bird* pBird = [Bird alloc];
       /* performSelector不支持基本类型,所以数值用NSNumber */
       NSNumber *height = [[NSNumber alloc] initWithFloat:1000.0];
       NSNumber *speed  = [[NSNumber alloc] initWithFloat:10.0];

       /* 通过方法名得到方法ID */
       SEL fly                   = @selector(fly);             //指向不带参数的fly
       SEL flyWithHeight         = @selector(fly:);            //指向带一个int参数的fly
       SEL flyWithHeightAndSpeed = @selector(fly:withSpeed:);  //指向带二个int参数的fly
       /* 用pGled对象调用方法ID所对应的方法(或叫作发送消息给pGled) */
       [pGled performSelector:fly];
       [pGled performSelector:flyWithHeight withObject:height ];
       [pGled performSelector:flyWithHeightAndSpeed withObject:height withObject:speed ];

       /* 通过字符串得到方法ID */
       SEL flyWithHeight2         = NSSelectorFromString(@"fly:");
       SEL flyWithHeightAndSpeed2 = NSSelectorFromString(@"fly:withSpeed:");
       /* 用pBird对象调用方法ID所对应的方法(或叫作发送消息给pBird) */
       [pBird performSelector:flyWithHeight2 withObject:height ];
       [pBird performSelector:flyWithHeightAndSpeed2 withObject:height withObject:speed ];

       [pGled release];
       [height release];
       [speed release];

       return 0;
    }

    属性--高级篇


    属性的定义格式如下: 属性的定义格式如下:
    @property  (<parameters>) <type> <name>;

    parameters经常用到的是 copy/retain/assign/noatomatic,它们都用来控制如何自动生成setter和getter,下面分别说明它们之间的区别:
    假设要将以下变量设置成属性: NSString* name; 然后展开的setter函数可能是:

      copy retain assign
    setter函数的展开 -(void) setName:(NSString*) newValue  {  
      if (oldValue != newValue) {  
           [oldValue release];  
           oldValue = [newValue copy];  
      }  
    }
    -(void) setName:(NSString*) newValue  {  
       if (oldValue != newValue) {  
            [oldValue release];  
            oldValue = [newValue retain];  
       }  
    }
    -(void) setName:(NSString*) newValue  {  
     if (oldValue != newValue) {
          oldValue = newValue;  
     }  
    }
    主要区别 会创建一个新对象 引用传入的对象,并将传入的对象引用计数加1 直接赋值,主要用于基本类型
  • 相关阅读:
    Docker三剑客之 Compose
    cloudrea manager 调整datanode数据存储目录
    Docker Dockerfile 定制镜像(转)
    Docker配置mysql互为主从
    Docker构建redis cluster集群
    Kubernetes集群向指定节点上创建容器
    Docker私有仓库registry的搭建及使用
    Docker简介及基本应用
    Kubernetes的UI界面Kubernetes Dashboard的搭建
    java垃圾回收机制
  • 原文地址:https://www.cnblogs.com/chenfulai/p/2251043.html
Copyright © 2011-2022 走看看