iOS——Core Animation 知识摘抄(二)

阴影

主要是shadowOpacity 、shadowColor、shadowOffset和shadowRadius四个属性

shadowPath属性

我们已经知道图层阴影并不总是方的,而是从图层内容的形状继承而来。这看上去不错,但是实时计算阴影也是一个非常消耗资源的,尤其是图层有多个子图层,每个图层还有一个有透明效果的寄宿图的时候。

如果你事先知道你的阴影形状会是什么样子的,你可以通过指定一个shadowPath来提高性能。shadowPath是一个CGPathRef类型(一个指向CGPath的指针)。CGPath是一个Core Graphics对象,用来指定任意的一个矢量图形。我们可以通过这个属性单独于图层形状之外指定阴影的形状。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *layerView1;
@property (nonatomic, weak) IBOutlet UIView *layerView2;
@end
@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//enable layer shadowsself.layerView1.layer.shadowOpacity = 0.5f;self.layerView2.layer.shadowOpacity = 0.5f;
//create a square shadowCGMutablePathRef squarePath = CGPathCreateMutable();CGPathAddRect(squarePath, NULL, self.layerView1.bounds);self.layerView1.layer.shadowPath = squarePath;
CGPathRelease(squarePath);
?//create a circular shadowCGMutablePathRef circlePath = CGPathCreateMutable();CGPathAddEllipseInRect(circlePath, NULL, self.layerView2.bounds);self.layerView2.layer.shadowPath =
circlePath;
CGPathRelease(circlePath); }
@end

如果是一个举行或是圆,用CGPath会相当简单明了。但是如果是更加复杂一点的图形,UIBezierPath类会更合适,它是一个由UIKit提供的在CGPath基础上的Objective-C包装类。

 

图层蒙板

CALayer有一个属性叫做mask可以解决这个问题。这个属性本身就是个CALayer类型,有和其他图层一样的绘制和布局属性。它类似于一个子图层,相对于父图层(即拥有该属性的图层)布局,但是它却不是一个普通的子图层。不同于那些绘制在父图层中的子图层,mask图层定义了父图层的部分可见区域。

mask图层的Color属性是无关紧要的,真正重要的是图层的轮廓。mask属性就像是一个饼干切割机,mask图层实心的部分会被保留下来,其他的则会被抛弃。(如图4.12)

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//create mask layerCALayer *maskLayer = [CALayer layer];maskLayer.frame = self.layerView.bounds;UIImage *maskImage = [UIImage imageNamed:@"Cone.png"];maskLayer.contents = (__bridge id)maskImage.CGImage;//apply mask to image layer?self.imageView.layer.mask = maskLayer;
}
@end

 

CALayer蒙板图层真正厉害的地方在于蒙板图不局限于静态图。任何有图层构成的都可以作为mask属性,这意味着你的蒙板可以通过代码甚至是动画实时生成。

 

组透明

iOS常见的做法是把一个空间的alpha值设置为0.5(50%)以使其看上去呈现为不可用状态。对于独立的视图来说还不错,但是当一个控件有子视图的时候就有点奇怪了,图4.20展示了一个内嵌了UILabel的自定义UIButton;左边是一个不透明的按钮,右边是50%透明度的相同按钮。我们可以注意到,里面的标签的轮廓跟按钮的背景很不搭调。

 

理想状况下,当你设置了一个图层的透明度,你希望它包含的整个图层树像一个整体一样的透明效果。你可以通过设置Info.plist文件中的UIViewGroupOpacity为YES来达到这个效果,但是这个设置会影响到这个应用,整个app可能会受到不良影响。如果UIViewGroupOpacity并未设置,iOS 6和以前的版本会默认为NO(也许以后的版本会有一些改变)。

另一个方法就是,你可以设置CALayer的一个叫做shouldRasterize属性(见清单4.7)来实现组透明的效果,如果它被设置为YES,在应用透明度之前,图层及其子图层都会被整合成一个整体的图片,这样就没有透明度混合的问题了(如图4.21)。

为了启用shouldRasterize属性,我们设置了图层的rasterizationScale属性。默认情况下,所有图层拉伸都是1.0, 所以如果你使用了shouldRasterize属性,你就要确保你设置了rasterizationScale属性去匹配屏幕,以防止出现Retina屏幕像素化的问题。

