• 访问外部网页

    实际上有两种方法,第一种是:

    1
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.google.com"]];



    这种方法将会退出当前程序,用Safari打开url。我有好几个朋友都问到这个问题,实际上非常简单,可以使用UIWebView在当前程序中打开网页(假定你的UIWebView实例为webView):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
         NSString *urlAddress = @"http://localhost";
           
        //Create a URL object.
        NSURL *url = [NSURL URLWithString:urlAddress];
           
        //URL Requst Object
        NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
           
        //Load the request in the UIWebView.
        [webView loadRequest:requestObj];
     
  • 以密码方式显示UITextField文本

    很简单,如下:

    1
    textField.secureTextEntry = YES;


     
  • 使用Javascript和PHP检测iPhone/iPod的使用

    这与iPhone编程无关,不过当你的网站需要为iPhone/iPod进行优化时,可能会需要使用下面的技术:


    使用Javascript检测是否正在使用iPhone 和 iPod


    如果你的网页需要支持iPhone和iPod Touch,首先你必须检测到是否正在使用iPhone和iPod Touch,这样你才可能为其使用特定的代码或样页式。下列代码段使用Javascript来检测iPhone/iPod Touch的使用,从而将网页重定向iPhone相关的网页。


    1
    2
    3
    4
    5
    6
    <br />
    if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {<br />
        if (document.cookie.indexOf("iphone_redirect=false") == -1) {<br />
            window.location = "http://m.espn.go.com/wireless/?iphone&i=COMR";<br />
        }<br />
    }<br />

     

    使用PHP检测是否正在使用 iPhone 和 iPod


    有时在iPhone上,Javascript被禁止使用。为检测到iPhone/iPod Touch的使用,你需要使用下列PHP代码:


    1
    2
    3
    4
    5
    <br />
    if(strstr($_SERVER['HTTP_USER_AGENT'],'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'],'iPod')) {<br />
        header('Location: http://yoursite.com/iphone');<br />
        exit();<br />
    }<br />

     
  • OpenGL ES纹理尺寸限制的处理方法

    大家都知道,OpenGL ES对纹理的尺寸有限制,就是长和宽都必须是2的整数次幂。(实际上OpenGL都有此限制,但有一些扩展可以解决此问题)。因此处理方案有两种:


    1. 将纹理尺寸限制为2的整数次幂。比如,我有一个480×320的背景图案,我可以用Photoshop将画布设置为512×512,在纹理映射时只使用480×320部分。当然我也可以将多个图案合成在一个纹理中,在纹理映射时根据图案的位置进行映射。
    2. 仍然使用正常的图像尺寸,但在使用时进行转换。下面是源代码:


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
            // 首先调整纹理的长和宽为2的整数次幂        
            if( (_width != 1) && (_width & (_width - 1)) )
            {
                    i = 1;
                    while((sizeToFit ? 2 * i : i) < _width)
                            i *= 2;
                    _width = i;
            }

            if( (_height != 1) && (_height & (_height - 1)) )
            {
                    i = 1;
                    while((sizeToFit ? 2 * i : i) < _height)
                            i *= 2;
                    _height = i;
            }

            // 如果调整后的图像尺寸大于最大纹理尺寸(1024),那么需要缩小
            while((_width &gt; kMaxTextureSize) || (_height &gt; kMaxTextureSize))
            {
                _width /= 2;
                _height /= 2;
                transform = CGAffineTransformScale(transform, 0.5, 0.5);
                imageSize.x *= 0.5;
                imageSize.y *= 0.5;
            }
     
  • iPhone程序的文档目录

    最近实在太忙,手头上的事情还没有完成,因此正在进行的几篇有关OpenGL ES的文章只能推后了。


    今天介绍一下怎样获得iPhone程序的文档目录(通常用来存储用户数据),方法一:


    1
    2
    NSString* documentsDirectory  = [NSHomeDirectory()
            stringByAppendingPathComponent:@"Documents"];


    方法二:


    1
    2
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
     
  • 开始学习iphone编程之六 – 简单示例代码

    下面有一些iPhone OS 3.0的范例代码。这些代码都是没有使用Interface Builder的。作为初学者,用这种方法可以更清晰的知道程序是怎样创建用户接口的。

    读文章 »

     
  • 振动

    想要你的iPhone/iPod Touch振动吗?实在很简单,只需一行代码:

    1
    AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);

    当然要记得在你的项目中加入AudioToolbox framework。不过振动的模式和长度无法控制。目前我在研究看是否有其他方法。

     
  • 存储OpenGL ES内容到相片簿中

    (注:本文改编自iPhone – saving OpenGL ES content to the Photo Album,懒得全文翻译了,只挑一下重点加上自己的语言描述一下)

     

    有许多程序都有将图片存入相片簿的功能。如果你使用了OpenGL ES,那么本文的方法适合你使用。简单步骤:

    1. 使用glReadPixels读取GL数据到字节数组中
    2. 使用UIImageWriteToSavedPhotosAlbum将UIImage存储到相片簿中

     

    但怎样将字节数组转换成UIImage比较困难。由于 [UIImage imageFromData:data]需要UIImage支持的文件格式,所以并不适用,因为从glReadPixels读取的字节数组中的数据是原始像素数据。可以使用CGImageCreate来创建一个CGImageRef,然后用[UIImage imageWithCGImage:imageRef]转换成UIImage。CGImageCreate要求CGDataProviderRef,可以通过CGDataProviderCreateWithData使用glReadPixels的数据来创建。整个过程的流程如下:

     

    glReadPixels -> CGDataProviderCreateWithData -> CGImageCreate -> [UIImage imageWithCGImage:] -> UIImageWriteToSavedPhotosAlbum

     

    但是还存在一个问题,OpenGL 使用标准笛卡尔坐标,即+Y朝上, -Y朝下。所以用glReadPixels获得的数组是上下颠倒的。可以使用位旋转技术进行修正。下面是代码(用在具有CAEAGLLayer的UIView中) :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
          -(UIImage *) glToUIImage {
       
              NSInteger myDataLength = 320 * 480 * 4;
               
              // allocate array and read pixels into it.
              GLubyte *buffer = (GLubyte *) malloc(myDataLength);
              glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
       
             // gl renders "upside down" so swap top to bottom into new array.
             // there's gotta be a better way, but this works.
             GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
     
             for(int y = 0; y <480; y++)
             {
                   for(int x = 0; x <320 * 4; x++)
                   {
                        buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
                   }
             }
             
            // make data provider with data.
            CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
             
            // prep the ingredients
            int bitsPerComponent = 8;
            int bitsPerPixel = 32;
            int bytesPerRow = 4 * 320;
     
            CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
            CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
            CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
             
            // make the cgimage
            CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel,
                 bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
           
            // then make the uiimage from that
            UIImage *myImage = [UIImage imageWithCGImage:imageRef];
            return myImage;
       }
     
       -(void)captureToPhotoAlbum {
                UIImage *image = [self glToUIImage];
                UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
        }
     
  • Poco C++ for iPhone之一 – 编译

    Poco C++是一个强大的跨平台C++库,你可以在iPhone程序中使用它,如果:

    1. 你打算使你的程序跨平台。
    2. 你喜欢使用C++或希望使用Poco C++中的功能如:XML,Zip等。

     

    目前,最新Poco C++版本为1.3.6P1,根据文档,它可以编译为iPhone静态库。但是我试用了一下,无法使用在iPhone Xcode项目中链接,不知何故。所以我自己创建了下列Xcode项目:

    • Poco Foundation
    • Poco Util
    • Poco Net
    • Poco XML
    • Poco Zip

     

    另外,由于Crypto,Data,NetSSL_OpenSSL库需要外部库而且目前我不需要使用,所以没有包括。另外我增加了一个目录iPhoneSamples,它目前包括了一个示例程序HelloPoco,演示了怎样在iPhone项目中使用Poco C++库(此演示程序十分简单,它调用Poco中的UUID功能,产生一个UUID,显示与屏幕上)。下面是包括了此展示程序以及各Xcode文件的Poco包的下载:

     

    poco-1.3.6p1

     
  • 跨平台代码分享之五 – 字符串转换

    严格地说,本文主题与跨平台代码无关。但是由于在iPhone上,通常界面程序还是由Objective-C编写的,经常需要用到STL string和NSString之间的转换。下面是转换的代码:

     

    NSString -> std::string

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    +(std::string)getString:(NSString*)theString
    {
        int size = [theString length]*sizeof(char);
        char *buffer = (char*) malloc(size+1);
        memset(buffer, 0, size+1);
        [theString getCString:buffer maxLength:size+1 encoding:NSASCIIStringEncoding];
        std::string str(buffer,size);
        free(buffer);
        return str;
    }

     

    std::string -> NSString

    1
    2
    3
    4
    +(NSString*)getNSString:(const std::string&)theString
    {
        return [NSString stringWithCString:theString.c_str()];
    }