iOS上mxnet的一个演示App

mxnet是最近火的不行的一个深度学习的框架,支持好多好多语言,有好多好多大牛在写。

之前也有想过把同样很牛很牛的caffe跑到iOS上看看速度怎么样,但是caffe有一大堆文件,感觉做起来很麻烦。

最近看到mxnet居然有一个单文件的版本
就做了一个简单的图像识别的演示App。跑在6上速度还可以,大概4秒一张图。

代码在这里:

WhatsThis-iOS on Github

iExplorer

玩iOS的好东西。

这个不是微软的IE,而是iPhone Explorer,应该是因为Apple的压力,名字改成了iExplorer,据说图标也小有改动。

不需要Jailbreak你的iOS设备,连上机器之后打开iExplorer就可以看到各个App下的内容和系统的一些文件。
一般来说,App中用户的数据都是放在App Name/Documents这个文件夹下面,比如游戏存档…
iExplorer可以自由地存取文件,所以可以干的事情就多了…

软件主页上提供的截屏:

loadView的用法

UIViewController的loadView

用UIViewController有一段时间了,才发现以前对loadView的理解完全不到位。

假如我们用Xcode新建一个View-based Application,在ViewController.m中加上

- (void) loadView {
NSLog(@"loadView Called");
}

再增加viewDidLoad,按照一般的情况,我们会有这样的Code

- (void) viewDidLoad {
[super viewDidLoad];
UIButton *customButton = [UIButton buttonWith.....
......
[self.view addSubView:customButton];
}

现在打开MainWindow.xib,删掉其中的ViewController,并在AppDelegate.m的

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

里增加ViewController的初始化

viewController = [[XXXViewController alloc] init];

编译运行就有问题了。Console中不断的输出loadView Called!

仔细的阅读loadView的文档,才知道loadView不是这么用的。

loadView在每一次使用self.view这个property,并且self.view为nil的时候被调用,用以产生一个有效的self.view。这个接口原本是为了让我们自定义view用的。在不被subclass实现的情况下,也就是[super loadView]的效果,应该就是产生了一个有效的view,也就是一个空白的view。

在上面这种情况下,loadView被实现为空(只有一条打印语句),而且我们没有通过XIB初始化ViewController,所以在viewDidLoad被执行时,self.view是为nil的。所以在执行[self.view addSubView:customButton]时,loadView被调用,用来产生一个有效的view,使得self.view不再为nil。罢特,我们错了(-_-!)。我们的loadView什么也没有做,于是就出现了上面的情形,不断的调用一个什么都不做的loadView….

当然,我们只要在loadView中增加一句[super loadView]就没有问题了。但这并不是Cocoa的设计者所期望的。

loadView仅仅应该在开发者希望自行通过编码而不是Interface Builder定制view的时候被实现,而且不应该在其中调用[super loadView],你的loadView中应该有self.view = …这样的行为。

如果仅仅是想要在当前view上增加一些UIButton或是UILabel,应该在viewDidLoad里去做,此时不要实现自己的loadView。

Invalid Context

按照《IPhone Game Development》开始学习Game Development。
当在一个Game Loop中进行Update和Render时,都需要得到CGContextRef画图形。如果直接调用Update和Render,
在其中调UIGraphicsGetCurrentContext()就会报Invalid Context。

按照文档中的说法,系统会维护一个CGContextRef的栈,而UIGraphicsGetCurrentContext()会取栈顶的CGContextRef
正确的做法是只在drawRect里调用UIGraphicsGetCurrentContext()
因为在drawRect之前,系统会往栈里面压入一个valid的CGContextRef,除非自己去维护一个CGContextRef,否则不应该在其他地方取CGContextRef

对于Game Loop这种设计,应该由drawRect调用Render进行View的重绘,Update只负责修改一些变量,在Render中进行判断和绘制。