• 图形库Core Plot


    [深入浅出iOS库]之图形库Core Plot

     

    [深入浅出iOS库]之图形库CorePlot

    罗朝辉 (http://www.cnblogs.com/kesalin/)

    本文遵循“署名-非商业用途-保持一致”创作公用协议

    一,前言

    Core Plot和s7Graph都是可在iOS平台下使用的开源矢量图形库,s7Graph功能相对比较简单一些,在此就不介绍了。Core Plot 功能强大很多,我们可以利用它很方便地画出复杂的曲线图、柱状图和饼图等等。下面我先来介绍如何在项目中配置使用 Core Plot 库,然后通过一个曲线图示例来演示如何使用它,最后结合示例介绍 Core Plot 的框架结构。

    本文源代码:https://github.com/kesalin/iOSSnippet/tree/master/CorePlotDemo

    效果图:

     

    二,在iOS工程中配置 Core Plot

    1,下载 Core Plot 库

    Core Plot 代码仓库托管在 Google Code 上,可通过 https://code.google.com/p/core-plot/ 获取最新的库和源码(目前为1.1),在这里我们只关心 iOS平台:

    解压 CorePlot_1.1.zip,其目录结构如下:

    如果通过静态链接方式引用CorePlot库,那么我们只需要关心Binaries/iOS目录即可,但是作为一个喜欢钻研的程序员,Documentation和Source下面想必你也不会视而不见;如果通过引入工程文件方式引用CorePlot库,那么我们需要引用Source/framework/CorePlot-CocoaTouch.xcodeproj。注意:CorePlot同时支持OS X 和 iOS 平台,CorePlot.xcodeproj 是OS X平台工程。此外,Source/examples 下的大量示例代码绝对是不可忽视的第一手参考资料。

    顺便吐槽一句,iOS平台的开源库很多,也会强大,但一如 iOS 系统自身,向后兼容性太差,用过Cocos 2D等库的童鞋应该深有体会。CorePlot也不例外,以前用0.4版本的时候,类名前缀市 CP,现在都修改为 CPT(CorePlot-Touch)了。

    2,在工程中添加 Core Plot 库

    下面,我将介绍如何用静态链接方式引用 CorePlot 库

    a),新建 CorePlotDemo SingleView 工程,拷贝 Binaries/iOS 目录到项目目录下,并重命名 iOS 为 CorePlotLib,如图所示:

    b) 在工程中通过添加已存在文件将 CorePlotHeaders  目录下的文件全部添加,并链接 libCorePlotTouch.a 静态库。如图所示:

    c) 因为CorePlot使用到 QuartzCore 库,所以我们还需要连接 QuartzCore.framework。此外为了让 XCode 装载导入头文件,需要设置编译环境,在 build setting 中查找 other linker flags,添加 '-all_load -ObjC' 标志。至此设置工作完成。

    三,使用 Core Plot 描绘曲线图

    1,Core Plot 要求它进行描绘的所在 view 类型必须为 CPTGraphHostingView 类型,所以在这里,我将设置 ViewController.nib 中 View 的类型为 CPTGraphHostingView。如图所示:

    2,修改 KSViewController.h 为:

    复制代码
    #import <UIKit/UIKit.h>
    #import "CorePlot-CocoaTouch.h"
    
    @interface KSViewController : UIViewController<CPTPlotDataSource, CPTAxisDelegate>
    
    @end
    复制代码

    如果你用过 NSTableView,那你应该很熟悉 CPTPlotDataSource 这种形式协议的用法, CPTPlotDataSource 为 CorePlot 提供数据源。在这里我还实现了 CPTAxisDelegate 协议,当我们想要对轴刻度的标签进行一定的定制时,需要实现该协议。在本例中,要用不同的颜色对 y 轴方向大于等于0和小于0的刻度标签进行区分,因此需要实现该协议。

    3,声明私有成员和方法

    请参考文件:https://github.com/kesalin/iOSSnippet/blob/master/CorePlotDemo/CorePlotDemo/KSViewController.m

    复制代码
    @interface KSViewController ()
    {
        CPTXYGraph * _graph;
        NSMutableArray * _dataForPlot;
    }
    
    - (void)setupCoreplotViews;
    
    -(CPTPlotRange *)CPTPlotRangeFromFloat:(float)location length:(float)length;
    
    @end
    复制代码

    在本例中,要描绘基于 xy 轴的图形,因此,声明了 CPTXYGraph 对象 _graph,然后声明一个可变数字 _dataForPlot 为 Core Plot 提供数据。私有方法 setupCoreplotView 是本例的重点,所有的描绘设置都在这个函数中进行。CPTPlotRangeFromFloat:length:是一个辅助类以简化 CPTPlotRange 的创建,其实现如下:

    -(CPTPlotRange *)CPTPlotRangeFromFloat:(float)location length:(float)length
    {
        return [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(location) length:CPTDecimalFromFloat(length)];
    }

    为了支持旋转操作,添加如下代码(注意,本文只考虑了 iOS6 的旋转,这又是 iOS 兼容性不太好的一大明证啊!):

    复制代码
    #pragma mark -
    #pragma mark Rotation
    
    -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
    {
        return YES;
    }
    
    -(BOOL)shouldAutorotate
    {
        return YES;
    }
    复制代码

    4,实现 setupCoreplotViews

    先来看效果说明图,此图非常重要,CorePlot常见的概念都在图中有说明,后文会多次引用到该图。

    下面,来介绍重点内容,如何使用 CorePlot 对数据进行描绘。

    复制代码
    - (void)setupCoreplotViews
    {
        CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
        
        // Create graph from theme: 设置主题
        //
        _graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
        CPTTheme * theme = [CPTTheme themeNamed:kCPTSlateTheme];
        [_graph applyTheme:theme];
        
        CPTGraphHostingView * hostingView = (CPTGraphHostingView *)self.view;
        hostingView.collapsesLayers = NO; // Setting to YES reduces GPU memory usage, but can slow drawing/scrolling
        hostingView.hostedGraph = _graph;
        
        _graph.paddingLeft = _graph.paddingRight = 10.0;
        _graph.paddingTop = _graph.paddingBottom = 10.0;
    复制代码

    a)首先,创建了一个可编辑的线条风格 lineStyle,用来描述描绘线条的宽度,颜色和样式等,这个 lineStyle 会被多次用到。

    然后,创建基于 xy 轴的图:CPTXYGraph,并设置其主题 CPTTheme,CorePlot 中的主题和日常软件中的换肤概念差不多。目前支持五种主题:kCPTDarkGradientTheme, kCPTPlainBlackTheme, kCPTPlainWhiteTheme, kCPTSlateTheme,kCPTStocksTheme, 最后一种股票主题效果见上面的效果图,而石板色主题 kCPTSlateTheme 效果见下面的效果图。你可以修改此处的代码尝试不同的主题效果,^_^。将 hostingView的 hostedGraph与 _graph 关联起来,也就是说:我们要在 View (CPTGraphHostingView)上画一个基于xy轴的图(CPTXYGraph)。至此,我们接触到CorePlot中的两个概念:宿主view 和图graph。然后我们设置_graph的 padding,这样在图的四周与屏幕边缘之间留有一丝空隙。

    复制代码
        // Setup plot space: 设置一屏内可显示的x,y量度范围
        //
        CPTXYPlotSpace * plotSpace = (CPTXYPlotSpace *)_graph.defaultPlotSpace;
        plotSpace.allowsUserInteraction = YES;
        plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(1.0) length:CPTDecimalFromFloat(2.0)];
        plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(1.0) length:CPTDecimalFromFloat(3.0)];
    复制代码

    上面的代码设置PlotSpace,这是什么意思呢?x,y二维空间可以无限延伸,但在屏幕上我们可以看到的只是一小部分空间,这部分可视空间就由 Plot Space设置。CPTXYPlotSpace 的 xRange 和 yRange 就设置了一屏内可显示的x,y方向的量度范围。在这里,我们设置x,y轴上的起点都是1.0,然后长度分别为2个和3个单位。请结合上面的说明图理解 PlotSpace 的含义。(注意:说明图中的起点不是1.0,这是因为设置了 allowsUserInteraction 为 YES,我对PlotSpace进行了拖动所导致的)。

    复制代码
        // Axes: 设置x,y轴属性,如原点,量度间隔,标签,刻度,颜色等
        //
        CPTXYAxisSet *axisSet = (CPTXYAxisSet *)_graph.axisSet;
        
        lineStyle.miterLimit = 1.0f;
        lineStyle.lineWidth = 2.0;
        lineStyle.lineColor = [CPTColor whiteColor];
        
        CPTXYAxis * x = axisSet.xAxis;
        x.orthogonalCoordinateDecimal = CPTDecimalFromString(@"2"); // 原点的 x 位置
        x.majorIntervalLength = CPTDecimalFromString(@"0.5");   // x轴主刻度:显示数字标签的量度间隔
        x.minorTicksPerInterval = 2;    // x轴细分刻度:每一个主刻度范围内显示细分刻度的个数
        x.minorTickLineStyle = lineStyle;
        
        // 需要排除的不显示数字的主刻度
        NSArray * exclusionRanges = [NSArray arrayWithObjects:
                                     [self CPTPlotRangeFromFloat:0.99 length:0.02],
                                     [self CPTPlotRangeFromFloat:2.99 length:0.02],
                                     nil];
        x.labelExclusionRanges = exclusionRanges;
    复制代码

    b), 有了 xy 轴图对象,我们可以来对 xy 轴的显示属性进行设置了。通过获取 XYGraph 的 axisSet 来获取轴的集合,集合中就包含了 x,y 轴对象 CPTXYAxis。在这里,设置 x 轴的原点为 2,主刻度的量度间隔为 0.5,每一个主刻度内显示细分刻度的个数为 2 个,并用白色宽度为2的线条来描绘 x 轴。如果有一些刻度的标签我们不想让它显示那该如何呢?很简单,设置轴的排除标签范围 labelExclusionRanges 即可。

    同样,我们设置 y 轴的显示属性:

    复制代码
        CPTXYAxis * y = axisSet.yAxis;
        y.orthogonalCoordinateDecimal = CPTDecimalFromString(@"2"); // 原点的 y 位置
        y.majorIntervalLength = CPTDecimalFromString(@"0.5");   // y轴主刻度:显示数字标签的量度间隔
        y.minorTicksPerInterval = 4;    // y轴细分刻度:每一个主刻度范围内显示细分刻度的个数
        y.minorTickLineStyle = lineStyle;
        exclusionRanges = [NSArray arrayWithObjects:
                           [self CPTPlotRangeFromFloat:1.99 length:0.02],
                           [self CPTPlotRangeFromFloat:2.99 length:0.02],
                           nil];
        y.labelExclusionRanges = exclusionRanges;
        y.delegate = self;
    复制代码

    请参考说明图理解上面轴设置的含义。注意,在这里,我设置了 y 轴的 delegate 为自身,这个 delegate 需要实现CPTAxisDelegate 协议,在这里我想要用不同的颜色对 y 轴方向大于等于0和小于0的刻度标签进行区分,因此需要实现该协议方法:axis:shouldUpdateAxisLabelsAtLocations:。

    复制代码
    #pragma mark -
    #pragma mark Axis Delegate Methods
    
    -(BOOL)axis:(CPTAxis *)axis shouldUpdateAxisLabelsAtLocations:(NSSet *)locations
    {
        static CPTTextStyle * positiveStyle = nil;
        static CPTTextStyle * negativeStyle = nil;
        
        NSNumberFormatter * formatter   = axis.labelFormatter;
        CGFloat labelOffset             = axis.labelOffset;
        NSDecimalNumber * zero          = [NSDecimalNumber zero];
        
        NSMutableSet * newLabels        = [NSMutableSet set];
        
        for (NSDecimalNumber * tickLocation in locations) {
            CPTTextStyle *theLabelTextStyle;
            
            if ([tickLocation isGreaterThanOrEqualTo:zero]) {
                if (!positiveStyle) {
                    CPTMutableTextStyle * newStyle = [axis.labelTextStyle mutableCopy];
                    newStyle.color = [CPTColor greenColor];
                    positiveStyle  = newStyle;
                }
    
                theLabelTextStyle = positiveStyle;
            }
            else {
                if (!negativeStyle) {
                    CPTMutableTextStyle * newStyle = [axis.labelTextStyle mutableCopy];
                    newStyle.color = [CPTColor redColor];
                    negativeStyle  = newStyle;
                }
        
                theLabelTextStyle = negativeStyle;
            }
            
            NSString * labelString      = [formatter stringForObjectValue:tickLocation];
            CPTTextLayer * newLabelLayer= [[CPTTextLayer alloc] initWithText:labelString style:theLabelTextStyle];
            
            CPTAxisLabel * newLabel     = [[CPTAxisLabel alloc] initWithContentLayer:newLabelLayer];
            newLabel.tickLocation       = tickLocation.decimalValue;
            newLabel.offset             = labelOffset;
            
            [newLabels addObject:newLabel];
        }
        
        axis.axisLabels = newLabels;
        
        return NO;
    }
    复制代码

    在上面的代码中,对于 y 轴上大于等于0的刻度标签用绿色描绘,而小于0的刻度标签用红色描绘。因为在这里我们自己设置了轴标签的描绘,所以这个方法返回 NO 告诉系统不需要使用系统的标签描绘设置了。其效果如下:

    至此,xy轴部分的描绘设置完成。

    c) 下面我们向图中添加曲线的描绘:

    复制代码
        // Create a red-blue plot area
        //
        lineStyle.miterLimit        = 1.0f;
        lineStyle.lineWidth         = 3.0f;
        lineStyle.lineColor         = [CPTColor blueColor];
        
        CPTScatterPlot * boundLinePlot  = [[CPTScatterPlot alloc] init];
        boundLinePlot.dataLineStyle = lineStyle;
        boundLinePlot.identifier    = BLUE_PLOT_IDENTIFIER;
        boundLinePlot.dataSource    = self;
        
        // Do a red-blue gradient: 渐变色区域
        //
        CPTColor * blueColor        = [CPTColor colorWithComponentRed:0.3 green:0.3 blue:1.0 alpha:0.8];
        CPTColor * redColor         = [CPTColor colorWithComponentRed:1.0 green:0.3 blue:0.3 alpha:0.8];
        CPTGradient * areaGradient1 = [CPTGradient gradientWithBeginningColor:blueColor
                                                                  endingColor:redColor];
        areaGradient1.angle = -90.0f;
        CPTFill * areaGradientFill  = [CPTFill fillWithGradient:areaGradient1];
        boundLinePlot.areaFill      = areaGradientFill;
        boundLinePlot.areaBaseValue = [[NSDecimalNumber numberWithFloat:1.0] decimalValue]; // 渐变色的起点位置
        
        // Add plot symbols: 表示数值的符号的形状
        //
        CPTMutableLineStyle * symbolLineStyle = [CPTMutableLineStyle lineStyle];
        symbolLineStyle.lineColor = [CPTColor blackColor];
        symbolLineStyle.lineWidth = 2.0;
        
        CPTPlotSymbol * plotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
        plotSymbol.fill          = [CPTFill fillWithColor:[CPTColor blueColor]];
        plotSymbol.lineStyle     = symbolLineStyle;
        plotSymbol.size          = CGSizeMake(10.0, 10.0);
        boundLinePlot.plotSymbol = plotSymbol;
        
        [_graph addPlot:boundLinePlot];
    复制代码

    首先,添加一个由红到蓝渐变的曲线图 CPTScatterPlot,设置该曲线图的曲线线条颜色为蓝色,宽度为3,标识为 @"Blue Plot",数据源 datasource 为自身。注意:一个图中可以有多个曲线图,每个曲线图通过其 identifier 进行唯一标识。 数据源将在后面介绍。如果我们不仅仅是描绘曲线,还想描绘曲线覆盖的区域,那么就要设置曲线图的区域填充颜色 areaFill,并设置 areaBaseValue。areaBaseValue就是设置该填充颜色从哪个值开始描述,比如本例是从1.0开始描绘(见上图中红色部分开始的位置为 y=1)。在这里我们设置的填充颜色为从红色变到蓝色的渐变色 CPTGradient,CPTGradient默认的变化开始色从x轴左边变化到右边的结束色,如下图所示:

     

    在本例中,将渐变色旋转-90度(即顺时针方向旋转90度),使得红色在下面,蓝色在上面(见说明图)。 对于曲线上的数值点用什么样的符号来表示呢?这就是CPTPlotSymbol 发挥作用的时候了,在这里是用蓝色的实心圆点来表示具体的数值。

    d), 有了蓝红曲线图的介绍,下面再来添加一个破折线风格的绿色曲线图:

    复制代码
    // Create a green plot area: 画破折线
        //
        lineStyle                = [CPTMutableLineStyle lineStyle];
        lineStyle.lineWidth      = 3.f;
        lineStyle.lineColor      = [CPTColor greenColor];
        lineStyle.dashPattern    = [NSArray arrayWithObjects:
                                    [NSNumber numberWithFloat:5.0f],
                                    [NSNumber numberWithFloat:5.0f], nil];
        
        CPTScatterPlot * dataSourceLinePlot = [[CPTScatterPlot alloc] init];
        dataSourceLinePlot.dataLineStyle = lineStyle;
        dataSourceLinePlot.identifier = GREEN_PLOT_IDENTIFIER;
        dataSourceLinePlot.dataSource = self;
        
        // Put an area gradient under the plot above
        //
        CPTColor * areaColor            = [CPTColor colorWithComponentRed:0.3 green:1.0 blue:0.3 alpha:0.8];
        CPTGradient * areaGradient      = [CPTGradient gradientWithBeginningColor:areaColor
                                                                      endingColor:[CPTColor clearColor]];
        areaGradient.angle              = -90.0f;
        areaGradientFill                = [CPTFill fillWithGradient:areaGradient];
        dataSourceLinePlot.areaFill     = areaGradientFill;
        dataSourceLinePlot.areaBaseValue= CPTDecimalFromString(@"1.75");
        
        // Animate in the new plot: 淡入动画
        dataSourceLinePlot.opacity = 0.0f;
        
        CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        fadeInAnimation.duration            = 3.0f;
        fadeInAnimation.removedOnCompletion = NO;
        fadeInAnimation.fillMode            = kCAFillModeForwards;
        fadeInAnimation.toValue             = [NSNumber numberWithFloat:1.0];
        [dataSourceLinePlot addAnimation:fadeInAnimation forKey:@"animateOpacity"];
        
        [_graph addPlot:dataSourceLinePlot];
    复制代码

    上面的代码与前面的红蓝渐变曲线图结构大体相同,只不过在这里使用的市破折线风格的线条,并且没有使用特殊符号对数值点进行描绘。在这里,我们添加了一个有意思的淡入动画。

    至此,描绘相关设置就完成了。先来回顾一下整个步骤:

    a) 在 CPTGraphHostingView 上放置一个 xy 轴图 CPTXYGraph;
    b) 然后对 xy 轴图进行设置,设置其主题,可视空间 CPTPlotSpace,以及两个轴 CPTXYAxis;
    c) 然后在 xy 轴图上添加红蓝渐变的曲线图CPTScatterPlot;
    d) 然后在 xy 轴图上添加绿色破折线曲线图CPTScatterPlot;

    e) 最后,我们来初始化一些演示数据,从而结束 setupCoreplotViews 方法的介绍。

    复制代码
        // Add some initial data
        //
        _dataForPlot = [NSMutableArray arrayWithCapacity:100];
        NSUInteger i;
        for ( i = 0; i < 100; i++ ) {
            id x = [NSNumber numberWithFloat:0 + i * 0.05];
            id y = [NSNumber numberWithFloat:1.2 * rand() / (float)RAND_MAX + 1.2];
            [_dataForPlot addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]];
        }
    复制代码

    5,实现数据源协议

    复制代码
    #pragma mark -
    #pragma mark Plot Data Source Methods
    
    -(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
    {
        return [_dataForPlot count];
    }
    
    -(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
    {
        NSString * key = (fieldEnum == CPTScatterPlotFieldX ? @"x" : @"y");
        NSNumber * num = [[_dataForPlot objectAtIndex:index] valueForKey:key];
        
        // Green plot gets shifted above the blue
        if ([(NSString *)plot.identifier isEqualToString:GREEN_PLOT_IDENTIFIER]) {
            if (fieldEnum == CPTScatterPlotFieldY) {
                num = [NSNumber numberWithDouble:[num doubleValue] + 1.0];
            }
        }
        
        return num;
    }
    复制代码

    和 NSTableView 相似,我们需要提供数据的个数,以及对应x/y轴的数据。至此,编译允许,你就能看到如期的效果:绿色破折线曲线图淡入,然后整个xy轴图就呈现在你面前,并且该图是允许你拖拽的,不妨多拖拽下,以更好地理解 CorePlot 中各种概念属性的含义。

    6,动态修改 CPTPlotSpace 的范围

    为了让例子更有趣一点,在 SetupCoreplotViews 的末尾添加如下代码:

        [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(changePlotRange) userInfo:nil repeats:YES];

    并实现 changePlotRange 方法:

    复制代码
    -(void)changePlotRange
    {
        // Change plot space
        CPTXYPlotSpace * plotSpace = (CPTXYPlotSpace *)_graph.defaultPlotSpace;
        
        plotSpace.xRange = [self CPTPlotRangeFromFloat:0.0 length:(3.0 + 2.0 * rand() / RAND_MAX)];
        plotSpace.yRange = [self CPTPlotRangeFromFloat:0.0 length:(3.0 + 2.0 * rand() / RAND_MAX)];
    }
    复制代码

    四,Core Plot 框架结构分析

    CorePlot 的类结构关系如下:

    其中最核心的就是 CPTGraph,本示例中的 CPTXYGraph是它的子类;一个图 CPTGraph包含一个轴集 CPTAxiset,每个轴集可包含多个轴;一个图 CPTGraph 可包含多个图空间 CPTPlotSpace;一个图 CPTGraph 可包含多个图形CPTSplot(曲线,饼图,柱状图等);图形CPTSplot 和轴都展现在某个图空间 CPTPlotSpace 中。其余的部分,尚未介绍到,暂且不提。

    也许下图能更形象地描述出 Core Plot 各种对象之间的关系。

    五,结语

    Core Plot 的类结构非常清晰,使用起来也很简单,可定制化程度非常高。保守估计国内做矢量图表展示的至少有 90% 以上在用它,曾经做过的一个基金应用就用到它。BTW,吐槽下iOS开发界的浮躁,很多招聘要求都具体到用会用这个库那个库,如加密/解密,解析json/xml,或数据库 sqlite,或图形库Core Plot 或 Three20 什么的。对于有过一定工作经验的程序员来说,学习这些库的使用也不就是一两天的功夫么?当然,对于程序员本身来说,我们不能浮躁地只停留在使用层面上,应该多一点好奇心,钻研下这些库的实现,适用场景,同类库比较等等是大有裨益的。

     

    Cocoa开发

     
    摘要: Core Plot和s7Graph都是可在iOS平台下使用的开源矢量图形库,s7Graph功能相对比较简单一些,在此就不介绍了。Core Plot 功能强大很多,我们可以利用它很方便地画出复杂的曲线图、柱状图和饼图等等。下面我先来介绍如何在项目中配置使用 Core Plot 库,然后通过一个曲线图示例来演示如何使用它,最后结合示例介绍 Core Plot 的框架结构。阅读全文
    posted @ 2013-04-04 13:25 飘飘白云 阅读(311) | 评论 (0) 编辑
     
    摘要: 前面写了一篇博文讲如何在 C# 中使用 ADO 访问各种数据库,在移动开发和嵌入式领域也有一个轻量级的开源关系型数据库-sqlite。它的特点是零配置(无需服务器),单磁盘文件存储数据(就像fopen一样),平台无关性,使用起来简单又高效。这些特点让其非常适合移动开发和嵌入式领域。当然,sqlite 也因其力求简单高效,也就限制了它对并发,海量数据的处理。下面,我就再接再厉,来讲讲如何在 iOS 中使用 sqlite 库和第三方封装库 FMDB,以及介绍一个 MAC 下开源的可视化 sqlite 浏览器。 本文源码:https://github.com/kesalin/iOSSnippet/tree/master/SQLiteDemo阅读全文
    posted @ 2013-03-28 23:45 飘飘白云 阅读(860) | 评论 (0) 编辑
     
    摘要: Per-Vertex 与 Per-Pixel 两种光照的异同:两者都是基于相同的光照原理来进行光照计算的,Per-Vertex 光照计算是在顶点着色阶段进行,然后在光栅化阶段进行线性插值;而 Per-Pixel 光照计算是在片元着色阶段针对每一个像素进行。因此后者要比前者效果更好,看上去更加细致逼真,当然计算量自然也要多一些。 卡通效果是将漫反射因子分级,从而形成不连续的跳跃的漫反射效果。在本文中,是在片元着色阶段进行卡通效果处理的,它也可以在顶点着色阶段进行。 在这个系列的介绍中,只提及了一些简单的光照效果,还有很多更加逼真的光照算法或技巧没有涉及,比如菲涅尔效果或使用光照贴图。阅读全文
    posted @ 2013-01-11 20:52 飘飘白云 阅读(822) | 评论 (6) 编辑
     
    摘要: 在前文《[OpenGL ES 07-1]光照原理》中已经介绍 Opengl 中的光照原理,接下来将演示如何将这些原理用 OpenGL ES 2.0 来实现。今天的这篇文章将介绍 Per-Vertex Light 以及深度缓存,下一篇文章将介绍 Per-Pixel Light 以及卡通效果。还记得在第六篇文章的末尾留了一个小作业,用顶点缓存描绘一个立方体么 Cube?在这篇文章就会用到它。Per-Vertex Light 示例效果如下:阅读全文
    posted @ 2012-12-31 21:12 飘飘白云 阅读(647) | 评论 (0) 编辑
     
    摘要: 在前文《[OpenGL ES 05]相对空间变换及颜色》中讲到人的眼睛捕捉色彩的过程:在光照的作用下,物体表面反射不同频率的光子到人的眼睛中刺激感光细胞从而形成视觉。在那一篇文章中,演示了如何使用颜色,但没有提及光照,在接下来的文章中,我将来详细介绍光的特性,物体的材质属性,光照原理以及在 OpenGL ES 2.0中的应用示例。阅读全文
    posted @ 2012-12-29 21:15 飘飘白云 阅读(897) | 评论 (5) 编辑
     
    摘要: 在前面几篇文章里,顶点数据都是在主存中分配的内存空间,当需要进行渲染时,这些数据便通过 glDrawElements 或 glDrawArrays 从 CPU 主存中拷贝到 GPU 中去进行运算与渲染。这种做法需要频繁地在 CPU 与 GPU 之间传递数据,效率低下,因此出现了 VBO (Vertex Buffer object),即顶点缓存,它直接在 GPU 中开辟一个缓存区域来存储顶点数据,因为它是用来缓存储顶点数据,因此被称之为顶点缓存。我们只会在初始化缓冲区,以及在顶点数据有变化时才需要对该缓冲区进行写操作。使用顶点缓存能够大大较少了CPU-GPU 之间的数据拷贝开销,因此显著地提升了程序运行的效率。阅读全文
    posted @ 2012-12-20 22:32 飘飘白云 阅读(887) | 评论 (2) 编辑
     
    摘要: 前面已经花了两篇文章来讲 3D 变换,可 3D 变换实在不是区区两篇文章能讲的透的,为了尽量将这个话题讲得全面点,在这篇本来讲颜色的文章里再顺带讲讲相对空间变换这个还没有提及的话题。相对空间变换类似于为“本地”坐标到“世界”坐标的变换,就是坐标空间之间的变换。你可以想象下这样一个动作,抬起胳膊同时弯曲手臂,手臂相当于在胳膊的坐标空间中旋转,而胳膊所在空间又相当于在身体或胳膊的坐标空间中旋转。就好像空间是嵌套的,一层套一层,外层会影响里层,里层的变换是相对于外层进行的。此外,还将介绍如何在 OpenGL ES 中使用颜色以及背面剔除。 今天将演示这样一个相对运动与颜色的示例,示例运行效果如下图所示,源码在这里:点此查看阅读全文
    posted @ 2012-12-11 10:42 飘飘白云 阅读(873) | 评论 (0) 编辑
     
    摘要: 在这一篇文章中,介绍了如何通过 3D 变换来实现平移,旋转和缩放,以更好地理解前文中介绍的理论知识;同时也实现了如何通过 UIControl 来控制 OpenGL View 中的物体;此外还详细介绍了描绘图元的模式以及顶点索引模式。在文章的最后,介绍了如何使用 CADisplayLink 来实现动画效果。阅读全文
    posted @ 2012-12-07 22:10 飘飘白云 阅读(1095) | 评论 (0) 编辑
     
    摘要: 本文详细介绍 3D 相关的一些数学知识,如矩阵变换,以及 3D 空间的物体是如何映射到屏幕上去这一整个过程:模型变换,视图变换,投影变换,视口变换。阅读全文
    posted @ 2012-12-06 19:57 飘飘白云 阅读(1307) | 评论 (0) 编辑
     
    摘要: 在前文《[OpenGL ES 01]iOS上OpenGL ES之初体验》中我们学习了如何在 iOS 平台上设置OpenGL ES 环境,主要是设置 CAEAGLLayer 属性,创建 EAGLContext,已经创建 renderbuffer 和 framebuffer,并知道如何清屏。但实际上并没有真正描绘点什么。在本文中,我们将学习OpenGL ES 渲染管线,顶点着色器和片元着色器相关知识,然后使用可编程管线在屏幕上描绘一个简单三角形。 在 OpenGL ES 1.0 版本中,支持固定管线,而 OpenGL ES 2.0 版本不再支持固定管线,只支持可编程管线。什么是管线?什么又是固定管线和可编程管线?管线(pipeline)也称渲染管线,因为 OpenGL ES在进行渲染处理过程中会顺序执行一列操作,这一系列相关的处理阶段就被称为OpenGL ES 渲染管线。pipeline 来源于福特汽车生产车间的流水线作业,在OpenGL ES 渲染过程中也是一样,一个操作接着一个操作进行,就如流水线作业一样,这样的实现极大地提供了渲染的效率。整个渲染管线如下图所示:阅读全文
    posted @ 2012-11-25 22:35 飘飘白云 阅读(550) | 评论 (0) 编辑
     
    摘要: OpenGL ES 是专门为手持设备指定的 3D 规范,它是 OpenGL 的简化版,该规范由khronos.org制定,目前最新规范版本为 3.0。 OpenGL ES 可以在不同手机系统上实现,也可以在浏览器上实现(Web GL)。在这里,我将介绍如何在 iOS 上使用 OpenGL ES,我是OpenGL ES 的初学者,错误之处难免,欢迎各位指出,共同提高。阅读全文
    posted @ 2012-11-24 23:24 飘飘白云 阅读(480) | 评论 (0) 编辑
     
    摘要: KVO 并不是什么新事物,换汤不换药,它只是观察者模式在 Objective C 中的一种运用,这是 KVO 的指导思想所在。其他语言实现中也有“KVO”,如 WPF 中的 binding。而在 Objective C 中又是通过强大的 runtime 来实现自动键值观察的。本文对 KVO 的使用以及注意事项,内部实现都一一做了介绍分析,通过阅读本文可以更深入地理解 KVO。Objective 中的 KVO 虽然可以用,但却非完美,有兴趣的了解朋友请查看《KVO 的缺陷》 以及改良实现 MAKVONotificationCenter 。阅读全文
    posted @ 2012-11-17 17:24 飘飘白云 阅读(970) | 评论 (2) 编辑
     
    摘要: 如果我们在 Objective C 中向一个对象发送它无法处理的消息,会出现什么情况呢?根据前文《深入浅出Cocoa之消息》的介绍,我们知道发送消息是通过 objc_send(id, SEL, ...) 来实现的,它会首先在对象的类对象的 cache,method list 以及父类对象的 cache, method list 中依次查找 SEL 对应的 IMP;如果没有找到且实现了动态方法决议机制就会进行决议,如果没有实现动态方法决议机制或决议失败且实现了消息转发机制就会进入消息转发流程,否则程序 crash。也就是说如果同时提供了动态方法决议和消息转发,那么动态方法决议先于消息转发,只有当动态方法决议依然无法正确决议 selector 的实现,才会尝试进行消息转发。在前文中,我并没有详细讲解动态方法决议,因此本文将详细介绍之。阅读全文
    posted @ 2012-11-14 23:33 飘飘白云 阅读(1115) | 评论 (0) 编辑
     
    摘要: iOS 游戏开发教程资源,主要是 cocos2D阅读全文
    posted @ 2012-11-10 22:49 飘飘白云 阅读(408) | 评论 (0) 编辑
     
    摘要: 这是本人在研究 Cocoa 开发过程中写过的一些文章,涵盖 runtime,class, message,多线程,core data,网络,framework,plugin等各方面,还比较成系列,所以整理出来,贴在这里,希望对大家有帮助。文章错误之处,也希望大家指正。所有文章均遵循“署名-非商业用途-保持一致”创作公用协议。阅读全文
    posted @ 2012-02-19 09:31 飘飘白云 阅读(3278) | 评论 (4) 编辑
     
    摘要: XCode 内置GDB,我们可以在命令行中使用 GDB 命令来调试我们的程序。下面将介绍一些常用的命令 po, print, info, help 等以及调试技巧。阅读全文
    posted @ 2012-01-31 16:02 飘飘白云 阅读(2647) | 评论 (0) 编辑
     
    摘要: 在前文《深入浅出Cocoa之类与对象》一文中,我已经详细介绍了ObjC中的 Class 与 Object 的概念,今天我们来如何在运行 时动态创建类。下面这个函数就是应用前面讲到的Class,MetaClass的概念,在运行时动态创建一个类。这个函数来自《Inside Mac OS X-The Objective-C Programming Language》。阅读全文
    posted @ 2012-01-30 14:02 飘飘白云 阅读(1186) | 评论 (0) 编辑
     
    摘要: 最近打算写一些ObjC中比较底层的东西,尤其是 runtime 相关的。苹果已经将 ObjC runtime 代码开源了,我们可以从:http://opensource.apple.com/source/objc4/objc4-493.9/runtime/ 浏览源代码,或点此下载源代码。 从哪里入手呢?那当然是最基本的类与对象。与C++相比,ObjC中的类与对象结构要简洁与一致得多(参考《深度探索C++对象模型》,你就知道C++中类与对象结构的复杂)。本文将详细讲解ObjC中类与对象的结构,下回将讲如何在 runtime 时操作类。阅读全文
    posted @ 2012-01-19 16:59 飘飘白云 阅读(1465) | 评论 (5) 编辑
     
    摘要: 在前文深入浅出Cocoa之消息中,我简要介绍了ObjC 中消息的基本情况,包括SEL查找,缓存以及消息转发等。在本文中,我要介绍一个很有趣的技术,Method swizzling,通过这个手法,我们可以动态修改方法的实现,从而达到修改类行为的目的。当然,还有其他办法(如 ClassPosing,Category)也可以达到这个目的。ClassPosing 是针对类级别的,是重量级的手法,Category 也差不多,比较重量级,此外 Category 还无法避免下面的递归死循环(如果你的代码出现了如下形式的递归调用,应该考虑一下你的设计,而不是使用在这里介绍的 Method Swizzling 手法,:))。阅读全文
    posted @ 2012-01-05 17:01 飘飘白云 阅读(854) | 评论 (0) 编辑
     
    摘要: Three20 是 facebook 开源的一款功能齐全又强大的库,覆盖 UI,network,JSON/XML解析等。其 github 仓库在这里:https://github.com/facebook/three20 ,这个页面也有如何在工程中添加 three20 库的介绍,不过在 Lion 版下以及 xcode 4.2 下有些许不同,英文好的同学可以参看原文。现整理如下:阅读全文
    posted @ 2011-12-31 17:26 飘飘白云 阅读(400) | 评论 (2) 编辑
     
    摘要: 使用 OCMock 进行 unit test 时,我们无法 stub 或 expect 类方法,那么又该怎样测试类方法呢?下面是一个解决办法:在测试类中的非类方法 wrap 一下类方法,然后测试 wrap 方法。阅读全文
    posted @ 2011-12-27 14:25 飘飘白云 阅读(210) | 评论 (0) 编辑
     
    摘要: XCode 内置了 OCUnit 单元测试框架,但目前最好用的测试框架应该是 GHUnit。通过 GHUnit + OCMock 组合,我们可以在 iOS 下进行较强大的单元测试功能。本文将演示如何在 XCode 4.2 下使用 OCUnit, GHUnit 和 OCMock 进行单元测试。阅读全文
    posted @ 2011-12-23 12:50 飘飘白云 阅读(2463) | 评论 (0) 编辑
     
    摘要: 搜集整理了一些有关申请开发者证书,授权,申请证书,发布应用程序方面的资料,经验证,比较准确,特此保存。 1,申请 IDP 图文教程 2,如何成为一个合格的iOS开发者 3,如何为 iTunes Connect 准备应用 4,如何使用iOS授权以及如何申请证书 5,如何联机调试以及发布程序阅读全文
    posted @ 2011-12-22 20:42 飘飘白云 阅读(274) | 评论 (0) 编辑
     
    摘要: 花了几天的时间,做了一个简陋的 Dicom viewer,这个查看器没有使用 DCMTK 库,而是自己移植了一个 Dicom 文件解析器(Thanks toAmarnath S and his greatpost.)。该Dicom 文件解析器已经开源,源代码在这里 or https://github.com/kesalin/DicomViewer。 贴几张效果图先: Dicom 文件列表阅读全文
    posted @ 2011-11-18 06:34 飘飘白云 阅读(406) | 评论 (1) 编辑
     
    摘要: DCMTK是德国 Offis 公司开发的实现 DICOM 协议的跨平台开源 C++库,在医学领域里是很有名的,它支持Windows ,Linux,Mac OS,SUN等平台。不过貌似在 iOS 平台上编译 DCMTK 的文档很少很少,折腾了好久终于编译成功了,记录下来。阅读全文
    posted @ 2011-11-10 12:41 飘飘白云 阅读(348) | 评论 (0) 编辑
     
    摘要: XCode 4 默认支持 Git 作为代码仓库,当我们新建一个仓库的时候,可以勾选创建默认仓库,只不过这个仓库是在本地的。本文介绍如何在 mac 机器上创建 Git 服务器,总体思路是:使用 gitosis 来简化创建过程,在用作服务器的机器上创建一个名为 git 的账户来创建 git 服务器,其他客户端通过 ssh 机制访问 git 服务器。阅读全文
    posted @ 2011-11-07 16:09 飘飘白云 阅读(389) | 评论 (0) 编辑
     
    摘要: 苹果Cocoa编码规范阅读全文
    posted @ 2011-11-02 16:36 飘飘白云 阅读(593) | 评论 (0) 编辑
     
    摘要: Objective C 的类方法(class method),即 static 方法,那些用 + 修饰的方法。类方法是属于类对象的,所以无需创建类的实例对象我们就可以直接使用它们。使用形式为: [ClassName classMethod]; 在这里 ClassName 代表的就是一个类对象,而不是作为一种类型。类名只有出现接收消息的表达式中才代表一个类对象,其他情况下都表示一种类型。阅读全文
    posted @ 2011-11-01 12:34 飘飘白云 阅读(175) | 评论 (0) 编辑
     
    摘要: 在前文深入浅出 Cocoa 之 Framework中讲解了 Framework,接下来讲解 plugin。如果你对 Framework 还不太熟悉的话,请阅读那篇文中,在本例中使用到了 framework,并在本文中没有详细讲述其创建和使用过程。 本文代码下载:点击这里 为什么要引入插件? 我们知道编译程序时,会连接相关 framework,通常我们所连接的框架是 Foundation 和 Application 框架。当程序启动运行时,每个被连接到的 framework 都会被加载到该程序的 objc 运行时环境中。如果我们想向正在运行的程序加载新的 framework,那该怎么办呢?答案之一就是使用 plugin 机制。cocoa 的 plugin 机制通常由 NSBundle 类来实现,而实现动态加载的功能由函数 objc_addClass 来完成。一般我们无需与 objc_addClass 这个函数打交道,我们使用 NSBundle 来完成绝大部分与 plugin 相关的工作。阅读全文
    posted @ 2011-10-28 13:35 飘飘白云 阅读(460) | 评论 (0) 编辑
     
    摘要: 扩展名 pch 表示 “precompliled header”,即预编译头文件,prefix.pch 为 XCode 工程默认生成的预编译头文件,在其中我们可以定制一些全局的宏,以方便开发。阅读全文
    posted @ 2011-10-16 20:58 飘飘白云 阅读(729) | 评论 (0) 编辑
     
    摘要: Mac OS X 扩展了 framework 的功能,让我们能够利用它来共享代码和资源。framework 在概念上有点像 Window 下的库,但是比库更加强大,通过 framework 我们可以共享所有形式的资源,如动态共享库,nib 文件,图像字符资源以及文档等。系统会在需要的时候将 framework 载入内存中,多个应用程序可以同时使用同一个 framework,而内存中的拷贝只有一份。一个 framework 同时也是一个 bundle,我们可以在 finder 里浏览其内容,也可以在代码中通过 NSBundle 访问它。利用 framework 我们可以实现动态或静态库的功能。与动态/静态库相比,framework 有如下优势: 第一,framework 能将不同类型的资源打包在一起,使之易于安装,卸载与定位; 第二,framework 能够进行版本管理,这使得 framework 能不断更新并向后兼容; 第三,在同一时间,即使有多个应用程序使用同一 framework,但在内存中只有一份 framework 只读资源的拷贝,这减少了对内存的占用阅读全文
    posted @ 2011-10-16 13:43 飘飘白云 阅读(560) | 评论 (0) 编辑
     
    摘要: 最近在研究如何在 Mac 上使用 Silverlight,在这个过程中,找到几种好玩的东西: 第一个是,CSharpPlugin,链接为:http://code.google.com/p/cocoa-sharp-dev/wiki/CSharpPlugin,这个插件很神奇,可以让我们在 XCode 中编写 C#,并在编写的C#中可以调用 Cocoa API,牛吧?可惜的是这个插件很久没有更新了,最后的更新时间为 2007年5月。 第二个是,MonoDevelop,链接为:http://monodevelop.com/,一般我们还需要安装 Moonlight 。我们可以在其中编写具有 Cocoa 界面风格的 C# 程序。这个 IDE 做得非常清爽,并在持续更新中。 第三个是, 使用 Emonic 插件在 Eclipse 上开发,下面将介绍这种方式阅读全文
    posted @ 2011-10-15 14:17 飘飘白云 阅读(106) | 评论 (0) 编辑
     
    摘要: XCode 会自动为新建的工程创建本地 Git 仓库,但是如何为已有的工程创建 Git 仓库呢?Google 到下面这篇文章,贴在下面了。 原文链接:点击这里 其中 ignore文件下载为:https://github.com/github/gitignore/blob/master/Objective-C.gitignore Creating a git repository for an existing Xcode project ∞阅读全文
    posted @ 2011-09-28 15:44 飘飘白云 阅读(166) | 评论 (0) 编辑
     
    摘要: 本文通过使用 Bonjour 实现了一个简单的服务器/客户端聊天程序,演示了 CFSocket,NSNetService/NSNetServiceBrowser, NSInStream/NSOutStream 的用法。 代码下载:点击这里 效果图如下:阅读全文
    posted @ 2011-09-15 21:42 飘飘白云 阅读(1483) | 评论 (8) 编辑
     
    摘要: NSDocument 并无 setTitle 这样设置标题的方法,但有两者途径可以设置 document 的显示名: 其一,NSDocument 有一个 displayName 的方法,该方法默认实现是显示最后与该文档关联文件的名字(不显示无后缀),如果没有文件与之关联,则显示"Untitled",我们可以修改该方法的实现,返回要显示的名称。下面的这个实现,显示其中第一个 windowController 所指 window 的 title 当作文档显示名称。阅读全文
    posted @ 2011-09-08 17:46 飘飘白云 阅读(79) | 评论 (0) 编辑
     
    摘要: 前面讲解了 Core Data 的框架,并完全手动编写代码演示了 Core Data 的运作过程。下面我们来演示如何结合 XCode 强大的可视化编辑以及 Cocoa 键值编码,绑定机制来使用 Core Data。有了上面提到的哪些利器,在这个示例中,我们无需编写 NSManagedObjectModel 代码,也无需编写 NSManagedObjectContext,工程模版在背后为我们做了这些事情。 今天要完成的这个示例,有两个 Entity:StudentEntity 与 ClassEntity,各自有一个名为 name 的 Attribute。其中 StudentEntity 通过一个名为 inClass 的 relationship 与 ClassEntity关联,而 ClassEntity 也有一个名为 students 的 relationship 与 StudentEntity 关联,这是一个一对多的关系。此外 ClassEntity 还有一个名为 monitor 的 relationship 关联到 StudentEntity,表示该班的班长。阅读全文
    posted @ 2011-09-07 16:58 飘飘白云 阅读(406) | 评论 (0) 编辑
     
    摘要: 前面讲解了 Core Data 的框架,并完全手动编写代码演示了 Core Data 的运作过程。下面我们来演示如何结合 XCode 强大的可视化编辑以及 Cocoa 键值编码,绑定机制来使用 Core Data。有了上面提到的哪些利器,在这个示例中,我们无需编写 NSManagedObjectModel 代码,也无需编写 NSManagedObjectContext,工程模版在背后为我们做了这些事情。 今天要完成的这个示例,有两个 Entity:StudentEntity 与 ClassEntity,各自有一个名为 name 的 Attribute。其中 StudentEntity 通过一个名为 inClass 的 relationship 与 ClassEntity关联,而 ClassEntity 也有一个名为 students 的 relationship 与 StudentEntity 关联,这是一个一对多的关系。此外 ClassEntity 还有一个名为 monitor 的 relationship 关联到 StudentEntity,表示该班的班长。 代码下载:阅读全文
    posted @ 2011-09-07 16:44 飘飘白云 阅读(572) | 评论 (0) 编辑
     
    摘要: 前面详细讲解了 Core Data 的框架以及设计的类,下面我们来讲解一个完全手动编写代码使用这些类的示例,这个例子来自苹果官方示例。在这个例子里面,我们打算做这样一件事情:记录程序运行记录(时间与 process id),并保存到xml文件中。我们使用 Core Data 来做这个事情。 示例代码下载:点击这里阅读全文
    posted @ 2011-09-03 23:03 飘飘白云 阅读(518) | 评论 (0) 编辑
     
    摘要: Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂。Core Data 相关的类比较多,初学者往往不太容易弄懂。计划用三个教程来讲解这一部分: 框架详解:讲解 Core data 框架,运作过程,设计的类; Core data应用程序示例:通过生成一个使用 Core data 的应用程序来讲解如何 在 XCode 4 中使用 Core data。 手动创建Core data示例:不利用框架自动生成代码,完全自己编写所有的 Core data 相关代码的命令行应用程序来深入讲解 Core data的使用。 本文为第一部份:框架详解阅读全文
    posted @ 2011-09-01 14:20 飘飘白云 阅读(807) | 评论 (0) 编辑
     
    摘要: block 是 Apple 在 GCC 4.2 中扩充的新语法特性,其目的是支持多核并行编程。我们可以将 dispatch_queue 与 block 结合起来使用,方便进行多线程编程。 本文源代码下载:点击下载阅读全文
    posted @ 2011-08-26 12:03 飘飘白云 阅读(516) | 评论 (0) 编辑
     
    摘要: iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。下面根据抽象层次从低到高依次列出iOS所支持的多线程编程范式: 1, Thread; 2, Cocoa operations; 3, Grand Central Dispatch (GCD) (iOS4 才开始支持) 下面简要说明这三种不同范式: Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread: Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程,那么 NSThread 就是官方推荐优先选用的方式。 POSIX t阅读全文
    posted @ 2011-08-18 14:12 飘飘白云 阅读(755) | 评论 (0) 编辑
     
    摘要: iOS应用程序的生命周期相比 Android 应用程序的生命周期来说,没那么简明易懂,但是也并不复杂。iOS应用程序的生命周期又根据系统是否支持多线程分为两种:不支持多线程的iOS4之前的系统以及支持多线程的iOS4及其之后的系统。阅读全文
    posted @ 2011-08-16 15:04 飘飘白云 阅读(160) | 评论 (0) 编辑
     
    摘要: 在入门级别的ObjC 教程中,我们常对从C++或Java 或其他面向对象语言转过来的程序员说,ObjC 中的方法调用(ObjC中的术语为消息)跟其他语言中的方法调用差不多,只是形式有些不同而已。本文详细深入浅出地讲解了ObjC中消息的方方面面。阅读全文
    posted @ 2011-08-15 17:44 飘飘白云 阅读(750) | 评论 (0) 编辑
     
    摘要: NSString 的 stringByAddingPercentEscapesUsingEncoding 可以对 url 参数进行编码,但是有点小问题,不会对所有需要编码的字符都编码。我们可以通过 CFStringRef 的 CFURLCreateStringByAddingPercentEscapes 函数来封装这个功能。代码如下:阅读全文
    posted @ 2011-08-11 15:21 飘飘白云 阅读(265) | 评论 (0) 编辑
     
    摘要: 前文提到将开发一个美式英语发音的 app,经过半个月的业余开发,version 1.0 终于完成。截图留念。后续将完善单元详细模块,以及语音语法知识模块。阅读全文
    posted @ 2011-08-06 21:08 飘飘白云 阅读(77) | 评论 (0) 编辑
     
    摘要: iOS 中可以通过 NSPredicate 来处理正则表达式。相关资料如下: 在 iOS 中,我们使用 NSPredicate 的字符串比较功能来进行正则表达式处理,其比较关键字为:MATCHES 下面,列举一个匹配6-15个由字母/数字组成的字符串的正则表达式,来看看 NSPredicate 的具体使用:阅读全文
    posted @ 2011-08-04 13:46 飘飘白云 阅读(1569) | 评论 (0) 编辑
     
    摘要: 最近猛补了一会子美式英语音标,音调,连读相关基础知识,收获不少。遂整理相关资料笔记之,也计划做一个这样的 app 方便学习,目前已经动工,希望自己能够坚持做下去。刚开始做,主题导航框架已经完成,秀一些简陋的界面图:阅读全文
    posted @ 2011-07-22 07:44 飘飘白云 阅读(144) | 评论 (0) 编辑
     
    摘要: 有同学在 CocoaChina 上提出这样一个问题:A viewController 中包含一个 B viewController(B 的 view 作为 A 的 view 的 subView),在横竖屏转换时,A 可以得到屏幕旋转相关的消息(如:shouldAutorotateToInterfaceOrientation),而 B 却得不到,即使 A,B 都实现了这些函数。原贴见这里:http://www.cocoachina.com/bbs/read.php?tid=40973&page=1#393765 这个问题我以前也碰到过,稍微研究了一下,其原因是 A 是在 AppDelegate 里 window 的 controller 层次体系中(比如,是 navigation push进去的等等),而 B 只是创建出来,让 A 方便使用其 view 而已,B 并没有加入这个层次体系中( B 的 parentViewController 为 nil,哪怕 B.view.superview 是 A.view)。所以 A 会跟着那个层次体系得到系统旋转相关的消息,而 B 被凉在一边,阅读全文
    posted @ 2011-07-18 23:10 飘飘白云 阅读(127) | 评论 (1) 编辑
     
    摘要: 最近在 iOS 上实现了一套自定义动画库,可以支持任何数值型变量的值的自动动画演示,并支持多种动画效果,效果还是很炫的。比如说你设置了一个偏移变量从50变到100,那么这个变化过程就可以以动画形式进行,而不是常规的一步到位。与 iOS 系统自带的 Animation 相比,我的这套自定义动画库,可配置性更高,使用更简单。用 set 表示有动画的设定值,用 update 表示常规的没有动画的设定值。目前支持的动画类型如下:阅读全文
    posted @ 2011-07-17 21:25 飘飘白云 阅读(136) | 评论 (0) 编辑
     
    摘要: 自定义TableViewCell实现圆角/渐变色TableView:代码实现定制 TableViewCell,用自绘画 cell 的边角,渐变色和阴影,详细实现请下载代码:代码下载:点击这里阅读全文
    posted @ 2011-07-15 07:19 飘飘白云 阅读(333) | 评论 (0) 编辑
     
    摘要: 向 Appstore 里查询已发布App的版本信息,有两种方案,思路都是一样的: 其一:在某个服务器上存储最新发布的版本信息,需要的时候向该服务器查询; 其二:在需要的时候向 appstore 查询; 在这里我来介绍第二种方法:向 appstore 查询应用程序信息,包括作者,版本,app 介绍页面地址等信息。阅读全文
    posted @ 2011-07-14 15:40 飘飘白云 阅读(322) | 评论 (0) 编辑
     
    摘要: 在服务器使用的时区与用户本地时区不一致的情况下,如果需要显示从服务器得来的时间,我们需要进行必要的时区和显示格式转换。 其转换过程为: 获取源(服务器)NSDateFormatter,用这 NSDateFormatter 得 dateFromString 方法获得源时区的时间。 然后计算两个时区的时间偏差量,用这个偏差量加上前面计算得到的源时区时间就得到用户本地时区的时间了。阅读全文
    posted @ 2011-05-27 14:57 飘飘白云 阅读(188) | 评论 (1) 编辑
     
    摘要: XCode 3.2 常用快捷键阅读全文
    posted @ 2011-03-19 21:15 飘飘白云 阅读(110) | 评论 (0) 编辑
     
    分类: Cocoa开发
    标签: iosCore Plot
  • 相关阅读:
    jQuery 选择器
    pf_ring 编译移植
    Android wifi 扫描机制
    wifi 万能钥匙协议
    linux下CJson使用
    libxml -- 解析 XML 文档
    关闭浏览器复制行为
    Ubuntu 语言设置
    Socket编程之非阻塞connect
    Java多维数组
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3000275.html
Copyright © 2020-2023  润新知