当shouldRasterize和UIViewGroupOpacity一起的时候,性能问题就出现了(我们在第12章『速度』和第15章『图层性能』将做出介绍),但是性能碰撞都本地化了(译者注:这句话需要再翻译)。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *containerView;
@end
@implementation ViewController
- (UIButton *)customButton
{//create buttonCGRect frame = CGRectMake(0, 0, 150, 50);UIButton *button = [[UIButton alloc] initWithFrame:frame];button.backgroundColor = [UIColor whiteColor];button.layer.cornerRadius = 10;//add labelframe = CGRectMake(20, 10, 110, 30);UILabel *label = [[UILabel alloc] initWithFrame:frame];label.text = @"Hello World";label.textAlignment = NSTextAlignmentCenter;[button addSubview:label];return button;
}
- (void)viewDidLoad
{[super viewDidLoad];//create opaque buttonUIButton *button1 = [self customButton];button1.center = CGPointMake(50, 150);[self.containerView addSubview:button1];//create translucent buttonUIButton *button2 = [self customButton];?button2.center = CGPointMake(250, 150);button2.alpha = 0.5;[self.containerView addSubview:button2];//enable rasterization for the translucent buttonbutton2.layer.shouldRasterize = YES;button2.layer.rasterizationScale = [UIScreen mainScreen].scale;
}
@end

仿射变换

当对图层应用变换矩阵,图层矩形内的每一个点都被相应地做变换,从而形成一个新的四边形的形状。CGAffineTransform中的“仿射”的意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行,CGAffineTransform可以做出任意符合上述标注的变换,图5.2显示了一些仿射的和非仿射的变换:

UIView可以通过设置transform属性做变换,但实际上它只是封装了内部图层的变换。

CALayer同样也有一个transform属性,但它的类型是CATransform3D,而不是CGAffineTransform,本章后续将会详细解释。CALayer对应于UIView的transform属性叫做affineTransform,清单5.1的例子就是使用affineTransform对图层做了45度顺时针旋转。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *layerView;
@end
@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//rotate the layer 45 degreesCGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4);self.layerView.layer.affineTransform = transform;
}
@end

注意我们使用的旋转常量是M_PI_4,而不是你想象的45,因为iOS的变换函数使用弧度而不是角度作为单位。弧度用数学常量pi的倍数表示,一个pi代表180度,所以四分之一的pi就是45度。

C的数学函数库(iOS会自动引入)提供了pi的一些简便的换算,M_PI_4于是就是pi的四分之一,如果对换算不太清楚的话,可以用如下的宏做换算:

#define RADIANS_TO_DEGREES(x) ((x)/M_PI*180.0) 
#define DEGREES_TO_RADIANS(x) ((x)/180.0*M_PI)

混合变换

当操纵一个变换的时候,初始生成一个什么都不做的变换很重要--也就是创建一个CGAffineTransform类型的空值,矩阵论中称作单位矩阵,Core Graphics同样也提供了一个方便的常量:CGAffineTransformIdentity

最后,如果需要混合两个已经存在的变换矩阵,就可以使用如下方法,在两个变换的基础上创建一个新的变换:CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);

我们来用这些函数组合一个更加复杂的变换,先缩小50%,再旋转30度,最后向右移动200个像素(清单5.2)。图5.4显示了图层变换最后的结果。
- (void)viewDidLoad
{[super viewDidLoad]; 
//create a new transformCGAffineTransform transform = CGAffineTransformIdentity;
//scale by 50%transform = CGAffineTransformScale(transform, 0.5, 0.5);
//rotate by 30 degreestransform = CGAffineTransformRotate(transform, M_PI / 180.0 * 30.0);
//translate by 200 pointstransform = CGAffineTransformTranslate(transform, 200, 0);//apply transform to layerself.layerView.layer.affineTransform = transform; }

图5.4中有些需要注意的地方:图片向右边发生了平移,但并没有指定距离那么远(200像素),另外它还有点向下发生了平移。原因在于当你按顺序做了变换,上一个变换的结果将会影响之后的变换,所以200像素的向右平移同样也被旋转了30度,缩小了50%,所以它实际上是斜向移动了100像素。

这意味着变换的顺序会影响最终的结果,也就是说旋转之后的平移和平移之后的旋转结果可能不同。

3D变换

绕Y轴旋转图层

@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//rotate the layer 45 degrees along the Y axisCATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);self.layerView.layer.transform = transform;
}
@end

透视投影

CATransform3D的透视效果通过一个矩阵中一个很简单的元素来控制:m34。m34(图5.9)用于按比例缩放X和Y的值来计算到底要离视角多远。

