about TableView in Mac OS X

| No Comments | No TrackBacks
问题来源 Mac OS X 直到Lion 才开始支持View base TableView
 那么如果应用程序要支持10.6-,是绝对不可以使用官方的API.那么要快速实现TableView Cell自定义非常复杂。

可选方案: 1 IKImageBrowserView/IKImageBrowserCell 自定义显示比较麻烦,苹果就没想这个事情
     2 NSCollectionView/NSCollectionViewItem 同上,自定义显示不够友好

官方没有合适的,自己想偷懒,那么找一找,是不是有开源项目呢?

2 PXListView  https://github.com/Perspx/PXListView  http://perspx.com/archives/making-list-views-really-fast/ 作者关于List view 的思考
3 TWUI, Twitter on Mac https://github.com/twitter/twui  这个不介绍了,看github介绍吧
4 others may be



Enhanced by Zemanta
转一篇
原文 http://www.xuzhe.com/?p=601
首先,我说的是 iOS 开发,不是 Mac OS。

其次,这次解决的三个 BAD_ACCESS 都是由于 iOS 程序在收到 Memory Warning 后,非当前 UIViewController 执行 viewDidUnload 后出现的问题。

这类崩溃在真机上比较难测,因为是随机出现的,而且看 Crash Log 经常会看不出是哪行代码 BAD_ACCESS 了。所以这就需要善用模拟器提供的 "Hardware -> Simulate Memory Warning" 功能了。

同时为了能够方便的 Debug 出僵尸指针是谁,我在 Xcode 里加入以下三个环境变量:

NSZombieEnabled NSAutoreleaseFreedObjectCheckEnabled NSDebugEnabled

Xcode 4 的话编辑一下 Scheme,加到 Environment Variables 里即可(如果以前没加过的话)。

做完准备工作就能比较方便的进行 Debug 了。可以每切换一次 UIViewController 就模拟一次内存警告,看会不会崩溃。

接下来说说我这次遇到的三个问题。
1、一个低级错误

由于我们有时会几个人同时改一个文件,结果就发生了A用完一个实例以后顺手给释放掉了,但是却把B写在 viewDidUnload 里的代码给留下了。自然也就过度释放了。

这类过度释放的错误比较容易发现,只要改代码的时候稍微在原有文件里做一下搜索就能避免。

2、关于 Interface Builder 里的实例生命周期有多长的问题。

开发过 Mac OS 应用的同学都知道在开发 Mac 应用的时候,IB 里的实例 IBOutlet 到代码里是不用 retain 的。但是在 iOS 里却是要 retain 的。

这有什么区别呢?

如果你用的是 UIView 的话,的确,在 iOS 里不做 retain 也不要紧。因为 UIViewController 里的 UIView 本质上都是被 addSubview 到别的 UIView(UIWindow)里去的。但如果你在 IB 里放的是一个 NSObject,问题就出来了。

这也就是我遇到的问题。iOS 会把这个 NSObject 释放掉!

找这个问题花了我不少功夫,因为这个 NSObject 我只是在 IB 里连了连线,压根儿就没在代码里出现......解决方法其实很简单,在代码里加上

@property (nonatomic, retain) NSObject *someObject;

就好了(注意内存释放)。

3、BCTabBarController 带来的噩梦

在解决了以上问题后,整个程序仍然在满世界地不停的崩溃。这让我也很崩溃。咱好歹也算对 iOS 内存管理略有心得,搞个程序崩成这样实在是说不过去。

继续找下去发现问题出在一个第三方的开源控件:BCTabBarController 上。

用一个水准不高的第三方控件的结果就是给开发带来一定方便的同时,也带来了更多的麻烦(我不是在指责 BCTabBarController 的水准,因为要在苹果有限的公开 API 上完全自己来模拟原生 UITabBarController 的行为,的确是有难度的)。

