全系列文章索引:
IOS开发问题索引(一)
IOS开发问题索引(二)
IOS开发问题索引(三)
IOS开发问题索引(四)
IOS开发问题索引(五)
IOS开发问题索引(六)
IOS开发问题索引(七)
IOS开发问题索引(八)
IOS开发问题索引(九)
1、ios音频队列服务编程指南
音频队列服务编程指南
音频队列服务编程指南(AudioQueue Services Programming Guide)(一)
http://blog.csdn.net/just_we_0727/article/details/8200853
音频队列服务编程指南(AudioQueue Services Programming Guide)(二)
http://blog.csdn.net/just_we_0727/article/details/8201023
音频队列服务编程指南(AudioQueue Services Programming Guide)(三)
http://blog.csdn.net/just_we_0727/article/details/8373440
2、ios数据绑定
关于PickerView数据源的问题
http://blog.sina.com.cn/s/blog_69ee96d70100kz8r.html
PickerView的工作方式是怎样的
http://www.cocoachina.com/bbs/simple/?t22239.html
PickerView数据源的绑定在“无形”之中,因为并不是采用一种可视的方法,比如xxxx.dataSource=myDataSource,而是通过实现协议的方式,对于UIPickerVIew,需要实现如下等若干协议
3、交叉编译libogg& libvorbis
交叉编译libogg& libvorbis
http://blog.163.com/dong_xiao_yang/blog/static/21613820520132125548615/
Tutorial: Open Source on iOS (Part 2): Compiling libogg oniOS
http://iosdeveloperzone.com/2012/09/29/tutorial-open-source-on-ios-part-2-compiling-libogg-on-ios/
Cross Compiling libogg for iOS
http://stackoverflow.com/questions/11711100/cross-compiling-libogg-for-ios
4、ios传感器总结(1)
ios传感器总结(1)
http://blog.csdn.net/shaobojohn/article/details/7843104
5、ios UIView事件注册
UIView事件注册
http://menglinger-520.blog.163.com/blog/static/16929433020117584733320/
6、ios进度条的实现
进度条的实现(MBProgressHUD)
http://blog.csdn.net/weasleyqi/article/details/8072897
7、ios录音功能的实现
ios录音功能的实现
http://blog.csdn.net/rs_network/article/details/6988447
iOS录音Wav音频 转换Amr,Android播放
http://blog.csdn.net/justinjing0612/article/details/9633121
http://code4app.com/ios/Sound-Recorder/4f9252d606f6e71769000000
8、Xcode引用文件注意
Xcode引用文件时,不要直接拷贝文件到项目目录,再以添加引用的形式引用,这时有可能报“找不到文件”错误,而且引用的文件目录是蓝色的,最好是直接饮用,选择copyitem的方式
9、ios 'libxml/xmlversion.h' file not found inxcode 4.2?
'libxml/xmlversion.h' file not found in xcode 4.2?
http://stackoverflow.com/questions/8850724/libxml-xmlversion-h-file-not-found-in-xcode-4-2
Remember to add the library in Link Binary en Build
Phases Section of the target project.
You need to put all the libxml headers on the include
path. For Xcode do this by adding /usr/include/libxml2to theheader paths (that will pass -I/usr/include/libxml2 to the c compiler)
This is in thebuild settings tab in Search Paths -> Header Search Paths
10、iosASIHTTPRequest类库简介和使用说明
ASIHTTPRequest类库简介和使用说明
http://www.cnblogs.com/dotey/archive/2011/05/10/2041966.html
ASIHTTPRequest类库在iOS 7.0中需要修改的地方
http://blog.s135.com/post/490/
代码技巧之ASIHttpRequest类库的使用
http://bbs.9ria.com/thread-259725-1-1.html
11、ios相对路径与绝对路径的转化NSBundle
ios相对路径与绝对路径的转化NSBundle
http://blog.csdn.net/zi2xuan/article/details/7319210
iOS的相对路径和绝对路径
http://wiki.eoe.cn/page/iOS_blog_page_98641.html
12、NSString字符串相加连接
NSString字符串相加连接的三种方法
http://blog.sina.com.cn/s/blog_56e2f4250102dusl.html
Objective-C语法之NSString字符串的那些事儿(三)
http://blog.csdn.net/xys289187120/article/details/6777283
13、iosXCode clang failed with exit code 254
原因:
进入IOS虚拟机,然后直接打开了共享目录中的Xcode工程进行编译;
XCode clang failed with exit code 254
http://stackoverflow.com/questions/17426810/xcode-clang-failed-with-exit-code-254
clang failed with exit code 254 only for iOS device target
http://stackoverflow.com/questions/11984074/clang-failed-with-exit-code-254-only-for-ios-device-target
iOS 5 - Apple LLVM compiler 3.0 error
http://www.cnblogs.com/mfryf/archive/2012/02/26/2369190.html
14、正则表达式
匹配几个字符串之一:
Var tagnameRex = /(div|font|table|ol|ul)/I; 查找任何指定字符串
【整理】关于用正则表达式处理html代码方面的建议
http://www.crifan.com/for_process_html_with_many_tag_recommend_use_third_lib_while_simple_html_use_regular_expression/
15、判断js对象是否拥有某属性
http://www.cnblogs.com/snandy/archive/2011/03/04/1970162.html
两种方式,但稍有区别
1,in 运算符
var obj = {name:'jack'};
alert('name' in obj);
// --> true
alert('toString' in obj);
// --> true
可看到无论是name,还是原形链上的toString,都能检测到返回true。
2,hasOwnProperty 方法
var obj = {name:'jack'};
obj.hasOwnProperty('name');
// --> true
obj.hasOwnProperty('toString');
// --> false
原型链上继承过来的属性无法通过hasOwnProperty检测到,返回false。
需注意的是,虽然in能检测到原型链的属性,但for in通常却不行。
当然重写原型后for in在IE9/Firefox/Safari/Chrome/Opera下是可见的。见:for in的缺陷
16、objective-c与js交互
※ 用 Objective-C 取得与设定 JavaScript 对象
要从 Objective-C取得网页中的 JavaScript 对象,也就是对windowScriptObject 做一些 KVC 调用,像是 valueForKey: 与 valueForKeyPath:。如果我们在 JS 里头,想要知道目前的网页位置,会这么写:
var location = window.location.href;
用 Objective-C 就可以这么调用:
NSString *location = [[webViewwindowScriptObject] valueForKeyPath:@"location.href"];
如果我们要设定 window.location.href,要求开启另外一个网页,在 JS 里头:
window.location.href= 'http://spring-studio.net';
在Objective-C:
[[webViewwindowScriptObject]setValue:@"http://spring-studio.net"forKeyPath:@"location.href"];
由于Objective-C 与 JS 本身的语言特性不同,在两种语言之间相互传递东西之间,就可以看到两者的差别:
1、JS 虽然是 OO,但是并没有 class,所以将 JS 对象传到 Obj C 程序里头,除了基本字串会转换成 NSString、基本数字会转成 NSNumber,像是 Array 等其他对象,在 Objective-C 中,都是 WebScriptObject 这个 Class。意思就是,JS 的 Array 不会帮你转换成 NSArray。
2、从 JS 里头传一个空对象给 Objective-C 程序,用的不是 Objective-C 里头原本表示「没有东西」的方式,像是 NULL、nil、NSNull 等,而是专属 WebKit 使用的 WebUndefined。
所以,如果我们想要看一个 JS Array 里头有什麽东西,就要先取得这个对象里头叫做 length 的 value,然后用 webScriptValueAtIndex: 去看在该 index 位置的内容。
假如我们在 JS 里头这样写:
var JSArray = {'zonble', 'dot', 'net'};
for (var i = 0; i < JSArray.length; i++) {
console.log(JSArray[i]);
}
在Objective-C 里头就会变成这样:
WebScriptObject *obj = (WebScriptObject *)JSArray;
NSUInteger count = [[obj valueForKey:@"length"]integerValue];
NSMutableArray *a = [NSMutableArray array];
for (NSUInteger i = 0; i < count; i++) {
NSString *item = [objwebScriptValueAtIndex:i];
NSLog(@"item:%@", item);
}
※ 用 Objective-C 调用 JavaScript function
要用 Objective-C 调用网页中的 JS function,大概有几种方法。第一种是直接写一段跟你在网页中会撰写的 JS 一模一样的程序,叫 windowScriptObject 用 evaluateWebScript: 执行。
例如,我们想要在网页中产生一个新的 JS function,内容是:
function x(x) {
return x + 1;
}
所以在 Objective-C 中可以这样写;
[[webView windowScriptObject] evaluateWebScript:@"function x(x) {return x + 1;}"];
接下来我们就可以调用 window.x():
NSNumber *result = [[webView windowScriptObject]evaluateWebScript:@"x(1)"];
NSLog(@"result:%d", [result integerValue]); // Returns 2
由于在 JS 中,每个 funciton 其实都是对象,所以我们还可以直接取得 window.x 叫这个对象执行自己。
在 JS 里头如果这样写:
window.x.call(window.x, 1);
Objective-C 中便是这样:
WebScriptObject *x = [[webView windowScriptObject]valueForKey:@"x"];
NSNumber *result = [xcallWebScriptMethod:@"call"withArguments:[NSArray arrayWithObjects:x,[NSNumbernumberWithInt:1], nil]];
这种让某个 WebScriptObject 自己执行自己的写法,其实比较不会用于从 Objective-C 调用 JS 这一端,而是接下来会提到的,由 JS 调用 Objective-C,因为这样 JS 就可以把一个 callback function 送到 Objective-C 程序里头。
如果我们在做网页,我们只想要更新网页中的一个区块,就会利用 AJAX 的技巧,只对这个区块需要的资料,对 server 发出 request,并且在 request 完成的时候,要求执行一段 callback function,更新这一个区块的显示内容。从 JS 调用 Objective-C也可以做类似的事情,如果 Objective-C程序里头需要一定时间的运算,或是我们可能是在 Objective-C 里头抓取网路资料,我们便可以把一个 callback function 送到 Objective-C程序里,要求Objective-C程序在做完工作后,执行这段 callback function。
※ DOM
WebKit 里头,所有的 DOM 对象都继承自 DOMObject,DOMObject 又继承自 WebScriptObject,所以我们在取得了某个 DOM 对象之后,也可以从 Objective-C 程序中,要求这个 DOM 对象执行 JS 程序。
假如我们的网页中,有一个 id 叫做 “#s” 的文字输入框(text input),而我们希望现在键盘输入的焦点放在这个输入框上,在 JS 里头会这样写:
document.querySelector('#s').focus();
在Objective-C中写法:
DOMDocument *document = [[webView mainFrame] DOMDocument];
[[document querySelector:@"#s"]callWebScriptMethod:@"focus"withArguments:nil];
※ 用 JavaScript 存取 Objective-C 的 Value
要让网页中的 JS 程序可以调用 Objective-C 对象,方法是把某个Objective-C 对象注册成 JS 中 window 对象的属性。之后,JS 便也可以调用这个对象的 method,也可以取得这个对象的各种 Value,只要是 KVC 可以取得的 Value,像是 NSString、NSNumber、NSDate、NSArray、NSDictionary、NSValue…等。JS 传 Array 到 Objective-C 时,还需要特别做些处理才能变成 NSArray,从 Obj C 传一个 NSArray 到 JS 时,会自动变成 JS Array。
首先我们要注意的是将 Objective-C 对象注册给 window 对象的时机,由于每次重新载入网页,window 对象的内容都会有所变动-毕竟每个网页都会有不同的 JS 程序,所以,我们需要在适当的时机做这件事情。我们首先要指定 WebView 的 frame loading delegate(用setFrameLoadDelegate:),并且实作webView:didClearWindowObject:forFrame:,WebView 只要更新了 windowScriptObject,就会调用这一段程序。
假如我们现在要让网页中的 JS 可以使用目前的 controller 对象,会这样写:
- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject*)windowObject forFrame:(WebFrame *)frame
{
[windowObjectsetValue:self forKey:@"controller"];
}
如此一来,只要调用 window.controller,就可以调用我们的 Objective-C 对象。假如我们的Objective-C Class 里头有这些成员变数:
@interface MyController : NSObject
{
IBOutlet WebView *webView;
IBOUtlet NSWindow *window;
NSString *stringValue;
NSInteger numberValue;
NSArray *arrayValue;
NSDate *dateValue;
NSDictionary *dictValue;
NSRect frameValue;
}
@end
指定一下 Value:
stringValue = @"string";
numberValue = 24;
arrayValue = [[NSArray arrayWithObjects:@"text",[NSNumbernumberWithInt:30], nil] retain];
dateValue = [[NSDate date] retain];
dictValue =[[NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1", @"value2", @"key2", @"value3", @"key3", nil]retain];
frameValue = [window frame];
用 JS 读读看:
var c = window.controller;
var main = document.getElementByIdx_x('main');
var HTML = '';
if (c) {
HTML += '' +c.stringValue + '';
HTML += '' +c.numberValue + '';
HTML += '' +c.arrayValue + '';
HTML += '' +c.dateValue + '';
HTML += '' +c.dictValue + '';
HTML += '' +c.frameValue + '';
main.innerHTML = HTML;
}
结果如下:
string 24 text,30 2010-09-09 00:01:04 +0800 { key1 = value1; key2 =value2; key3 = value3; } NSRect: {{275, 72}, {570, 657}}
不过,如果你看完上面的范例,就直接照做,应该不会直接成功出现正确的结果,而是会拿到一堆 undefined,原因是,Objective-C 对象的 Value 预设被保护起来,不会让 JS 直接存取。要让 JS 可以存取 Objective-C 对象的 Value,需要操作 +isKeyExcludedFromWebScript: 针对传入的 Key 一一处理,如果我们希望 JS 可以存取这个 key,就回传 NO:
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name
{
if (!strcmp(name, "stringValue")){
return NO;
}
return YES;
}
除了可以读取 Objective-C对象的 Value 外,也可以设定 Value,相当于在 Objective-C中使用 setValue:forKey:,如果在上面的 JS 程序中,我们想要修改 stringValue,直接调用 c.stringValue = ‘new value’ 即可。像前面提到,在这裡传给 Objective-C的 JS 对象,除了字串与数字外,class 都是 WebScriptObject,空对象是 WebUndefined。
※ 用 JavaScript 调用 Objective-C method
Objective-C 的语法沿袭自 SmallTalk,Objective-C 的 selector,与 JS 的 function 语法有相当的差异。WebKit 预设的实事是,如果我们要在 JS 调用 Objective-C selector,就是把所有的参数往后面摆,并且把所有的冒号改成底线,而原来 selector 如果有底线的话,又要另外处理。
假使我们的 controller 对象有个 method,在Objective-C 中写成这样:
- (void)setA:(id)a b:(id)b c:(id)c;
在 JS 中就这么调用:
controller.setA_b_c_('a', 'b', 'c');
实在有点丑。所以 WebKit 提供一个方法,可以让我们把某个 Objective-C selector 变成好看一点的 JS function。我们要实作webScriptNameForSelector:
+ (NSString *)webScriptNameForSelector:(SEL)selector
{
if (selector == @selector(setA:b:c:)) {
return @"setABC";
}
return nil;
}
以后就可以这么调用:
controller.setABC('a', 'b', 'c');
我们同样可以决定哪些 selector 可以给 JS 使用,哪些要保护起来,方法是实作 isSelectorExcludedFromWebScript:。而我们可以改变某个 Objective-C selector 在 JS 中的名称,我们也可以改变某个 value 的 key,方法是实作 webScriptNameForKey:。
有几件事情需要注意一下:
用 JavaScript 调用 Objective C 2.0 的property
在上面,我们用 JS 调用 window.controller.stringValue,与设定里头的 value 时,这边很像我们使用 Objective-C 2.0 的语法,但其实做的是不一样的事情。用 JS 调用 controller.stringValue,对应到的Objective-C 语法是 [controller valueForKey:@"stringValue"],而不是调用Objective-C 对象的 property。
如果我们的 Objective-C 对象有个 property 叫做 stringValue,我们知道,Objective-C property 其实会在编译时,变成 getter/setter method,在 JS 里头,我们便应该要调用 controller.stringValue() 与controller.setStringValue_()。
Javascript 中,Function 即对象的特性
JS 的 function 是对象,当一个 Objective-C 对象的 method 出现在 JS 中时,这个 method 在 JS 中,也可以或多或少当做对象处理。我们在上面产生了 setABC,也可以试试看把它倒出来瞧瞧:
console.log(controller.setABC);
我们可以从结果看到:
function setABC() { [native code] }
这个 function 是 native code。因为是 native code,所以我们无法对这个 function 调用 call 或是 apply。
另外,在把我们的 Objective-C 对象注册成 window.controller 后,我们会许也会想要让 controller 变成一个 function 来执行,像是调用 window.controller();或是,我们就只想要产生一个可以让 JS 调用的 function,而不是整个对象都放进 JS 里头。我们只要在 Objective-C 对象中,实作 invokeDefaultMethodWithArguments:,就可以回传在调用 window.controller() 时想要的结果。
现在我们可以综合练习一下。前面提到,由于我们可以把 JS 对象以 WebScriptObject 这个 class 传入 Obj C 程序,Objective-C 程序中也可以要求执行 WebScriptObject 的各项 function。我们假如想把 A 与 B 两个数字丢进 Objective-C 程序里头做个加法,加完之后出现在网页上,于是我们写了一个 Objective-C method:
- (void)numberWithA:(id)a plusB:(id)b callback:(id)callback
{
NSInteger result = [a integerValue] + [bintegerValue];
[callbackcallWebScriptMethod:@"call" withArguments:[NSArrayarrayWithObjects:callback, [NSNumber numberWithInteger:result],nil]];
}
JS 里头就可以这样调用:
window.controller.numberWithA_plusB_callback_(1, 2,function(result) {
var main =document.getElementByIdx_x('main');
main.innerText = result;
});
※ 其他平台上 WebKit 的用法
除了 Mac OS X,WebKit 这几年也慢慢移植到其他的作业系统与 framework 中,也或多或少都有 Native API 要求 WebView 执行 Js,以及从 JS 调用 Native API 的机制。
跟 Mac OS X 比较起来,IOS 上 UIWebView 的公开 API 实在少上许多。想要让 UIWebView 执行一段 JS,可以透过调用 stringByEvaluatingJavaScriptFromString:,只会回传字串结果,所以能够做到的事情也就变得有限,通常大概就拿来取得像 window.title 这些资讯。在 IOS 上我们没办法将某个 Objective-C 对象变成 JS 对象,所以,在网页中触发了某些事件,想要通知 Objective-C 这一端,往往会选择使用像「zonble://」这类 Customized URL scheme。
ChromeOS 完全以 WebKit 製作使用者介面,不过我们没办法在 ChomeOS 上写我们在这边所讨论的桌面或行动应用程序,所以不在我们讨论之列。(顺道岔题,ChromeOS 是设计来给 Netbook 使用的作业系统,可是像 Toshiba 都已经用 Android,做出比 Netbook 更小的 Smartbook,而且应用程序更多,ChromeOS 的产品做出来的话,实在很像 Google 拿出两套东西,自己跟自己对打)。
Android 的 WebView 对象提供一个叫做 addJavascriptInterface() 的 method,可以将某个 Java 对象注册成 JS 的 window 对象的某个属性,就可以让 JS 调用 Java 对象。不过,在调用 Java 对象时,只能够传递简单的文字、数字,複杂的 JS 对象就没办法了。而在 Android 上想要 WebView 执行一段 JS,在文件中没看到相关资料,网路上面找到的说法是,可以透过 loadUrl(),把某段 JS 用 bookmarklet 的形式传进去。
在 QtWebKit 里头,可以对 QWebFrame 调用addToJavaScriptWindowObject,把某个 QObject 暴露在 JS 环境中,我不清楚 JS 可以传递哪些东西到 QObject 里头就是了。在 QtWebKit 中也可以取得网页里头的 DOM 对象(QWebElement、QWebElementCollection),我们可以对 QWebFrame 还有这些 DOM 对象调用 evaluateJavaScript,执行 Javascript。
GTK 方面,因为是 C API,所以在应用程序与 JS 之间,就不是透过操作包装好的对象,而是调用 WebKit 里头 JavaScript Engine 的 C API。
※ JavaScriptCore Framework
我们在 Mac OS X 上面,也可以透过 C API,要求 WebView 执行 Javascript。首先要 import 。如果我们想要简单改一下 window.location.href:
JSGlobalContextRef globalContext = [[webView mainFrame] globalContext];
JSValueRef exception = NULL;
JSStringRef script =JSStringCreateWithUTF8CString("window.location.href='http://spring-studio.net'");
JSEvaluateScript(globalContext, script, NULL, NULL, 0, &exception);
JSStringRelease(script);
如果我们想要让 WebView 里头的 JS,可以调用我们的 C Function:
- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject*)windowObject forFrame:(WebFrame *)frame
{
JSGlobalContextRef globalContext = [frameglobalContext];
JSStringRef name =JSStringCreateWithUTF8CString("myFunc");
JSObjectRef obj =JSObjectMakeFunctionWithCallback(globalContext, name,(JSObjectCallAsFunctionCallback)myFunc);
JSObjectSetProperty (globalContext, [windowObjectJSObject], name, obj, 0, NULL);
JSStringRelease(name);
}
那麽,只要 JS 调用 window.myFunc(),就可以取得们放在 myFunc 这个 C function 中回传的结果:
JSValueRef myFunc(JSContextRef ctx, JSObjectRef function, JSObjectRefthisObject, size_t argumentCount, const JSValueRefarguments[], JSValueRef* exception)
{
return JSValueMakeNumber(ctx, 42);
}
若是传入参数是字符串,记得加上单引号‘’
参考链接:
iOS开发之Objective-C与JavaScript的交互
http://www.cnblogs.com/zhuqil/archive/2011/08/03/2126562.html
iOS UIWebView中javascript与Objective-C交互、获取摄像头
http://www.cnblogs.com/lwme/p/ios-call-objc-camera-from-javascript-in-uiwebview.html
IOS开发之——objective-c与javascript交互
http://blog.sina.com.cn/s/blog_50e0bce501018ydu.html
17、编写自文档化的代码
编写自文档化的代码
http://www.cnblogs.com/anderslly/archive/2009/06/21/write-self-documenting-code.html
编写自文档化的代码
http://kb.cnblogs.com/page/47707/
18、objective-c与js交互
如何在Objective-C的类里面声明私有方法.
http://hi.baidu.com/shiqyn/item/52887ff19d3df61aa729885f
Objective-C中的类本身并没有私有方法这个概念,声明在 .h 文件中的方法都是公有的。不过,要想实现私有方法的效果还是有办法的,就是用Category。
// Hello.h
#import
@interface Hello : NSObject {
//变量声明
}
// 方法声明
@end
//
// Hello.m
#import "Hello.h"
@interface Hello () //=>此处Hello命名一致,后边跟括号
//=>@property (某种) aType ivarName ; 可实现私有变量
// 私有方法声明
- (void)test;
@end
@implementation Hello
// 私有方法实现
//=>@synthesize ivarName; 有私有变量的话
- (void)test {
// ..
}
// 方法实现
@end
在上面这个例子中,test 就是 Hello 类的“私有方法”了。再次证明,Category这个东东真的很强大~。
19、iphone中的delegate委托机制
Objective-C回调机制(delegate,protocol)
http://blog.sina.com.cn/s/blog_6545eb460100pyjy.html
iphone中的delegate委托机制
http://wsqwsq000.iteye.com/blog/1121155
详解Objective-C中委托和协议
http://mobile.51cto.com/iphone-283416.htm
20、iOSdelegate使用时注意
delegate方法调用前,最好先判断是否可以回调:
if([_testDelegate respondsToSelector:@selector(onResult:)])
{
[_testDelegateonResult:str];
}