当前位置:  编程技术>移动开发
本页文章导读:
    ▪利用ffmpeg1.0提取音频并播发        利用ffmpeg1.0提取音频并播放 很久以前,我就想在android做一个复读机程序,用来播放我喜欢的我从网上下的《老友记》,但编一个mp3播放机当然很容易,但其它格式只能借助其它解码工具了.........
    ▪ Java代码生成和好析xls文件        Java代码生成和解析xls文件 使用poi来生成xls文件:引用的包poi-3.2.final.jar;要了解的类HSSFWorkbook,HSSFSheet,HSSFRow,HSSFCellHSSFWorkbook workbook=new HSSFWorkbook();得到一个Excel文件的引用HSSFSheet sheet=workbook..........
    ▪ objective-c 札记5:类别       objective-c 笔记5:类别 1.什么是类别? 为现有的类添加新的方法。"category"   声明类别:   @interface NSString (NumberConvenience) - (NSNumber *) lengthAsNumber; @end // NumberConvenience        实现类别:   @i.........

[1]利用ffmpeg1.0提取音频并播发
    来源: 互联网  发布时间: 2014-02-18
利用ffmpeg1.0提取音频并播放

很久以前,我就想在android做一个复读机程序,用来播放我喜欢的我从网上下的《老友记》,但编一个mp3播放机当然很容易,但其它格式只能借助其它解码工具了,于是在网上找了一堆关于ffmpeg的资料。其它能完成音频播放的工能,欲发几篇文章,一来记录下这几天成果,二是然望能同修们有帮助。

首先的的开发环境是ubuntu,用的是ffmpeg1.0,现在网上很多资料都在很以前比较老的版本,
网上已有很多关于ffmpeg的下载和在lunix底下编译的文章,这里不不多作介绍了,之于利用ndk编译我以后有时间,会说下自己观点和看法。

提取音频程序与解码可能参考 fmpeg-1.0/doc/examples/filtering_audio.c和ffmpeg-1.0/doc/examples/decoding_encoding.c;ffmpeg.c和ffplay太过复杂,对于我这个急于求成的外行来说不太适宜。网上有几篇文章很好比如,
http://ushertechblog.sinaapp.com/post-24.html

#include <stdio.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <SDL.h>
#define SDL_AUDIO_BUFFER_SIZE 1024
typedef struct PacketQueue {
	AVPacketList * first_pkt, *last_pkt;
	int nb_packets;
	int size;
	SDL_mutex *mutex;		//mutex主要是用来实现资源的互拆的,跟java里在synchronize关键作用有相似之处
							//,虽然本和序中没有用多线程,但sdl在播放另启了一个线程。
	SDL_cond * cond;
} PacketQueue;
PacketQueue audioq;

void packet_queue_init(PacketQueue *q) {
	memset(q, 0, sizeof(PacketQueue));
	q->mutex = SDL_CreateMutex();
	q->cond = SDL_CreateCond();
}

int packet_queue_put(PacketQueue *q, AVPacket *pkt) {

	AVPacketList *pkt1;
	if (av_dup_packet(pkt) < 0)
		return -1;
	pkt1 = av_malloc(sizeof(AVPacketList));
	if (!pkt1)
		return -1;
	pkt1->pkt = *pkt;
	pkt1->next = NULL;

	SDL_LockMutex(q->mutex);

	if (!q->last_pkt)
		q->first_pkt = pkt1;
	else
		q->last_pkt->next = pkt1;
	q->last_pkt = pkt1;
	q->nb_packets++;
	q->size += pkt1->pkt.size;
	SDL_CondSignal(q->cond);

	SDL_UnlockMutex(q->mutex);
	return 0;
}