这次的问题出在 BC 调用其管理的 UIViewController 的 viewWillAppear: 函数时,忽略了该 UIViewController 可能已经 viewDidUnload 过了。一上来就直接调用 viewWillAppear: ,结果当然不是崩掉就是逻辑乱掉。

解决方法是在 BC 调用 [viewController viewWillAppear:NO]; 之前加一句 [viewController view]; ,确保 viewDidLoad 先于 viewWillAppear: 被调用即可。

注:loadView 和 viewDidLoad 都不应该自己直接去调用,用 [viewController view]; 这种方法来让 view 自行载入的好处是,如果 view 已经被载入了,这一步操作不会让所有 view 再被载入一次。

现已发现的问题就是这么多,要在 iOS 上写个没有内存泄露又不会崩溃的程序实在是有难度。
SSD:~ yarshure$ ps -ef|grep AirPlay|grep -v  grep|awk '{print $2}'|xargs lsof -p |grep IPv4
?\x9e?  342 yarshure   16u    IPv4 0xffffff8016b0c320       0t0      TCP 192.168.69.56:49883->114.80.128.121:http (ESTABLISHED)
?\x9e?  342 yarshure   19u    IPv4 0xffffff8020d9ec00       0t0      TCP 192.168.69.56:50005->58.215.45.192:http (ESTABLISHED)
?\x9e?  342 yarshure   21u    IPv4 0xffffff8020d9fa40       0t0      TCP 192.168.69.56:49994->114.80.128.121:http (ESTABLISHED)
?\x9e?  342 yarshure   23u    IPv4 0xffffff8026da8de0       0t0      TCP 192.168.69.56:50008->114.80.128.121:http (ESTABLISHED)
?\x9e?  342 yarshure   24u    IPv4 0xffffff8020da16c0       0t0      TCP 192.168.69.56:50009->58.215.45.192:http (ESTABLISHED)



截图就不更新了,体验的赶紧下载尝鲜吧。

AirPlay.png
AirPlay.zip  下载链接,点击前面的那个
1 支持专辑和Artist 图片效果
2 目前只用pre, pause,n 操作
3 显示当前播的音乐专辑,演唱者,歌曲名字
4 目前不支持切换电台,下周会实现
   可以手动切电台http://restful.airplayme.com/radios/selected.json 查看电台id
   然后手动替换 defaultstation.plist 文件中id 项目,重启即可

2011.12.06 晚上版本
preview.png
下载地址:


1 界面美化
2 简单指出选电台
2011.12.07 更新
1 优化版本 胶片效果完善
2 修改启动时不显示界面问题

channel.png


早期功能版本
1 频道选择
2 歌曲/艺人/专辑搜索
3 歌词显示
4 seek 功能

airplay_func_ver.png



Enhanced by Zemanta

无题

| No Comments | No TrackBacks
晚上和哥哥姐姐在IM上聊了很多
总想写很多事情,但是不知道如何写起。

将来的某一天会下吧。

UsingBlocksAsContextInfo - Demonstrates how to implement Objective-C "blocks" passed in as the 'contextInfo' to NSAlert, helping to handle the alert result.


// This is a quick tip on how to use the context info as a block parameter.

// You can use this type of pattern for any methods that have a delegate/selector/contextInfo pattern.

- (void)btnShowAlertClicked:(id)sender  {

    NSAlert *alert = [NSAlert alertWithMessageText:@"Alert Message"

                                     defaultButton:@"Default Button"

                                   alternateButton:@"Alternate Button"

                                       otherButton:@"Other Button"

                         informativeTextWithFormat:@"Informative Text"];

    

    BOOL someLocalVariable = YES;

    

    // We create a block that can easily access local variables to this method.

    // This is much easier than trying to package them all up into a contextInfo object

    void (^blockCallback)(NSInteger) = ^(NSInteger returnCode) {

        // Inside the block callback we can easily access locals

        if (someLocalVariable) {

            if (returnCode == NSAlertDefaultReturn) {

                [button setTitle:@"Default Return Button Clicked!"];

            } else {

                [button setTitle:@"Something else clicked...try again."];

            }

        }

    };

    

    // We copy the block, since it needs to stay alive for longer than the current scope

    [alert beginSheetModalForWindow:self.window

                      modalDelegate:[self class]

                     didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)

                        contextInfo:Block_copy(blockCallback)];

}


