群晖上的Docker是个很好用的功能,本人也使用Docker安装了不少程序,总体来说使用还是很方便的。

但是最近冒出了一个问题:Docker里面的程序如果有新版本了要如何更新呢?

搜罗了一圈百度,结果没找到什么有价值的东西,果然百度一下,什么都不知道。最后还是用Google找到了办法,总结了两个办法:

第一个,笨办法:把下载的镜像删掉,容器也删掉,重新下载,保证是最新的;

第二个,保留容器的设置:首先在群晖的web页面上把docker里需要更新的程序停止,然后用命令docker pull <repo>更新要更新的程序,完事后回到页面上选中该程序后,点击操作->清除,清理里面的数据(事实证明,这一步必须要做,否则会无效),最后启动该容器,里面的程序就会是最新版本的了

在使用群晖自带的Audio Station的时候,发现右下角有均衡器EQ的图标:

但是这个图标….居然是灰色的不能点!

尝试过各种方法,然而并不能开启EQ。明明官网上写的是有的哇!

等等。。USB speakers,USB speakers,USB speakers…….

原来这玩意TMD只能在使用USB speakers的时候才有用啊!

为了确认这点,翻了翻官方的knowledgebase ,然后找到了下面这段:

这回是写的清清楚楚的了,看来除了使用USB speakers以外,EQ均衡器都是无法使用的!

 

一、什么是VHD

VHD 是Microsoft Virtual Hard Disk format(微软虚拟磁盘文件)的简称。可以由Microsoft Virtual PC 2007,Windows VistaWindows 7/8,Hyper-VWindows Server 2008 R2/2012,Microsoft Virtual Server 2005等创建,Virtual BoxVMWare等可以挂载使用。

VHD文件格式可以被压缩成单个文件存放在宿主机器的文件系统上,主要包括虚拟机启动所需系统文件

二、VHD文件类型

VHD虚拟硬盘有固定VHD、动态VHD 、差异VHD和链接硬盘四种类型,我们可以根据自己的实际需求去选择相应的格式,但在Windows7中只有固定VHD和动态VHD两种类型。

  • 固定VHD:对已分配的大小不会更改。
  • 动态VHD:大小与写入的数据大小相同,并随着数据的写入而相应增加直到达到大小上限。动态VHD上限为2,040 GB。
  • 差异 VHD :与动态VHD 类似,但只包含所关联父VHD修改后的磁盘块。差异VHD的上限为2,040 GB。
  • 链接硬盘VHD:文件本身指向一个磁盘或者一个分区。

VHD的优点:

  1. 维护简单:VHD磁盘操作时就跟物理磁盘一样,维护起来较为简单,我们可以对它进行分区、格式化、压缩、删除等等操作,这些操作并不影响物理分区。这种操作更有利于初学者反复试验分区、格式等功能。
  2. 像U盘一样加载自如:当你对VHD分区写入一些重要数据后,并不想他人修改其中的内容时,我们可以随时将此VHD进行脱机或分离操作,在需要的时候再将它附加进来修改。同样可以向U盘一样从“安全删除硬件并弹出媒体”中弹出某个VHD。
  3. 轻松备份:备份时我们仅仅需要将创建的VHD文件进行备份,它所包含的分区中所内容便被统一备份,当然我们也可以用备份工具将VHD文件所在的整个物理分区进行备份,这样不用说VHD分区中的内容也被纳入其中了。(其实Windows7和Windows2008的Backup工具备份产生的主文件也是VHD格式)
  4. 迁移方便:当我们有一个VHD文件需要在多台计算机上使用时,我们只要先将此VHD分离开来,将其复制到目的计算机上,再进行附加上去即可。同时我们可以通过服务器进行分发,使用脚本将其附加到目的机。当然在物理机与虚拟机之间迁移也是没问题的。
  5. 与虚拟机互相通用:Windows7和Windows2008 R2的VHD文件与VPC、Hyper-V的虚拟硬盘是互通的,我们可以将虚拟机中的VHD文件附加到Windows7和Windows2008 R2中。反过来Windows7和Windows2008 R2中的VHD在分离后也可以挂载到VPC和Hyper-V中。
  6. 可直接用于系统部署:我们可以使用Imagex工具将已经捕获的映像释放到此放,或通过WDS服务器部署系统到VHD。
  7. 双重的安全保护:由于VHD创建时产生的是一个存储文件,在这里我们便可以对此文件和VHD的分区进行不同的权限限制,这样即可以对分区读写权限进行设置保证部分人员有往VHD分区中存储数据的权限,也可以对此VHD文件设置读写权限保证此文件在分离后不被他人给删除。