int quit = 0;
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {
	AVPacketList *pkt1;
	int ret;

	SDL_LockMutex(q->mutex);

	for (;;) {

		if (quit) {
			ret = -1;
			break;
		}

		pkt1 = q->first_pkt;
		if (pkt1) {
			q->first_pkt = pkt1->next;
			if (!q->first_pkt)
				q->last_pkt = NULL;
			q->nb_packets--;
			q->size -= pkt1->pkt.size;
			*pkt = pkt1->pkt;
			av_free(pkt1);			//这招我很赞赏,他在取去一个packet后,将上一个paket置空,而在下面的程序就不用再调用av_free操作了
			ret = 1;
			break;
		} else if (!block) {
			ret = 0;
			break;
		} else {
			SDL_CondWait(q->cond, q->mutex);
		}
	}
	SDL_UnlockMutex(q->mutex);
	return ret;
}

//int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size) {
int audio_decode_frame(AVCodecContext *aCodecCtx, AVFrame *frame,
		uint8_t *audio_buf) {
	static AVPacket pkt_temp;
	int len1, data_size, got_frame;
	int new_packet;
	for (;;) {
		while (pkt_temp.size > 0 || (!pkt_temp.data && new_packet)) {
			if (!frame) {
				if (!(frame = avcodec_alloc_frame()))
					return AVERROR(ENOMEM);
			} else {
				avcodec_get_frame_defaults(frame);
			}
			new_packet = 0;

			len1 = avcodec_decode_audio4(aCodecCtx, frame, &got_frame,
					&pkt_temp);
			if (len1 < 0) {
				/* if error, skip frame */
				pkt_temp.size = 0;
				break;
			}
			pkt_temp.data += len1;
			pkt_temp.size -= len1;

			if (got_frame <= 0) /* No data yet, get more frames */
				continue;
			data_size = av_samples_get_buffer_size(NULL, aCodecCtx->channels,
					frame->nb_samples, aCodecCtx->sample_fmt, 1);
			memcpy(audio_buf, frame->data[0], frame->linesize[0]);
			/* We have data, return it and come back for more later */
			return data_size;
		}
		if (quit)
			return -1;

		if ((new_packet = packet_queue_get(&audioq, &pkt_temp, 1)) < 0)
			return -1;

	}
}

void audio_callback(void *userdata, Uint8 *stream, int len) {
	AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;
	//以后变量全定义成static ,确保下次循环,变量不会被初始化
	static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
	static unsigned int audio_buf_remain_size=0;		//记录下audio_buffer剩余数据量
	static unsigned int audio_buf_total_size=0;			//记录下audio_buffer总数据量
	static unsigned int audio_buf_index = 0;

	int read_size; //第次送入*stream中数据的真正长度,理论值是len,但在最后一次操作实际值可能会小于len;

	AVFrame *frame = NULL;


	int flag=0;
	while(len){

		if(audio_buf_index>=audio_buf_total_size){

			audio_buf_remain_size = audio_decode_frame(aCodecCtx, frame, audio_buf);
			  audio_buf_total_size=audio_buf_remain_size;


			audio_buf_index=0;
			if(audio_buf_total_size<0){
						audio_buf_remain_size=audio_buf_total_size = 1024;
						memset(audio_buf, 0, audio_buf_total_size);
						continue;
			}
		}



		read_size=(audio_buf_remain_size > len)? len : audio_buf_remain_size;


		memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, read_size);

		audio_buf_index += read_size;
		audio_buf_remain_size -= read_size;
		stream += read_size;
		len -= read_size;
	}


}