+ (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void (^)(NSInteger returnCode))continuationHandler {

    continuationHandler(returnCode);

    // The block must always be retained before the first call. This is the matching release

    Block_release(continuationHandler);

}


| No Comments | No TrackBacks

static void _processData(AppDelegate *self, NSInteger i) {

    // Notice that the _window can be accessed here, even though it is a private ivar

    // A compiler error (or warning) will happen if this method was outside the @implementation scope of AppDelegate.

    NSLog(@"Processing %d in window %@", i, self->_window);

}


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    for (NSInteger i = 0; i < 200; i++) {

        _processData(self, i);

    }

}

@金色

| No Comments | No TrackBacks
kong_hometown.JPG
@yarshure 2011.09.19 下午  

AppKit 一点笔记(三)

| No Comments | No TrackBacks
程序如何运行?
  入口main函数
  
#import <Cocoa/Cocoa.h>
 
int main(int argc, char *argv[])
{
    return NSApplicationMain(argc,  (const char **) argv);
}
  
应用程序主进程开启
 通过Info.plist 查找 NSMainNibFile,并load之
NSMainNibFile 文件Load完成后,下一步NibFile中"File's owner' 回调用awakeFromNib
10.6 之后支持[super awakeFromNib]

程序启动完成

程序状态管理和维护通过

NSApplication,NSApplicationDelegate 

NSNibLoading,单独load

使用NSBundle 3个方法

  

+ (BOOL)loadNibFile:(NSString *)fileName externalNameTable:(NSDictionary *)context withZone:(NSZone *)zone;

+ (BOOL)loadNibNamed:(NSString *)nibName owner:(id)owner;

- (BOOL)loadNibFile:(NSString *)fileName externalNameTable:(NSDictionary *)context withZone:(NSZone *)zone;


看起来第二个更简单些

  


另外Document base Application NSDocument 类可以使用

- (NSString *)windowNibName;方法加载目标Nib文件


NSWindowController 同样可以使用上面的这个方法


AppKit 一点笔记(二)

| No Comments | No TrackBacks
1 Dock Menu 效果如图
dock_menu.png
实现方法

NSApplicationDelegate

实现

- (NSMenu *)applicationDockMenu:(NSApplication *)sender

{

    return _menu;

}

2 状态条菜单

  需要NSMenuDelegate protocol

@protocol NSMenuDelegate <NSObject>

@optional

- (void)menuNeedsUpdate:(NSMenu*)menu;


- (NSInteger)numberOfItemsInMenu:(NSMenu*)menu;

- (BOOL)menu:(NSMenu*)menu updateItem:(NSMenuItem*)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel;

- (void)menuWillOpen:(NSMenu *)menu;

- (void)menuDidClose:(NSMenu *)menu;

- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item;

@end


statbar_menu.png

StatusBar加Icon

- (void)activateStatusMenu:(int)status

{

    NSStatusBar *bar = [NSStatusBar systemStatusBar];

    icon = [bar statusItemWithLength:NSVariableStatusItemLength];

    [icon retain];

NSString* filePath;

switch (status) {

case 0:

filePath = [[NSBundle mainBundle] pathForResource:@"sync_complete" ofType:@"png"];

break;

case 1:

filePath = [[NSBundle mainBundle] pathForResource:@"sync_processing" ofType:@"png"];

break;

case 2:

filePath = [[NSBundle mainBundle] pathForResource:@"sync_error" ofType:@"png"];

break;

default:

break;

}

NSImage* image = [[NSImage alloc] initWithContentsOfFile:filePath];

[icon setImage:image];

[icon setHighlightMode:YES];

[icon setMenu:mainMenu];

}


关于菜单就讲这么多