三、什么是VHDX

随着虚拟环境的企业工作负荷的增加以及性能要求的提高,虚拟硬盘 (VHD) 格式需要适应这些变化。Windows Server 2012 中的 Hyper-V 引入了一个新版本的 VHD 格式,称为 VHDX,它在设计上可以处理当前以及将来的工作负荷。
与旧的 VHD 格式相比,VHDX 具有更大的存储容量。它还在电源故障期间提供数据损坏保护并且优化动态磁盘和差异磁盘的结构对齐方式,以防止在新的大型扇区物理磁盘上性能降级。

四、VHDX的特性和功能

VHDX 格式的主要新功能如下:

  • 支持的虚拟硬盘的存储容量高达 64 TB。
  • 通过记录对 VHDX 元数据结构的更新,可以在电源发生故障时保护数据不会被损坏。
  • 改进了虚拟硬盘格式的对齐方式,可在大型扇区磁盘上更好地工作。
VHDX 格式还提供以下功能:
  • 动态磁盘和差异磁盘较大的数据块大小,可让这些磁盘满足工作负荷的需求。
  • 一个 4 KB 的逻辑扇区虚拟磁盘,可以在为 4 KB 扇区设计的应用程序和工作负荷使用该磁盘时提供较高的性能。
  • 能够存储有关用户可能想记录的文件的自定义元数据,如操作系统版本或应用的修补程序。
  • 高效地表示数据(也称为“剪裁”),使文件大小更小并且允许基础物理存储设备回收未使用的空间。(剪裁需要直接连接到虚拟机或 SCSI 磁盘的物理磁盘以及与剪裁兼容的硬件。)

五、兼容性

VHD:Windows XP以及更早的操作系统均不能直接挂载

VHDX:Windows 8 / Windows Server 2012引入了VHDX的格式,Windows 7以及更早的操作系统均不能直接挂载使用

挂载方式:自Windows 8 / Windows Server 2012 系统开始,可以直接双击VHD/VHDX进行挂载。一些第三方软件也提供了挂载VHD/VHDX的功能,如:如何在XP中挂载VHD 

不知道什么是VHD/VHDX的,请移步:VHD/VHDX科普文

固定VHD/VHDX在创建之后就直接在磁盘上占用了该文件设定的大小,性能较好;动态vhd/vhdx文件一开始占用磁盘空间小,但是在长时间写入后会不停的增大。即使你删除了其中的文件,虚拟磁盘文件所占用的磁盘物理空间也不会因此自动释放。本文的目的就是把这些空间释放出来。

注意:VHD/VHDX的磁盘分区格式如果是exFat,那么下面的方法是没有太大效果的!如果是NTFS则基本可以完全释放!(之前建立了一个簇大小是512的exFat分区发现磁盘空间回收不能,随后转用NTFS就可以了)