int main(int argc, char *argv[]) {
	AVFormatContext *pFormatCtx;
	int i, videoStream, audioStream;
	AVCodecContext *pCodecCtx, *aCodecCtx;
	AVCodec *pCodec, *aCodec;
	AVFrame *pFrame;
	AVFrame *pFrameRGB;
	AVPacket packet;
	SDL_Event event;
	int frameFinished;
	int numBytes;
	uint8_t *buffer;

	if (argc < 2) {
		printf("Please provide a movie file\n");
		return -1;
	}

	if (SDL_Init(SDL_INIT_AUDIO)) {
		fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
		exit(1);
	}
	av_register_all();

	pFormatCtx = avformat_alloc_context();
	// Open video file
	//if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
	if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL ) != 0)
		return -1; // Couldn't open file

	// Retrieve stream information
	if (avformat_find_stream_info(pFormatCtx, NULL ) < 0)
		return -1; // Couldn't find stream information

	// Dump information about file onto standard error
	av_dump_format(pFormatCtx, 0, argv[1], 0);

	// Find the first video stream
	videoStream = -1;
	audioStream = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++) {
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO
				&& videoStream < 0)
			videoStream = i;
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
				&& audioStream < 0)
			audioStream = i;
	}
	if (videoStream == -1)
		return -1; // Didn't find a video stream
	if (audioStream == -1)
		return -1;
	// Get a pointer to the codec context for the video&audio stream
	pCodecCtx = pFormatCtx->streams[videoStream]->codec;

	aCodecCtx = pFormatCtx->streams[audioStream]->codec;

	SDL_AudioSpec wanted_spec, spec;
	wanted_spec.freq = aCodecCtx->sample_rate;
	wanted_spec.format = AUDIO_S16SYS;
	wanted_spec.channels = aCodecCtx->channels;
	wanted_spec.silence = 0;
	wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
	wanted_spec.callback = audio_callback;
	wanted_spec.userdata = aCodecCtx;

	if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
		fprintf(stderr, "SDL_OpenAudio:%s\n", SDL_GetError());
		return -1;
	}

	// Find the decoder for the video stream
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL ) {
		fprintf(stderr, "Unsupported codec!\n");
		return -1; // Codec not found
	}
	// Find the decoder for the video stream
	aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
	if (aCodec == NULL ) {
		fprintf(stderr, "Unsupported codec!\n");
		return -1; // Codec not found
	}
	// Open codec
	if (avcodec_open2(aCodecCtx, aCodec, NULL ) < 0)
		return -1; // Could not open codec
	// Open codec
	if (avcodec_open2(pCodecCtx, pCodec, NULL ) < 0)
		return -1; // Could not open codec

	packet_queue_init(&audioq);
	SDL_PauseAudio(0);
	//Set up a screen

	while (av_read_frame(pFormatCtx, &packet) >= 0) {
		// Is this a packet from the video stream?
		if (packet.stream_index == audioStream) {
			packet_queue_put(&audioq, &packet);
		} else {
			av_free_packet(&packet);
		}
		SDL_PollEvent(&event);
		switch (event.type) {
		case SDL_QUIT:
			quit = 1;
			SDL_Quit();
			exit(0);
			break;
		default:
			break;
		}

	}
	// Free the packet that was allocated by av_read_frame
	av_free_packet(&packet);

	// Free the RGB image

	for (;;) {

		getchar();							//这个是用来阻塞主线程,也可以用来接收键盘命令,比如暂停播放之类的
		break;
	}
	// Close the codec
	avcodec_close(pCodecCtx);
	avcodec_close(aCodecCtx);

	// Close the video file
	avformat_close_input(&pFormatCtx);

	return 0;
}



 


    
[2] Java代码生成和好析xls文件
    来源: 互联网  发布时间: 2014-02-18
Java代码生成和解析xls文件
使用poi来生成xls文件:引用的包poi-3.2.final.jar;

要了解的类HSSFWorkbook,HSSFSheet,HSSFRow,HSSFCell

HSSFWorkbook workbook=new HSSFWorkbook();得到一个Excel文件的引用

HSSFSheet sheet=workbook.createSheet();得到一个sheet,还有HSSFSheet sheet=workbook.createSheet("sheet1");方法可以设置Sheet的名称。

然后我们可以得到一行HSSFRow row=sheet.createRow(rowNum);

最后我们可以得到的是HSSFCell cell=row.create(cellNum);在Cell中还有一个类型的问题,一定要注意



下面是一个从数据库里面读取数据生成文件的方法