AppKit 一点笔记

| No Comments | No TrackBacks

NSWindowController

- (id)initWithWindow:(NSWindow *)window

或者使用 - (NSString *)windowNibName

NSWindowController *controller = [[c alloc] init];

    if (_windowControllers == nil) {

        _windowControllers = [NSMutableArray new];

    }

    [_windowControllers addObject:controller];

    [controller showWindow:self];//显示Window,self 为NSWindowController

    [controller release];


注册窗口关闭通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowClosed:) name:NSWindowWillCloseNotification object:nil];


处理关闭窗口通知,移出不需要的Window

- (void)_windowClosed:(NSNotification *)note {

    NSWindow *window = [note object];

    for (NSWindowController *winController in _windowControllers) {

        if (winController.window == window) {

            [[winController retain] autorelease]; // Keeps the instance alive a little longer so things can unbind from it

            [_windowControllers removeObject:winController];

            break;

        }

    }

}

Enhanced by Zemanta

sysctl on iOS5

| No Comments | No TrackBacks
iPhone4.txt



See iPhone4s hardware  info 

hw.machine = iPhone4,1
hw.model = N94AP
hw.ncpu = 2
hw.byteorder = 1234
hw.physmem = 529481728
hw.usermem = 447721472
hw.pagesize = 4096
hw.epoch = 1
hw.vectorunit = 0
hw.busfrequency = 200000000
hw.cpufrequency = 800000000
hw.cachelinesize = 32
hw.l1icachesize = 32768
hw.l1dcachesize = 32768
hw.l2settings = 1
hw.l2cachesize = 1048576
hw.tbfrequency = 24000000
hw.memsize = 529481728
hw.availcpu = 2

开发中使用了 http://opensource.apple.com/ 开发的项目 system_cmds 中sysctl 


Enhanced by Zemanta

Steven P. Jobs 1955-2011

| No Comments | No TrackBacks


IMG_0002.jpg
苹果失去了一位富有远见和创造力的天才,世界失去了一位神人。我们这些有幸认识史蒂夫并与之公事的人们,失去了一位亲爱的朋友和激励我们的精神导师。史蒂夫留下了一个只有他才能开创的公司,他的精神将永远是苹果的基石。(苹果官网,孙方翻译)

#pragma mark KVO

- (void)observeValueForKeyPath:(NSString *)keyPath

                      ofObject:(id)object

                        change:(NSDictionary *)change

                       context:(void *)context

{

NSLog(@"dict= %@ obj= %@,keypath=%@",change,object,keyPath);

//    if (object ==xxx) {

//        if ([keyPath isEqualToString:@"title"]) {

//            

//        }else if ([keyPath isEqualToString:@"name"]) {

//            

//        }

//    } else if(object == bbb){

//        

//    }

    if (context == 123) {

        

    } else if(context == 456){

        

    }

    

}

-(void)traceObj:(Entry*)obj

{

[obj addObserver:self

  forKeyPath:@"title"

options:0

context:123];

    [obj addObserver:self

  forKeyPath:@"name"

options:0

context:456];

    [objB addObserver:self

  forKeyPath:@"name"

options:0

context:NULL];

}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

-(void)viewDidLoad

{

[super viewDidLoad];


Entry *entry =[[Entry alloc] init];

[self traceObj:entry];

[entry setValue:@"abc" forKey:@"title"];

id msg=[entry valueForKey:@"titl"];

NSLog(@"%@",msg);

[[NSNotificationCenter defaultCenter] addObserver:self 

selector:@selector(keyboardShow:)

name:UIKeyboardWillShowNotification 

  object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self 

selector:@selector(keyboardShow:)

name:UIKeyboardWillHideNotification

  object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self 

selector:@selector(textChanged:)

name:UITextFieldTextDidChangeNotification

  object:nil];

}

-(void)textChanged:(NSNotification*)noti