m34的默认值是0,我们可以通过设置m34为-1.0 / d来应用透视效果,d代表了想象中视角相机和屏幕之间的距离,以像素为单位,那应该如何计算这个距离呢?实际上并不需要,大概估算一个就好了。

因为视角相机实际上并不存在,所以可以根据屏幕上的显示效果自由决定它的防止的位置。通常500-1000就已经很好了,但对于特定的图层有时候更小后者更大的值会看起来更舒服,减少距离的值会增强透视效果,所以一个非常微小的值会让它看起来更加失真,然而一个非常大的值会让它基本失去透视效果,对视图应用透视的代码见清单5.5,结果见图5.10。

@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//create a new transformCATransform3D transform = CATransform3DIdentity;//apply perspectivetransform.m34 = - 1.0 / 500.0;//rotate by 45 degrees along the Y axistransform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);//apply to layerself.layerView.layer.transform = transform;
}
@end

  

消亡点

Core Animation定义了这个点位于变换图层的anchorPoint(通常位于图层中心,但也有例外,见第三章)。这就是说,当图层发生变换时,这个点永远位于图层变换之前anchorPoint的位置。

当改变一个图层的position,你也改变了它的消亡点,做3D变换的时候要时刻记住这一点,当你视图通过调整m34来让它更加有3D效果,应该首先把它放置于屏幕中央,然后通过平移来把它移动到指定位置(而不是直接改变它的position),这样所有的3D图层都共享一个消亡点。

sublayerTransform属性

如果有多个视图或者图层,每个都做3D变换,那就需要分别设置相同的m34值,并且确保在变换之前都在屏幕中央共享同一个position,如果用一个函数封装这些操作的确会更加方便,但仍然有限制(例如,你不能在Interface Builder中摆放视图),这里有一个更好的方法。

CALayer有一个属性叫做sublayerTransform。它也是CATransform3D类型,但和对一个图层的变换不同,它影响到所有的子图层。这意味着你可以一次性对包含这些图层的容器做变换,于是所有的子图层都自动继承了这个变换方法。

相较而言,通过在一个地方设置透视变换会很方便,同时它会带来另一个显著的优势:消亡点被设置在容器图层的中点,从而不需要再对子图层分别设置了。这意味着你可以随意使用position和frame来放置子图层,而不需要把它们放置在屏幕中点,然后为了保证统一的消亡点用变换来做平移。

我们来用一个demo举例说明。这里用Interface Builder并排放置两个视图(图5.12),然后通过设置它们容器视图的透视变换,我们可以保证它们有相同的透视和消亡点,代码见清单5.6,结果见图5.13。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic, weak) IBOutlet UIView *layerView1;
@property (nonatomic, weak) IBOutlet UIView *layerView2;
@end
@implementation ViewController
- (void)viewDidLoad
{[super viewDidLoad];//apply perspective transform to containerCATransform3D perspective = CATransform3DIdentity;perspective.m34 = - 1.0 / 500.0;self.containerView.layer.sublayerTransform = perspective;//rotate layerView1 by 45 degrees along the Y axisCATransform3D transform1 = CATransform3DMakeRotation(M_PI_4, 0, 1, 0);self.layerView1.layer.transform = transform1;//rotate layerView2 by 45 degrees along the Y axisCATransform3D transform2 = CATransform3DMakeRotation(-M_PI_4, 0, 1, 0);self.layerView2.layer.transform = transform2;
}

背面(相当于水平翻转,但其实是。。。)

但这并不是一个很好的特性,因为如果图层包含文本或者其他控件,那用户看到这些内容的镜像图片当然会感到困惑。另外也有可能造成资源的浪费:想象用这些图层形成一个不透明的固态立方体,既然永远都看不见这些图层的背面,那为什么浪费GPU来绘制它们呢?

CALayer有一个叫做doubleSided的属性来控制图层的背面是否要被绘制。这是一个BOOL类型,默认为YES,如果设置为NO,那么当图层正面从相机视角消失的时候,它将不会被绘制。

固体对象

我们把一个有颜色的UILabel放置在视图内部,是为了清楚的辨别它们之间的关系,并且UIButton被放置在第三个面视图里面,后面会做简单的解释。

