Xcode上制作系统偏好设置面板项目(Preference Panes)

翻了半天网上没有很多关于这方面的,虽然Apple开发文档里写有。
嘛咱也不是说要翻译这个文档,而是简单介绍一下。
使用prefPane就和iOS的Settings里面的那些第三方程序设置一样,只不过Mac是直接安装到系统偏好设置面板里。而主要的功能就是作为外部设置来设置app,好处就是能变相绕过Sandbox来开启程序内部的一些不被允许的功能,当然同时app因为本身没开启这些功能可以通过Apple的审核上架到MacAppStore。

首先来了解下prefPane的原理,其实prefPane就是一个bundle,和app差不多,同样需要h和m文件,也有info.plist,也需要icon,而UI的话只有一个nib(当然可以做得多个然后之前切换什么的,那些就比较高级了)。而prefPane根据需要可以分成独立的prefPane来执行功能,也可以通过修改目标程序的设置plist文件达到设置app的功能,也可以直接使用NotificationCenter来通知程序:设置已经更改了!快做出反应!
这次主要介绍修改目标程序的偏好设置plist文件,优点是非常简单,缺点就是设置并不能马上生效,必须重新加载读取UserDefault或者重新运行程序。

继续阅读“Xcode上制作系统偏好设置面板项目(Preference Panes)”

iOS 7上进行Per App VPN设置(未能实验成功)

iOS7的新特性:支持Per-App-VPN,但是几个测试版下来都没发现有相关的设置。不过最后在开发文档里找到了相关的说明,但是这个其实是作为配置文件的API,并不能直接在设备上进行设置。而且操作极其繁琐,如果各位不愿意花时间去折腾的话可以等正式版iOS7放出后相关工具更新了再去设置。

再次说明一下本方法及其繁琐而且目前处于测试阶段没办法保证100%成功。另外本文仅作为技术研究,不提供任何代理服务。如需翻墙,请出门左转购买VPS不用谢。

目前是不明原因iOS7无法安装配置文件,应该是文件内容有错误。还需慢慢进行实验调整,不过思路应该是对的。

Per-App-VPN的官方说法:
屏幕快照 2013-09-12 23.22.15

Per-App-VPN有两种模式:
1.任何App包括Safari访问特定网址触发就打开VPN(也可以设置成手动提前打开)。
2.针对单个App进行代理,即App运行后自动开启VPN。
两个模式基本都差不多,就是设置的内容有些区别。其实你也可以把它理解为是一种路由表。

建议系统为Mac,需要工具:
1.Xcode任意版本(或者单独去找plist编辑器也可以)。
2.iPhone配置实用工具(Mac版本下载地址,目前版本3.5(289))。
3.iOS7设备一台。
4.可用VPN一个。
5.终端命令行。

制作方法: 继续阅读“iOS 7上进行Per App VPN设置(未能实验成功)”

最近真心够忙的

拖了好久的MoeApps终于出公测版了,虽然仅仅只是Lite版本的公测。
功能上面的基本来说没有大问题…至少目前来说已经没有技术难题了。全部完成也就只剩下时间的问题了。不过全部完成也不代表就能直接上架,因为该死的Apple条款所以咱们还在考虑内置一些新东西进去。
于是来放一些预览图好了~虽然说是支持iOS7而且效果也是iOS7的,不过iOS6下运行的和旧的MoeApps Lite没什么区别。
首先是iOS6和iOS7下运行的对比:
屏幕快照 2013-06-17 23.07.43
话说觉得其实iOS7下挺好看的,估计是因为传统界面看习惯或者说看腻了吧?
继续阅读“最近真心够忙的”

整页面可变高度UIScrollView和可变高度UITableViewCell的方法