{

NSLog(@"%@ %@",input.text,[noti userInfo]);

NSString *sTr =input.text;

if ([sTr length] >=10) {

input.text = [sTr substringWithRange:NSMakeRange(0,9)];

UIAlertView *alert=[[[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"ok" otherButtonTitles:@"2",@"cancel",nil] autorelease];

[alert show];

}

NSMutableArray *array=[[NSMutableArray alloc] initWithCapacity:10];

}

-(void)keyboardShow:(NSNotification*)noti

{

if ([[noti name] isEqualToString:UIKeyboardWillShowNotification]) {

input.center = CGPointMake(input.center.x, input.center.y-200);

} else {

input.center = CGPointMake(input.center.x, input.center.y+200);

}


}

######################################

@implementation Entry

@synthesize title;

@synthesize price;

@synthesize image53;

@synthesize image;



-(id)valueForUndefinedKey:(NSString *)key

{

return [NSString stringWithFormat:@"%@ not have value for key %@",self,key];

}

-(void)setValue:(id)value forUndefinedKey:(NSString *)key

{

}


Enhanced by Zemanta

东北老家小河

| No Comments | No TrackBacks
儿时夏季经常在河里游泳
拍摄于2011年9.19 傍晚

IMG_0189.jpg

昨天写的script

| No Comments | No TrackBacks

#!/bin/sh

apppath=`xcodebuild |grep Validation|awk '{print $2}'`

sign='iPhone Distribution:Yarshure Kong Healthcare Communications Co., Ltd.'

ipapath=`pwd`'/BlanceBall.ipa'

echo $apppath

/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication  -s "$sign" "$apppath" -o "$ipapath"

scp "$ipapath" macgeeks:~/macgeeks.cn/bbs/apps/


Enhanced by Zemanta

iOS API

| No Comments | No TrackBacks
Screenshot 2011.09.13 15.15.00.png
SpringBoard 中间那个title,表示正在播放的东东。有API可以修改啊?
发现豆瓣FM没有修改,基本是没提供API了。

第一次写CoreImage Code

| No Comments | No TrackBacks

    NSString *path=[[NSBundle mainBundle] pathForResource:@"111.jpg" ofType:nil];

    CIImage *image=[CIImage imageWithData:UIImagePNGRepresentation(imageView.image)];//[CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:path]];

    NSDictionary *pro=[image properties];

    NSLog(@"-- %@",pro);

    CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform"];//CIBloom

    [filter setDefaults];

    CGAffineTransform a=CGAffineTransformMakeRotation(0.5);

    [filter setValue:[NSValue valueWithCGAffineTransform:a] forKey:@"inputTransform"];

//    [filter setValue:[NSNumber numberWithFloat:0.5] forKey:@"inputRadius"];

    [filter setValue: image forKey: @"inputImage"];

    CIImage *result = [filter valueForKey: @"outputImage"];

    CIContext *context =[CIContext contextWithOptions:nil];

    

    CGImageRef cgimg=[context createCGImage:result fromRect:[result extent]];

    imageView.image = [UIImage imageWithCGImage:cgimg scale:1.0 orientation:UIImageOrientationUp];

关于动画的邮件

| No Comments | No TrackBacks
pic.animationDuration=10;
animation.duration = 2;
2个动画一起,而且时间不一样
可能10的这个根本没动起来
我写了个demo ,你可以参考下,看看是否满足你的要求


sample.zip

在 2011-7-18,下午6:01, ぃ空空一筑か 写道:

    孔老师,您好,最近做项目需要用到图片自动切换,按照我自己的想法,是遍历文件目录下的图片,随机取出一副,然后随机用一个动画效果,用UIView的beginAnimation和commitAnimation来实现。之前看过您的PPT,上面恰好有个UIImageView的动画,将图片当作一个集合给ImageView的animationImages属性,然后设置好其它的参数,再startAnimating和stopAnimation来实现。这种方法用于自动切换图片应该是最简单的,但我想在图片切换中加动画,查找了UIImageView的所有属性和方法,没有能实现的。也试过了用UIView的Layer来加载CATranition,但是没有效果。想问您一下,用UIImageView能不能实现我想要的?如果能的话,请指点一下,谢谢!下面是我相关的代码
  NSArray *fileList=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:DOCUMENTS_FOLDER error:nil];