@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic, strong) IBOutletCollection(UIView) NSArray *faces;
@end
@implementation ViewController
- (void)addFace:(NSInteger)index withTransform:(CATransform3D)transform
{//get the face view and add it to the containerUIView *face = self.faces[index];[self.containerView addSubview:face];//center the face view within the containerCGSize containerSize = self.containerView.bounds.size;face.center = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);// apply the transformface.layer.transform = transform;
}
- (void)viewDidLoad
{[super viewDidLoad];//set up the container sublayer transformCATransform3D perspective = CATransform3DIdentity;perspective.m34 = -1.0 / 500.0;self.containerView.layer.sublayerTransform = perspective;//add cube face 1CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100);[self addFace:0 withTransform:transform];//add cube face 2transform = CATransform3DMakeTranslation(100, 0, 0);transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);[self addFace:1 withTransform:transform];//add cube face 3transform = CATransform3DMakeTranslation(0, -100, 0);transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);[self addFace:2 withTransform:transform];//add cube face 4transform = CATransform3DMakeTranslation(0, 100, 0);transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0);[self addFace:3 withTransform:transform];//add cube face 5transform = CATransform3DMakeTranslation(-100, 0, 0);transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);[self addFace:4 withTransform:transform];//add cube face 6transform = CATransform3DMakeTranslation(0, 0, -100);transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);[self addFace:5 withTransform:transform];
}
@end

从这个角度看立方体并不是很明显;看起来只是一个方块,为了更好地欣赏它,我们将更换一个不同的视角。

旋转这个立方体将会显得很笨重,因为我们要单独对每个面做旋转。另一个简单的方案是通过调整容器视图的sublayerTransform去旋转照相机。

添加如下几行去旋转containerView图层的perspective变换矩阵:

perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0); 
perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);
这就对相机(或者相对相机的整个场景,你也可以这么认为)绕Y轴旋转45度,并且绕X轴旋转45度。现在从另一个角度去观察立方体,就能看出它的真实面貌(图5.21)。

光亮和阴影

如果需要动态地创建光线效果,你可以根据每个视图的方向应用不同的alpha值做出半透明的阴影图层,但为了计算阴影图层的不透明度,你需要得到每个面的正太向量(垂直于表面的向量),然后根据一个想象的光源计算出两个向量叉乘结果。叉乘代表了光源和图层之间的角度,从而决定了它有多大程度上的光亮。

清单5.10实现了这样一个结果,我们用GLKit框架来做向量的计算(你需要引入GLKit库来运行代码),每个面的CATransform3D都被转换成GLKMatrix4,然后通过GLKMatrix4GetMatrix3函数得出一个3×3的旋转矩阵。这个旋转矩阵指定了图层的方向,然后可以用它来得到正太向量的值。

结果如图5.22所示,试着调整LIGHT_DIRECTION和AMBIENT_LIGHT的值来切换光线效果

#import "ViewController.h" 
#import 
#import
#define LIGHT_DIRECTION 0, 1, -0.5 
#define AMBIENT_LIGHT 0.5
@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic, strong) IBOutletCollection(UIView) NSArray *faces;
@end
@implementation ViewController
- (void)applyLightingToFace:(CALayer *)face
{//add lighting layerCALayer *layer = [CALayer layer];layer.frame = face.bounds;[face addSublayer:layer];//convert the face transform to matrix//(GLKMatrix4 has the same structure as CATransform3D)CATransform3D transform = face.transform;GLKMatrix4 matrix4 = *(GLKMatrix4 *)&transform;GLKMatrix3 matrix3 = GLKMatrix4GetMatrix3(matrix4);//get face normalGLKVector3 normal = GLKVector3Make(0, 0, 1);normal = GLKMatrix3MultiplyVector3(matrix3, normal);normal = GLKVector3Normalize(normal);//get dot product with light directionGLKVector3 light = GLKVector3Normalize(GLKVector3Make(LIGHT_DIRECTION));float dotProduct = GLKVector3DotProduct(light, normal);//set lighting layer opacityCGFloat shadow = 1 + dotProduct - AMBIENT_LIGHT;UIColor *color = [UIColor colorWithWhite:0 alpha:shadow];layer.backgroundColor = color.CGColor;
}
- (void)addFace:(NSInteger)index withTransform:(CATransform3D)transform
{//get the face view and add it to the containerUIView *face = self.faces[index];[self.containerView addSubview:face];//center the face view within the containerCGSize containerSize = self.containerView.bounds.size;face.center = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);// apply the transformface.layer.transform = transform;//apply lighting
    [self applyLightingToFace:face.layer];
}
- (void)viewDidLoad
{[super viewDidLoad];//set up the container sublayer transformCATransform3D perspective = CATransform3DIdentity;perspective.m34 = -1.0 / 500.0;perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0);perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);self.containerView.layer.sublayerTransform = perspective;//add cube face 1CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100);[self addFace:0 withTransform:transform];//add cube face 2transform = CATransform3DMakeTranslation(100, 0, 0);transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);[self addFace:1 withTransform:transform];//add cube face 3transform = CATransform3DMakeTranslation(0, -100, 0);transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);[self addFace:2 withTransform:transform];//add cube face 4transform = CATransform3DMakeTranslation(0, 100, 0);transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0);[self addFace:3 withTransform:transform];//add cube face 5transform = CATransform3DMakeTranslation(-100, 0, 0);transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);[self addFace:4 withTransform:transform];//add cube face 6transform = CATransform3DMakeTranslation(0, 0, -100);transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);[self addFace:5 withTransform:transform];
}
@end