public void testQuery() {
    Transaction tx = null;
    tx = session.beginTransaction();
    Query query = session.createQuery("from Tid");
    List<Tid> list = query.list();
    tx.commit();
  int k = 0;
  HSSFWorkbook workbook = new HSSFWorkbook();
  HSSFSheet sheet = workbook.createSheet("sheet1");

  HSSFRow row = sheet.createRow(k);
  k++;

  //得到一个HSSFCell对象
  HSSFCell cell1 = row.createCell(0);

  //首先要设置HSSFCell的类型,一共有五种CELL_TYPE_STRING,CELL_TYPE_NUMBERIC,CELL_TYPE_FORMULA,

//CELL_TYPE_BLANK,CELL_TYPE_BOOLEAN,CELL_TYPE_ERROR,共6种

//具体可以查看文档http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFCell.html#getCellType()
  cell1.setCellType(HSSFCell.CELL_TYPE_STRING);
  cell1.setCellValue((new HSSFRichTextString("MER_NUM")));



HSSFCell cell2 = row.createCell(1);
  cell1.setCellType(HSSFCell.CELL_TYPE_STRING);
  cell2.setCellValue(new HSSFRichTextString("TML_NUM"));



  HSSFCell cell3 = row.createCell(2);
  cell1.setCellType(HSSFCell.CELL_TYPE_STRING);
  cell3.setCellValue(new HSSFRichTextString("COUNTER_NUM"));


for (Iterator<Tid> it = list.iterator(); it.hasNext();) {
      Tid tid = (Tid) it.next();
       HSSFRow row_ = sheet.createRow((short) k);
      

       HSSFCell c1 = row_.createCell(0);
       c1.setCellType(HSSFCell.CELL_TYPE_STRING);
       c1.setCellValue((new HSSFRichTextString(tid.getMer_num())));

    

       HSSFCell c2 = row_.createCell(1);
       c2.setCellType(HSSFCell.CELL_TYPE_STRING);
       c2.setCellValue(new HSSFRichTextString(tid.getTml_num()));

  

       HSSFCell c3 = row_.createCell(2);
       c3.setCellType(HSSFCell.CELL_TYPE_STRING);
       c3.setCellValue(new HSSFRichTextString(tid.getCounter_num()));
       k++;
  }

  //新建输出流对象FileOutputStream
  FileOutputStream fos = null;
  try {
     fos = new FileOutputStream("D://T99_TID_RELA.xls");

    //然后写入HSSFWorkbook中
     workbook.write(fos);
     fos.flush();
  } catch (Exception e) { // TODO Auto-generated catch block
     e.printStackTrace();
  } finally {
   if (null != fos) {
    try {
     fos.close();
     System.out.println("文件生成!");
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
}



HSSFCell类型判断与取值的方法

public String getCellValue(HSSFCell cell)throws Exception{

       int cellType=cell.getCellType();

       String cellValue=null;

      switch(cellType){   

       case HSSFCell.CELL_TYPE_NUMERIC:  
            cellValue = String.valueOf(cell.getNumericCellValue());

           /*

             *DecimalFormat df=new DecimalFormat("#");
             *cellValue = df.format(cell.getNumericCellValue());

             *DecimalFormat表示的数据格式化,有很多中用法

             */
            break;  
        case HSSFCell.CELL_TYPE_FORMULA:  
            cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);  
            cellValue = String.valueOf(cell.getNumericCellValue());  
            break;  
        case HSSFCell.CELL_TYPE_BLANK:  
            cellValue=" ";  
            break;  
        case HSSFCell.CELL_TYPE_BOOLEAN:  
            break;  
        case HSSFCell.CELL_TYPE_ERROR:  
            break; 

        default:
             throw new IllegalArgumentException("数据格式不对");

      }

      return cellValue;

}







解析一个Excel文件

public void testRead() {
  HSSFWorkbook workbook = null;
  DecimalFormat df = new DecimalFormat("#");
  try {
   workbook = new  HSSFWorkbook(new FileInputStream(new File(
     "D://Book1.xls")));

   //POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filePath));
   // 获得Sheet数
   System.out
     .println("===SheetsNum===" + workbook.getNumberOfSheets());
   // 开始读取
   for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
    if (null != workbook.getSheetAt(i)) {
     // 获得一个Sheet
     HSSFSheet sheet = workbook.getSheetAt(i);
     System.out.println("共有" + sheet.getLastRowNum() + "行");
     for (int rowNumOfSheet = 10; rowNumOfSheet <= sheet
       .getLastRowNum(); rowNumOfSheet++) {
      if (null != sheet.getRow(rowNumOfSheet)) {
       // 获得一个row
       HSSFRow row = sheet.getRow(rowNumOfSheet);
       System.out.print("第" + rowNumOfSheet + "行   ");
       // System.out.print("一行有"+row.getLastCellNum()+"单元格");
       for (short cellNumOfRow = 0; cellNumOfRow < row
         .getLastCellNum(); cellNumOfRow++) {

        HSSFCell cell = row.getCell(cellNumOfRow);
        int cellType = cell.getCellType();
        switch (cellType) {
        case 0:// Numberic
          String strCell = df.format(cell.getNumericCellValue());
          System.out.print(strCell + " ");
         break;
        case 1:
          strCell = cell.getRichStringCellValue().getString();
          System.out.print(strCell + " ");
          break;
        default:
          System.out.println("数据格式不对!");
        }
       }
       System.out.print("/n");
      }
     }
    }
   }
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

}





工具集HSSFCellUtil  http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/contrib/HSSFCellUtil.html



设置Sheet名称和单元格内容为中文

workbook.setSheetName(n,"库存",HSSFCell.ENCODING_UTF_16);

cell.setEncoding((short)1);cell.setCellValue("单位");



设置列宽和行高

sheet.setColumnWidth((short)column,(short)width);

row.setHeight((short)height);



添加区域,合并单元格

Region region=new Region((short)rowForm,(short)columnForm,(short)rowTo,(short)columnTo);

sheet.addMergedRegion(region);

// 得到该区域

sheet.getNumMergedRegion();



设置字体和内容位置

HSSFFont font=workbook.createFont();

font.setFontHeightInPoints((short) 11);//字号  
font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);//加粗  
style.setFont(font);  
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中  

style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中  

style.setRotation((short)rotation);//单元格内容的旋转的角度  

HSSFDataFormat df = wb.createDataFormat();  

style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式  

cell.setCellFormula(string);//给单元格设公式  

style.setRotation((short)rotation);//单元格内容的旋转的角度  

cell.setCellStyle(style)



常用的单元格边框格式

public static HSSFCellStyle getCellStyle(short type) {     

         HSSFWorkbook workbook =new  HSSFWorkbook();  

         HSSFCellStyle style = wb.createCellStyle();  

         style.setBorderBottom(type);//下边框   

         style.setBorderLeft(type);//左边框   

         style.setBorderRight(type);//右边框   

         style.setBorderTop(type);//上边框   

         return style;

      } 

虚线HSSFCellStyle.BORDER_DOTTED

实线HSSFCellStyle.BORDER_THIN



最后是插入图片

/先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray  

ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();  

BufferedImage bufferImg = ImageIO.read(new File("ok.jpg"));  

ImageIO.write(bufferImg,"jpg",byteArrayOut);  

//读进一个excel模版  

FileInputStream fos = new FileInputStream(filePathName+"/stencil.xlt");   

fs = new POIFSFileSystem(fos);  

//创建一个工作薄  

HSSFWorkbook wb = new HSSFWorkbook(fs);  

HSSFSheet sheet = wb.getSheetAt(0);  

HSSFPatriarch patriarch = sheet.createDrawingPatriarch();  

HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)10,10);       

patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG)); 


    
[3] objective-c 札记5:类别
    来源: 互联网  发布时间: 2014-02-18
objective-c 笔记5:类别

1.什么是类别?

为现有的类添加新的方法。"category"

 

声明类别:

 

@interface NSString (NumberConvenience)

- (NSNumber *) lengthAsNumber;

@end // NumberConvenience

 

 

 

 实现类别:

 

@implementation NSString (NumberConvenience)

-(NSNumber *) lengthAsNumber
{
unsigned int length = [self length];

return ([Number numberWithUnsignedInt: length]);

}//lengthAsNumber

@end //NumberConvenience

 

 

 

调用方法:

[dic setObject:[@"hello" lengthAsNumber] forKey:@"hello"];

 

2.类别的局限性:

   第一:无法向类中添加新的实例变量。(可以使用全局字典存储对象与你想要关联的额外变量之间的映射,但也要考虑是否s是完成当前任务的最佳选择)

   第二:名称冲突,即类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。你的类别方法将完全取代初始方法,从而无法再使用初始方法,增加前缀是个不错的选择。

 

3.类表的优点(作用)

  第一:类的实现不能分散到多个不同的.m文件中。而类别的实现则可以分散到多个不同的.m文件或多个不同的框架中。

  eg:

  @interface CategoryThing : NSObject{

 int thing1;
 int thing2;
 int thing3;
}