picNames=[[NSMutableArray alloc] initWithArray:[fileList pathsMatchingExtensions:[NSArray arrayWithObject:@"jpg"]]];
imageArray=[[NSMutableArray alloc] initWithCapacity:[picNames count]];
for (int i=0; i<[picNames count]; i++) {
NSString *sPath=[NSString stringWithFormat:@"%@/%@",DOCUMENTS_FOLDER,[picNames objectAtIndex:i]];
[imageArray addObject:[UIImage imageWithContentsOfFile:sPath]];
}
pic=[[UIImageView alloc] init];
        NSArray arrayWithArray:imageArray];
pic.animationDuration=10;
pic.animationRepeatCount=-1;
CATransition *animation = [CATransition animation];
        animation.duration = 2;
        animation.timingFunction = UIViewAnimationCurveEaseInOut;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = YES;
animation.type = @"cube";
[pic.layer addAnimation:animation forKey:@"animation"];
[pic startAnimating];

Enhanced by Zemanta
iPad1和iPad2就SOC性能差距很大
错误不太应该,应该只是慢,感觉卡的样子。
建议改成iPod那个样子,不在屏幕上的图片不要加载到内存,用张default代替,需要的时候再用真正的渲染。
苹果是这么玩的,肯定会有提升的。

孔祥波


在 2011-9-9,下午4:06, ぃ空空一筑か 写道:

   孔老师你好,那个开源的coverFlow例子,你应该很早就看过,我想问个问题,我们项目里面前段时间用到了这个东西,解决了大多数问题,但还有个问题解决不了。
   我们的项目是在Ipad上面,滑动的图片比较大,在滑动时,如果手指滑动的时间快于动画的时间,连续这样,就会出现图片绘制错位的情况,在模拟器上面不存在这种表况,我估计是跟设备有关系,处理器不够好,不知道这个有没有解决的办法。然后就是在Ipad1上面滑动的流畅度远不如在Ipad2上面的,已经试过一些优化的方法了,不知道有没有什么方法可以让图片滑动更加流畅点。
   谢谢!

Enhanced by Zemanta

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • 1o1efdgdg: 初来乍到,请多多关照。 read more
  • Cisbye Xue: 树欲静而风不止,子欲养而亲不待。 节哀! read more
  • kevin: 楼主,可否给个联系方式,有问题请教你... 我按照你blog给出的命令 : libtool -dynamic -arch_only armv6 -syslibroot [file] -L read more
  • 孔祥波: 1,2,3已经称为过去时 4,5有待继续 6 零花钱是有了 7 iPad2,iPhone4,kindle3都有了 下半年要的计划呢? read more
  • iamdaiyuan: 节哀。好好珍惜身边的人吧 read more
  • xian.suzhou: 另外,我是苏州大学的一名老师,我们现在也在进行iphone输入法的开发。看到前面陈心涛同学给你的留言,想和他讨论一些输入法的问题,是否能提供他的邮箱地址?谢谢了! read more
  • xian.suzhou: 不知楼主会不会看到这个留言了,呵呵,我也想要一个例子,能发发给我一份,谢谢了! read more
  • iphonemaker: 具体怎么使用,能说说嘛,最好给个demo事例,谢谢。 qq:37079765 read more
  • dbanotes: 电子设备都有啥?要不帮我做点零活儿,我帮你解决掉好了 read more
  • meggy.meng: 恩 是需要做点计划 read more

Recent Assets

  • channel.png
  • airplay_func_ver.png
  • preview.png
  • AirPlay.png
  • kong_hometown.JPG
  • statbar_menu.png
  • dock_menu.png
  • HK_Plazza.jpg
  • NanJing_East.jpg
  • IMG_0019.jpg

页面

OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.37