点击事件

你应该能注意到现在可以在第三个表面的顶部看见按钮了,点击它,什么都没发生,为什么呢?

这并不是因为iOS在3D场景下正确地处理响应事件,实际上是可以做到的。问题在于视图顺序。在第三章中我们简要提到过,点击事件的处理由视图在父视图中的顺序决定的,并不是3D空间中的Z轴顺序。当给立方体添加视图的时候,我们实际上是按照一个顺序添加,所以按照视图/图层顺序来说,4,5,6在3的前面。

即使我们看不见4,5,6的表面(因为被1,2,3遮住了),iOS在事件响应上仍然保持之前的顺序。当试图点击表面3上的按钮,表面4,5,6截断了点击事件(取决于点击的位置),这就和普通的2D布局在按钮上覆盖物体一样。

你也许认为把doubleSided设置成NO可以解决这个问题,因为它不再渲染视图后面的内容,但实际上并不起作用。因为背对相机而隐藏的视图仍然会响应点击事件(这和通过设置hidden属性或者设置alpha为0而隐藏的视图不同,那两种方式将不会响应事件)。所以即使禁止了双面渲染仍然不能解决这个问题(虽然由于性能问题,还是需要把它设置成NO)。

这里有几种正确的方案:把除了表面3的其他视图userInteractionEnabled属性都设置成NO来禁止事件传递。或者简单通过代码把视图3覆盖在视图6上。无论怎样都可以点击按钮了(图5.23)。

转载于:https://www.cnblogs.com/lihaiyin/p/4450663.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Blazor University (11)组件 — 替换子组件的属性

原文链接:https://blazor-university.com/components/replacing-attributes-on-child-components/替换子组件的属性源代码[1]到目前为止,我们已经了解了如何创建代码生成的属性[2],以及如何捕获意外参数[3]。除了这两种技术之外,B…

HTTPS实现原理

HTTPS实现原理 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL。其所用的端口号是443。…

C#使用ServiceController控制windows服务

C#中,使用ServiceController类控制windows服务,使用之前要先添加引用:System.ServiceProcess,然后在命名空间中引用:using System.ServiceProcess。下面举例获取本机的所有已安装的Windows服务和应用,然后查找某一应用活服务是否已经安装。 代码: using System; using S…

电信aep平台是什么意思_江苏天鼎证券:股票平台跳水是什么意思?股票为什么会跳水?...

相信很多新手在刚玩股票的时候会遇到很多的专业的基础知识不能理解,比如什么是跳水?为什么会跳水呢?接下来就为大家详细来说股票的跳水以及为何会跳水。一、股票平台跳水是什么意思?股票跳水通常指股价在较短的时间内,出现从高位下降到低位的现象。出…

mysql mgr简介_MySQL Group Replication(MGR)使用简介与注意事项

MySQL Group Replication(MGR)是MySQL官方在5.7.17版本引进的一个数据库高可用与高扩展的解决方案,以插件形式提供。MGR基于分布式paxos协议,实现组复制,保证数据一致性。内置故障检测和自动选主功能,只要不是集群中的大多数节点都…

python beautifulsoup4 table tr_python BeautifulSoup解析表

牧羊人nacy这是通用的工作示例(表数据)标记。它返回带有内部列的行的列表。第一行仅接受一个(表头/数据)。def tableDataText(table): rows [] trs table.find_all(tr) headerow [td.get_text(stripTrue) for td in trs[0].find_all(th)] # header row i…

clob字段怎么导出_Oracle 11g及12c+版本下为啥有些表不能exp导出?