经常做程序会有需要一页显示不完的东西要滚动,而且又正好碰上比如里面的UITextView里文字字数不确定而如果字太多要做滚动的方式,虽然UITextView自带了UIScrollView但是还是觉得不如一整页滚动的效果好?
于是解决方法就是使用单独的UIScrollView,这货在程序中应该算是最不智能的东西吧?而且又正好碰上一些高度不确定的东西比如刚才说的UITextView里的文字,似乎不能不用代码来解决了。
但是作为非老开发者来说,非常不希望完全使用代码来写界面,那么应该如何配合StoryBoard或者nib文件来制作UIScrollView呢?
解决方法的思路是这样的,首先要根据文本来确定UITextView的高度,然后再加上界面上其他东西的高度(应该说是总高度),来绘制ScrollView。
可参考这个
于是第一步:确定UITextView的高度,而这需要根据文本来运算,既然文本长度不确定,自然要从文本上下功夫了:

NSString *text = self.textview.text;
CGSize stringSize = [text sizeWithFont:[UIFont boldSystemFontOfSize:14] constrainedToSize:CGSizeMake(320, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];

代码分解第一步获取到textview里的文本,然后根据文本来确定文本的大小(宽度和高度),其中需要根据你自己实际情况修改的:
1.boldSystemFontOfSize是textview里文本的字体大小。
2.CGSizeMake里的320这个要根据textview的宽度来修改,比如在这里宽度占完整个屏幕就是320(不是640哦,iOS后台会自动算Retina的)。
得到的stringSize就是实际文本的大小(包括宽度和高度,而下面我我们直接只用高度所以实际用的时候就直接:stringSize.height),接下来要把UITextView设置成这个尺寸,这样可以显示完全部的字:

[self.textview setFrame:CGRectMake(78, 0, 320, stringSize.height + 100)];

我为什么在后面会有个+ 100呢?因为实际调试的时候发现如果直接设置高度为stringSize.height会出现最下面两行被挡住了。总之这个数字可以根据自己实际情况进行调整。
而前面的78和0这两个对应的是textview所在界面的x,y值,这个可以直接在Storyboard或者nib里textview的size inspector里的View里看到,直接照用就行了。

高深人士应该能看得出其实这里已经是手动来绘制textview了,其实本来咱是想用setContentSize单独设定高度的,但是似乎没用…

设置完了UITextView之后来设置UIScrollView:

[self.scrollview setContentSize:CGSizeMake(320, stringSize.height + 200)];

这次后面+200是因为要包含界面上其他的东西。

于是这样应该就能达到效果了,如果有误差的话稍微调整以上提到的几个数值,应该能达到你想要的效果了。

另外还有一种解决方案就是使用静态的UITableView,因为其内置已经做好UIScrollView了,只要根据UITextView来决定cell的高度就可以了。
不过可变高度的cell又是如何做到的呢?上面已经知道了如何根据文本来确定高度,那么直接将高度应用在cell里不就好了~
于是:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSArray *array = arraylist[row];
NSString *text = [array valueForKey:@"message"];
CGSize stringSize = [text sizeWithFont:[UIFont boldSystemFontOfSize:12] constrainedToSize:CGSizeMake(292, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
return stringSize.height +50;
}

咱根据当前cell直接从array中直接读message,接下来的就和上面一样进行文本的长度确定,而到了最后则是返回stringSize.height,外加上自行调整的误差。

而至于当文本字体大小改变或者界面尺寸改变的时候,重新修改上面代码的对应变量即可(比如横屏等),重新运算过后就可以了。

最后附赠一个多点触控捏合缩小放大字体的代码(代码效果不是很好…参考):

- (void)viewDidLoad{
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
[self.textview addGestureRecognizer:pinchGesture];
}


- (IBAction)handlePinchGesture:(UIGestureRecognizer *)sender {
static int fontSize = 20;
if (sender.state == UIGestureRecognizerStateBegan)
{
// initialBounds = _view.bounds;
}
CGFloat factor = [(UIPinchGestureRecognizer *)sender scale];
if(factor > 1.0)
{
fontSize += 1;
}
else
{
fontSize -= 1;
}
if (fontSize >50) {
fontSize =50; return;
}
if (fontSize <5) { fontSize = 5; return; } [self.textview setFont:[UIFont fontWithName:@"Helvetica" size:fontSize]]; return; }

[Obj-c]匹配字段&NSArray里的Null问题&消除HTML转义字符

首先是监测字段匹配,假设要监测字符串string里是否含”a”这个字符:

if ([string rangeOfString:@"a"].location != NSNotFound) {
//do something
}

当NSArray为空或者里面某项为null的时候,在TableView或者其他什么界面经常会出现崩溃的问题。
解决方法:检测是否为空。但是普通的if (array != nil)是没用的,得这样操作:

if (array != [NSNull null]) {
//array not empty
}

尽管可能编译时会有警告…不过工作是正常的,至少程序不会再崩溃了。

最后,HTML输出的时候经常会连比如”&”或者空格之类的都转换成了“&amp;”或者“&nbsp;”这样的字符。
解决方法:手动转换回来。
加入以下代码:(为了防止被转换,咱已经将英文标点”;”更换成了全角的“;”,使用前请先手动更换回来)

-(NSString *)htmlEntityDecode:(NSString *)string{
string = [string stringByReplacingOccurrencesOfString:@"";" withString:@"\""];
string = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
string = [string stringByReplacingOccurrencesOfString:@"&;" withString:@"&"];
string = [string stringByReplacingOccurrencesOfString:@"<;" withString:@"<"]; string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
string = [string stringByReplacingOccurrencesOfString:@" ;" withString:@" "];
return string;
}

然后这么用:
string = [self htmlEntityDecode:string];
得到的string就是正常的了~

MoeApps/MoeApks和萌电波近期暂停开发

因为打算6月之前把手头上公司的活全部做完,所以估计会超忙的,就没多少时间顾及到MoeApps以及萌电波更别说MoeApks了。所以打算暂时搁置这两个计划。嘛….只是搁置不代表抛弃就是的,等下个月忙完之后才会有空继续吧。反正目前萌电波算是比较完美了的,当然破解获奖这个活动还是继续的。只不过MoeApps就算写完也不会那么快能放出就是了。
当然因为忙,估计连blog也不会频繁更新吧…反正本来就没多少人看就是了。

说到Blog,话说最近不知道怎么的老有人给咱写垃圾评论,而且还只针对教程那几篇文章….于是目前关掉了那几篇文章的评论功能,并且开启了评论验证,其实本来也不想怎么干的,只不过因为实在是受不了一天要处理几次好麻烦..
嘛..反正之前评论过的直接显示就是了~这点WP做得倒是蛮好的。
继续阅读“MoeApps/MoeApks和萌电波近期暂停开发”

[你敢破我敢送]破解萌电波即可获得正版免费注册&新测试版本发布

不想出钱但是想出力?现在来破解萌电波就可以有机会免费拿到注册名额噢~
破解掉萌电波的注册验证或者使其无限期使用。之后将破解方法发给咱,就有机会获得免费的注册名额一个。
破解前请必须遵守:
1.不得对咱的服务器(咱自己的包括萌否的)进行包括数据库注入或者DDos等方式的攻击破坏(因为服务器down了的话会影响别人正常使用让人家困扰的,严重的话咱会考虑向JC蜀黍求助的)。
2.破解方法必须得是对应最新版本的,将破解方法发给咱之前请先检查下是否有新版本发布。新版本发布后对应旧版本的方法即无效。
3.不得抄袭,咱也会保证你的方法是唯一的。
破解完后将破解的方法(请简单描述)以及截图发送到本人的邮箱,而且因为要推广你信息所以建议附带上自行的blog或者社交页面的网址(默认的话咱会帮您填上blog地址,如果找不到的话才会使用社交页面)。验证过后会邮件返信通知您。
目前暂时还没什么拿得出手的,所以就只能送免费注册名额了,之后可能会多举办类似的…也可能会在MoeApps上举行。而以后也会有更多的礼品加入其中,比如送app或者送兑换卡之类的。

下载:
请直接到萌电波发布页面去下载主程序。

PS:清理注册信息的方法:调教面板里的GM code中输入[cleanreginfo]后执行,重启程序即可恢复到未注册状态。
PS2:破解后需要能开始收听歌曲才算破解,过期时关掉过期窗口虽然注册信息是提示“已注册”但是并无法播放歌曲,所以不算破解。

继续阅读“[你敢破我敢送]破解萌电波即可获得正版免费注册&新测试版本发布”

萌否电台Mac版准备改收费,免费名额预定中

目前的版本基本功能已经完成了,而还要更进一步的话咱白干会觉得比较亏(有米才有动力嘛~)…所以打算之后准备进行收费化~
当然价格不会很贵的啦~咱虽然说是执行收费,但是并不像别的软件那样过分的漫天要价,咱还是想尽量压低市场的价格,所以之后定价会在一个合理的范围(大概10RMB或者5USD这样),至少让所谓“穷学生”都能买得起。
上架MAS什么的,因为咱无法预估使用人数所以根本不敢去购买Mac开发者计划…

屏幕快照 2013-04-12 下午3.57.00

而因为不同于一般应用程序,电台是属于在线程序,所以验证方式当然是选择联网验证,这样一定程度上也防止序列号被滥用(被破解的话可能会考虑之后对程序进行加密)。当然主要的目的还是为了锻炼咱的技术。当然方便统计用户信息也是一方面(说实话咱现在都不知道有多少人在使用咱写的东西..。)。

原理也比较简单,程序启动之后会验证是否已保存有注册信息,没有的话则是试用版,将机器的信息上传到咱的服务器进行时间记录,超过时间的提示试用期已过,只能退出程序。
而存在了注册信息的话会尝试联网进行验证,而网络不通或者验证范围注册信息是无效也会有提示并退出程序。只有验证通过了才能继续使用软件。
服务器端的话就比较简单,直接一个返回页面以及做好数据库即可。不过保障服务器在线就是重点了,不过根据统计来看,咱服务器挂掉的几率/次数比萌否的还要少很多,所以咱是不担心这个。

预计内置收费功能会和下次大更新也就是内置播放列表或者上传歌曲等功能一起发布。
现在的话开始招免费名额,一共5位,在下面留言就有机会获得(并不是说先到先得,大家拼RP吧)。
想要预购或者赞助的话也可以,可以到这个页面捐助咱。同样之后可以直接获得免费注册名额。
继续阅读“萌否电台Mac版准备改收费,免费名额预定中”

RegIP更新v2.1

这次算是比较大的更新,当然GitHub上的源代码也一起更新了。
主要的改变一个是添加了可以定时自动更新IP。
每间隔10分钟自动执行绑定一次,这样当自动重新拨号更换IP的时候可以及时绑定域名(虽然比不上路由器…毕竟人家有检测触发,咱检测不到PPPOE重拨号)。
第二个是界面和代码的优化。
首次成功在程序里显示消息记录(虽然实现的方法挺简单的),然后将记录的文本也缩小了,记录的信息也比之前详细一些,显示得也更多。
代码的话优化了许多…除了开启ARC之外,还添加了输入检测,其他的就是整理过了感觉上看起来比较舒服这样。
屏幕快照 2013-04-12 上午3.35.57

bug的话也有,就是信息纪录在钥匙串里(为了提高保密性所以直接用钥匙串,不过其实可以保存在UserDefault里的,那样真的就是明文保存了,不过因为本来传输就是未加密的所以根本无保密性可言),然后似乎第一次能记录信息之外,后面的修改似乎久无法保存了,只能在钥匙串访问里删除掉com.RegIP开头的两个密钥才行(虽然在程序里添加了删除记录的密钥功能,但是似乎不起作用…)。不过这个不是很影响日常操作而且代码里也没发现问题,所以搁置解决。

咱常用NameCheap和Oray所以只有这两个服务商…如果有需要别的域名服务商可以告诉咱,基本上大多数都会提供有API,添加进去都不是困难的事情。
因为是小程序也不常维护,所以就不内置更新检测了(主要是弄证书什么的验证挺麻烦的)。下载可以到上方“下载”页面找RegIP直接下载,当然和以前一样是开源,高手们可以直接去GitHub里下载源代码自行编译(特别是10.7以下或者32位的Mac用户)。

继续阅读“RegIP更新v2.1”