@end //CategoryThing

//3个类别声明
@interface CategoryThing (Thing1)
- (void) setThing1 :(int) thing1;
- (int) thing1;
@end // CategoryThing (Thing1)

@interface CategoryThing (Thing2)
- (void) setThing2 :(int) thing2;
- (int) thing2;
@end // CategoryThing (Thing2)

@interface CategoryThing (Thing3)
- (void) setThing3 :(int) thing3;
- (int) thing3;
@end // CategoryThing (Thing3)

    实现:

    CategoryThing的实现:

    #import "CategoryThing.h"

@implementation CategoryThing

-(NSString *) description
{
  NSString *desc;
  desc = [NSString stringWithFormat: @"%d %d %d",
  thing1,thing2,ting3];
  return (desc);
}//description

@end //CategoryThing

 

    thing1 的实现:

    # import "CategoryThing.h"

@implementation CategoryThing (Thing1)
-(void) setThing1:(int) t1
{
 thing1 = t1;
}//setTing1

-(int) thing1
{
 return (thing1);
}// thing1

@end //CategoryThing(Thing1)

 

   thing2,thing3 的实现类似ting1.....

 

 

  第二:创建对私有方法的前向引用。

 

  Cocoa中没有真正的私有方法,则实现私有方法类似功能的方法为:

先在类别中声明方法;然后到现有类的实现中实现该方法。

这样这个类中的其他方法可以使用该方法,而其他外部的类就不会知道该方法的存在了

 

  第三:向对象添加非正式协议。

 

非正式协议是NSObject 的一个类别。非正式协议用于实现委托。

什么又是委托呢?

委托(delegate),是一种对象,另一个类的对象会要求委托对象执行它的某些操作。如:NSWindow类的对象询问它自己的委托对象是否应该允许关闭某个窗口。

 

 

NSNetServiceBrowser *browser;
browser = [[NSNetServiceBrowser alloc] init];

ITunesFinder *finder;
finder = [[ITunesFinder alloc] init];
//告诉浏览器使用finder 对象为委托对象
[browser setDelegate:finder];
[browser do someing...]
[browser release];
[finder release];//好习惯从现在开始

    委托对象ITunesFinder 又是长什么样呢?

   ITunesFinder 接口:

    @interface ITunesFinder : NSObject

    @end // so easy?

 

    并不需要在@interface  中声明方法。要成为一个委托对象,我们只需要实现已经打算调用的方法。

 

   @implementation ITunesFinder

 

   -(void) test1

   {

      .......

    }

 

  -(void) test2

  {

    .....

  }

 

  test1和test2 为委托方法。

 

  委托和类别的关系:

 

 委托强调类表的另一种应用:被发送给委托对象的方法可以声明为一个NSObject 的类别。

 

响应选择器:

 @selector(test1:)

如果该委托对象能够响应给定的消息,则向该对象发送此消息,否则,将暂时忽略该委托对象,继续正常运行。

选择器可以被传递,可以作为方法的参数使用,可以作为实例变量存储。

 

 

 

 

 

 


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3