测试环境:windows 10 1609 x64,以下是详细步骤(参考自:https://linhost.info/2011/01/windows-how-to-compact-a-dynamic-vhd/

1.打开cmd,需要使用管理员权限,调用diskpart命令

diskpart

2.选择要处理的vhd/vhdx文件

select vdisk file="<vhd/vhdx文件的路径>"

3.以只读方式附加这个磁盘

attach vdisk readonly

4.使用压缩命令

compact vdisk

5.压缩完成之后进行分离

detach vdisk

经过上述操作之后,文件理论上就会变小了!

一、一般在代码中的调用,要么通过id找到,要么直接new出来:

①、调用setTextSize(<数值单位>,<值>)

这里的数值单位可以为下列的几种:

TypedValue.COMPLEX_UNIT_PX
TypedValue.COMPLEX_UNIT_DIP
TypedValue.COMPLEX_UNIT_SP

当然还有不常用的,比如

TypedValue.COMPLEX_UNIT_PT

1 .如果直接使用固定的数值,那么该数值的单位则由上述的几种枚举决定,比如:

setTextSize(TypedValue.COMPLEX_UNIT_SP,16);//就是设置为16sp的大小

2 .如果使用资源文件中的数值,那么请注意,数值单位 要设置为 COMPLEX_UNIT_PX,比如:

setTextSize(TypedValue.COMPLEX_UNIT_PX,getResources().getDimensionPixelSize(R.dimen.你的资源);

 原因如下

* 获取dimension的方法有几种,区别不大
* 共同点是都会将dp,sp的单位转为px,px单位的保持不变
*
* getDimension() 返回float
* getDimensionPixelSize 返回int 小数部分四舍五入
* getDimensionPixelOffset 返回int,但是会抹去小数部分

getDimensionPixelSize在要求不高的情况下也可以替换为getDimensionPixelSize或者getDimensionPixelOffset,具体根据业务需求决定

②、调用setTextSize(<Size>):

这个方法不带单位,Doc的描述如下:

Set the default text size to the given value, interpreted as “scaled pixel” units. This size is adjusted based on the current density and user font size preference.

大意就是,Size单位是px且当设置为某个值的时候,最后会乘一个destiny后显示出来

没例子,也不建议用

二、自定义控件中调用:

①、使用paint直接画TextView:

调用paint.setTextSize(<px值>)即可

②、在declare-styleable中定义size,在xml中设置size,代码中通过TypedArray取出来:

这是比较常见的情况,此时通过调用TypedArray的对象调用getDimension,getDimensionPixelSize 或者getDimensionPixelOffset 方法来获取。同样的,返回结果是以px为单位的

然后,同(一)里面的做法,设置大小即可

继续阅读

前几天遇到一个问题,将uint32_t类型的值放到字典里面传递到下一个vc中。就这么个简单的问题,却踩进了坑。

由于之前主攻java,想当然的就将uint32_t转换成NSString然后丢到下一个vc中,然后要使用的时候再转回uint32_t,然后问题就出现了:转回uint32_t后发现数值不正确。

下面是之前的转换方式:

//uint32_t --> NSString
uint32_t a=2373916479;
NSString * aStr=[NSString stringWithFormat:@"%u",a];//这个没毛病,确实变成了字符串
//NSString --> uint32_t
uint32_t b=[aStr intValue];//这句话有问题

通过上面的代码执行后发现a和b的值不一样,惊到我了!

通过查询uint32_t的定义,发现这货就是unsigned int。然后再回来看代码,觉得没问题哇。。。

然后再转念一想,它是无符号的int,直接转数值会有损。于是将最后一句改成:

uint32_t b=[aStr longLongValue];

虽然执行结果正确了,但是xcode提示了一个警告:

Implicit conversion loses integer precision:'long long' to 'uint32_t' (aka 'unsigned int')

虽然能解决问题,但是这个警告实在是看的很不爽,而且实现起来比较暴力。怎样才能更加优雅的解决目前的困扰呢?

搜索了StackOverflow,突然发现可以把uint32_t放到NSNumber中,再放到字典里面,于是:

//uint32_t --> NSNumber
uint32_t a=2373916479;
NSNumber * aNumber=[NSNumber numberWithUnsignedInt:a];//用NSNumber包裹uint32_t,这样就能放到字典中了
//NSNumber --> uint32_t
uint32_t b=[aNumber unsignedIntValue];//结果正确

经过上面的实践之后,总结一下:

  1. 一切都是基础不扎实导致的
  2. uint32_t本质是unsigned int,如果先转化为字符串再用intValue转回来就会有可能出现数据不正确的情况,而且NSString也没有提供unsingedIntValue,所以使用NSString不明智;
  3. NSNumber是一个可以放到字典和数组中的类型。如果需要再字字典或者数组中存放基本数据类型,可以把所需要的基本数据类型转化为NSNumber后再存入

最近有这么个给图片加水印的需求,把网上的方法基本都试了个遍,最后也就发现一个简单的方法比较可靠。改造了一下,变成了下面这样的:

#define UIColorFromHex(s)  [UIColor colorWithRed:(((s & 0xFF0000) >> 16))/255.0 green:(((s &0xFF00) >>8))/255.0 blue:((s &0xFF))/255.0 alpha:1.0]
-(UIImage *)watermarkImage:(UIImage *)img withName:(NSString *)name
{
    NSString* mark = name;
    const NSString * copyRight=@"©2017 测试公司.All rights reserved.";
    int w = img.size.width;
    int h = img.size.height;
    UIGraphicsBeginImageContext(img.size);
    [img drawInRect:CGRectMake(0, 0, w, h)];
    UIFont * font=[UIFont systemFontOfSize:64];
    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowColor = UIColorFromHex(0x666666);
    shadow.shadowBlurRadius = 5;
    shadow.shadowOffset = CGSizeMake(1, 3);
    NSDictionary *attr_mainContent = @{
                           NSFontAttributeName: font,  //设置字体
                           NSForegroundColorAttributeName: [UIColor cyanColor] ,  //设置字体颜色
                           NSShadowAttributeName:shadow,
                           NSVerticalGlyphFormAttributeName:@0
                           };
    NSDictionary *attr_copyRight = @{
                                       NSFontAttributeName: font,  //设置字体
                                       NSForegroundColorAttributeName: [UIColor whiteColor] ,  //设置字体颜色
                                       NSBackgroundColorAttributeName:[UIColor grayColor]
                                       };
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
    CGSize main_Size1 = [name boundingRectWithSize:CGSizeMake(MAXFLOAT, 0.0) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;
    CGSize main_Size2 = [name boundingRectWithSize:CGSizeMake(w, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;

    CGSize copyRight_Size1 = [copyRight boundingRectWithSize:CGSizeMake(MAXFLOAT, 0.0) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;
    CGSize copyRight_Size2 = [copyRight boundingRectWithSize:CGSizeMake(w, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;

    //=======
    //draw main text
    [mark drawInRect:CGRectMake(20, h - 20 - main_Size2.height - copyRight_Size2.height, main_Size1.width, main_Size2.height) withAttributes:attr_mainContent];//左下角
    //=======
    //draw copy right text
    //copyRight
    [copyRight drawInRect:CGRectMake(0, h - copyRight_Size2.height , copyRight_Size1.width, copyRight_Size2.height) withAttributes:attr_copyRight];//左下角

    UIImage *aimg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return aimg;
}

效果如下:(iPhone 7Plus的大小)

我在这里面加入了两段水印,上面的是要加入的信息,下面是版权信息。

NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
CGSize main_Size1 = [name boundingRectWithSize:CGSizeMake(MAXFLOAT, 0.0) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;
CGSize main_Size2 = [name boundingRectWithSize:CGSizeMake(w, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:dic context:nil].size;

这一段代码用来获取要添加的水印字符的宽度和高度。main_Size1的width就是文本的宽度,main_Size2的height就是文本的高度。这里踩过一个坑,之前照抄网上的获取宽度和高度的代码,发现添加上去的水印文字总是显示不全,后来测试了才发现,需要指定一个宽度,假设为x,这样获取到的高度是文本最大宽度为x的情况下对应的高度(汗颜,仔细想想确实应该是这样)。如果将文本的宽度指定为图片的宽度的话,那么基本可以保证文字的正常显示。

[mark drawInRect:CGRectMake(20, h - <height>, <width>, <height>) withAttributes:<Your Attr>];

这一段是最核心的部分,用于将文本绘制到图片上。可以绘制到由UIGraphicsBeginImageContext指定的区域中的任意位置。代码中我设置绘制区域为整个图片,水印设置在左下角。

这里有一个Attributes参数,是一个属性数组。其中可用的属性如下:

  • NSKernAttributeName:设置字符间距,取值为 NSNumber 对象(整数),正值间距加宽,负值间距变窄
  • NSFontAttributeName:设置文本的字体,参数为UIFont对象
  • NSForegroundColorAttributeName:设置文本的颜色,参数为UIColor
  • NSParagraphStyleAttributeName:设置段落格式。参数为NSMutableParagraphStyle或者NSParagraphStyle对象。例如:
    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
    paragraph.alignment = NSTextAlignmentCenter;//居中
  • NSBackgroundColorAttributeName:设置文本的背景颜色,参数为UIColor
  • NSStrokeWidthAttributeName:设置文本的描边宽度。

    这个属性所对应的值是一个 NSNumber 对象(小数)。该值改变描边宽度(相对于字体size 的百分比)。默认为 0,即不改变。正数只改变描边宽度。负数同时改变文字的描边和填充宽度。例如,对于常见的空心字,这个值通常为3.0。

    如果同时设置了空心的两个属性,并且NSStrokeWidthAttributeName属性设置为整数,那么文字前景色就无效果了

  • NSStrokeColorAttributeName:设置文本的描边颜色
  • NSStrikethroughStyleAttributeName:设置删除线。参数为数字。例如:NSStrikethroughStyleAttributeName:@3 表示删除线的宽度为3
  • NSUnderlineStyleAttributeName:添加下划线。参数为枚举类型。可用的类型如下:

    NSUnderlineStyleNone

    NSUnderlineStyleSingle   

    NSUnderlineStyleThick

    NSUnderlineStyleDouble

    设置单下划线:NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle)

  • NSUnderlineColorAttributeName:设置下划线颜色,参数为UIColor
  • NSShadowAttributeName:设置阴影效果,参数为NSShadow对象。注意这个属性必需和这三个属性NSVerticalGlyphFormAttributeName,NSObliquenessAttributeName和NSExpansionAttributeName之一同时使用才能生效,否则将无效。

    关于NSShadow的用法,如下:

    NSShadow *shadow = [[NSShadow alloc] init];//初始化
    shadow.shadowColor = [UIColor grayColor];//设置阴影颜色
    shadow.shadowBlurRadius = 2;//模糊程度,值越大越模糊
    shadow.shadowOffset = CGSizeMake(2, 4);//阴影的位置。如:设置为CGSizeMake(0, 0)则会直接叠加到文本后方;CGSizeMake(0, 4)则是出现在文本的下方
  • NSVerticalGlyphFormAttributeName:该属性所对应的值是一个 NSNumber 对象(整数)。0 表示横排文本。1 表示竖排文本。在 iOS 中,总是使用横排文本,0 以外的值都未定义。
  • NSObliquenessAttributeName:设置字体倾斜,参数为NSNumber 0或1
  • NSExpansionAttributeName:设置文本扁平化(个人感觉很丑,而且还会影响文本的宽度计算),参数为NSNumber 0或1
  • NSTextEffectAttributeName:设置文本特殊效果,取值为 NSString 对象,目前只有图版印刷效果可用
  • NSBaselineOffsetAttributeName:设置基线偏移值,取值为 NSNumber (float),正值上偏,负值下偏
  • NSWritingDirectionAttributeName:设置文字书写方向,从左向右书写或者从右向左书写。以下是API中的说明:

    NSNumbers representing the nested levels of writing direction overrides as defined by Unicode LRE, RLE, LRO, and RLO characters. The control characters can be obtained by masking NSWritingDirection and NSWritingDirectionFormatType values.

    LRE: NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding
    RLE: NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding
    LRO: NSWritingDirectionLeftToRight|NSWritingDirectionOverride
    RLO: NSWritingDirectionRightToLeft|NSWritingDirectionOverride

  • NSLinkAttributeName:设置链接属性,取值为NSURL对象。点击后调用浏览器打开指定URL地址
  • NSAttachmentAttributeName:设置文本附件,取值为NSTextAttachment对象,常用于文字图片混排

基本就以上这些属性

PS:UILabel也是可以设置以上属性,只是代码不一样而已。关于这个可以参考:http://www.jianshu.com/p/6665c088bd01

之前考虑用MMPopupView来实现弹出式对话框,不得不说这个弹出的效果还是很不错的,可惜我发现使用xib来绘图还是有点问题的,所以想了个另类的办法:弹出一个模态的view controller来充当对话框。

成功实现之后,发现无法改变背景透明度,即弹出动画显示的过程中背景是有透明色的,动画过后就变成不透明了。于是在网上搜索到了这样的解决办法:

参考:http://www.jianshu.com/p/4f7a29bb333f

AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate];

UIViewController *vc = [[UIViewController alloc]init];//这里写你要弹出的vc

appdelegate.window.rootViewController.definesPresentationContext = YES;

view.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[appdelegate.window.rootViewController presentViewController:vc animated:YES completion:^{

vc.view.backgroundColor=[UIColor colorWithRed:237/255.0 green:236/255.0 blue:244/255.0 alpha:0.5];//这里写你需要的颜色,或者透明度

}];

这样基本上就可以了。如果要更加完美的话,可以修改弹出动画的背景透明度,和上述的颜色一致,这样就可以让弹出效果更自然

本文原引出处:http://wpchina.org/how-to-change-wordpress-domain-prefectly-1528/

UPDATE wp_options SET option_value = replace(option_value, ‘<你的旧域名>’,'<新域名>’) ;
UPDATE wp_posts SET post_content = replace(post_content, ‘<你的旧域名>’,'<新域名>’) ;
UPDATE wp_comments SET comment_content = replace(comment_content, ‘<你的旧域名>’, ‘<新域名>’) ;
UPDATE wp_comments SET comment_author_url = replace(comment_author_url, ‘<你的旧域名>’, ‘<新域名>’) ;

上文中是基于phpMySql的,其中有几个注意要点:

0.写在前面:数据库要备份要备份要备份!万一操作失误,那损失就大了

1.一定要选中数据库之后,再去点击右侧上方的SQL选项卡

2.UPDATE 后面的是表的名称。如果在安装wordpress时自定义过表名称,这里要修改成实际的表名称

3.替换前最好先看看wp_options(也许叫别的名称)中的home字段是什么,然后用这个字段值去替换例子中的www.mydomain.com

4.为了防止出错,修改好sql语句之后,最好先点击右下角的模拟查询按钮。没有这个按钮?请检查sql语句是否正确,否则请升级phpMyAdmin。如果模拟查询执行后的结果有错误,说明sql语句哪里有问题,需要一个一个排查直至问题解决。确认无误后再点击执行按钮。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

至于文中有人评论说:”二级站点只能访问首页,其他还是转跳到原来的域名地址“,我表示这人maybe是改错了什么地方,允悲

我已经按照这个方法更换过N个域名了,貌似还没出过问题