【引言】今天有同事问了一个问题,在Oracle 11g下,为啥exp方式导出一个用户的数据表,在imp后却发现有些表并没有迁移过来。经查阅官方文档,发现和Oracle11g及12c 版本相对于10g,有一个新特性deferred_segment_creation(…

C# 读写二进制文件

读写二进制文件的一种选择是直接使用流类型;在这种情况下,最好使用字节数组执行读写操作。另一个选择是使用为这个场景定义的读取器和写入器:BinaryReader和BinaryWriter。使用它们的方式类似于使用 StreamReader 和 StreamWriter&#xff0c…

推荐系统(1)--splitting approaches for context-aware recommendation

开篇语: 大一的时候。在实验室老师和师兄的带领下。我開始接触推荐系统。时光匆匆,转眼已是大三,因为大三课甚是少。于是便有了时间将自己所学的东西做下总结。第一篇博客。献给过去三年里带我飞的老师和师兄们,感谢你们的无私帮助…

python 百度云文字识别 proxy_python使用百度文字识别功能方法详解

介绍python使用百度智能去的文字识别功能,可以识别截图中的文,登陆路验证码等等。, 登陆百度智能云,选择产品服务。选择“人工智能”---文字识别。点击创建应用。 如图下面有关于“文字识别”的各类信息,如通用文字识别…

Android性能优化典范(转)

本文转自:http://hukai.me/android-performance-patterns/ 2015新年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App。课程专题不仅仅介绍了Andr…

Xamarin效果第二十一篇之GIS中可扩展浮动操作按钮

在前面文章中简单玩了玩GIS的基本操作、Mark相关、AR、测距和加载三维白模,今天再次对操作栏又一次修改了,直接放到了右下角可伸缩效果;啥也不说了都在效果里:添加支持圆角 ContentView:Xamarin.Forms.PancakeView再来Xamarin 社区工具包:Xamarin.CommunityToolkit再来看看最终…

【新版发布】ComponentOne 新增 .NET 6 和 Blazor 平台控件支持

ComponentOne Enterprise是葡萄城推出的一款内置 300 多种开发控件的 .NET控件集,可满足 WinForm、WPF、Blazor、ASP.NET MVC 等平台下的系统开发需求,提供表格数据管理、数据可视化、报表和文档等功能,被开发人员誉为“.NET开发的‘瑞士军刀…

Ruby如何成长成高性能系统构架

为什么80%的码农都做不了架构师?>>> 结束了一份Ruby为主的工作,想把个方面总结一下,这篇是关于系统性能方面的.以下数据都是简单回忆的数据,加之企业保密数据的需要,和精确数有些出入,仅供参考. 说起Ruby的性能,无论从官方到社区,都公认是劣于其它的框架…

ArcGIS 10.2数字化线状要素时自动拼接成一条线

(1)在已有线的基础上自动连接成一条线 数字化时,经常会碰到这种情况,不小心双击了,或者画到一半饿了,双击完成去吃饭了,回来继续画,该怎样去做呢? 一开始一直和捕捉和经典…

设置tableView的分割线从最左端开始

苹果原生的tableView的cell分割线默认是没有从最左端开始,有时候这样不免影响美观,有时也会有这样的需求,设置tableView的分割线从最左端开始: 不多说了,直接上代码吧: //分割线从顶端开始 --------适配iO…

java 定时 spring_Spring定时任务实现与配置(一)

朋友的项目中有点问题。他那边是Spring架构的,有一个比较简单的需要定时的任务执行。在了解了他的需求之后,于是提出了比较简单的Springquartz的实现方式。注意本文只是讨论,在已搭建完毕的Spring工程下,完成最简单的定时任务。第…

内核同步机制

内核中用于临界区保护下的互斥机制,它包括自旋锁、原子操作和信号量,三者保证了对临界资源访问的互斥型。 1.1 内核中的互斥机制 1.1.1 自旋锁 自旋锁用在多个CPU系统中。当一个线程在一个CPU上正使用资源,而另一个线程在另一个CPU上正忙等待…

makefile运行_NVDIA TX2入门 系列之三:运行Yolov3

上篇TX2安装完成OpenCV 3.4.0之后,基本软件包已经安装完成,本篇开始安装并运行大名鼎鼎的号称速度最快的目标识别分类算法Yolov3。Yolov3 是啥啊Yolov3是一款基于darknet深度学习框架的目标检测开源项目,目前已经发展到第3版本,即…

C#实现树的双亲表示法

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace 树的实现 {public partial class Form1 : Form{public Form1(){Init…