首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

【iOS 开发】Xcode9 自动签名更新设备列表

内测分发测试 iOS App 的时候,在 https://developer.apple.com/account/ios/device/ 添加了设备的 UDID 之后,往往 Xcode 这边不会及时同步信息,提供一个解决办法: 去 ~/Library/MobileDevice/Provisioning 这个路径下删除所有内容(注:如果你同时管理了多个 AppleID 或者有一些无法通过 AppleID 自动同步的 provisioning profile 要防止误删) 如下图,在 Xcode 偏好设置里面点击 Download Manual Profiles 把云端管理的 provisioning profile 下载到 Xcode 把项目的 Build Target 选为真机,在自定签名的地方点按 i 按钮可以看到更新后的设备总数

优秀的个人博客,低调大师

Android开发实践:JNI层线程回调Java函数示例

JNI是Java Native Interface的缩写,是Java平台的重要特性,使得Java代码可以方便地与C/C++代码编译生成的动态链接库进行交互。本文主要给出一份示例代码(工程文件见附件),描述如何在Android的JNI层开启一个线程,并在线程中回调Java层的函数。 代码主要分为Java层(java代码)和JNI层(c语言代码),首先看看Java层的代码(Native.java)。 如上所示,Java层与JNI层的接口代码主要封装在Native类中,该类定义了三个native函数,分别完成jni库的初始化,调用jni层开启线程,调用jni层关闭线程等功能。并且提供一个回调函数(onNativeCallback),供jni层调用,并在回调函数中打印count的值。 再看看JNI层是如何开启线程并回调Java层的(native.c),关键的地方都在代码中进行了注释: 1. 头文件包含和全局变量的定义 2. 初始化函数的实现 3. 开启关闭线程的实现 4. 线程的实现(关键) 由上述代码可以看到,JNI层通过pthread库完成了线程的创建,需要特别注意的是,JNI层的线程中,必须通过全局的JavaVM来获取到环境变量,也必须通过全局的jobject获取java类对象,从而找到java端的函数,进行回调。 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1358558,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发学习笔记:浅谈显示Intent和隐式Intent

Intent寻找目标组件的两种方式: 显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的。 隐式Intent:通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间。 一.显式Intent 一般情况下,一个Android应用程序中需要多个屏幕,即是多个Activity类,并且在这些Activity之间进行切换通过Intent机制来实现的。在同一个应用程序中切换Activity时,我们通常都知道要启动的Activity具体是哪一个,因此常用显式的Intent来实现的。 下面的例子是在同一应用程序中MainActivity启动SecondActivity,下面的代码中,主要是为“转到SecondActivity”按钮添加了OnClickListener,使得按钮被点击时执行onClick()方法,onClick()方法中则利用了Intent机制,来启动SecondActivity,关键的代码是22~25行。 main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello1" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="转到SecondActivity" /> </LinearLayout> second.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello2" /> <Button android:id="@+id/secondBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="返回" /> </LinearLayout> MainActivity.java package com.android.test.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button)findViewById(R.id.btn); //响应按钮btn事件 btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //显示方式声明Intent,直接启动SecondActivity Intent it = new Intent(MainActivity.this,SecondActivity.class); //启动Activity startActivity(it); } }); } } SecondActivity.java package com.android.test.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class SecondActivity extends Activity { private Button secondBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); secondBtn=(Button)findViewById(R.id.secondBtn); //响应按钮secondBtn事件 secondBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //显示方式声明Intent,直接启动MainActivity Intent intent = new Intent(SecondActivity.this,MainActivity.class); //启动Activity startActivity(intent); } }); } } AndroidManifest.xml清单文件,16~18行为SecondActivity在清单文件里的声明 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity" android:label="@string/app_name"> </activity> </application> </manifest> 效果图: 二.隐式Intent 下面是同一应用程序中的Activity切换的例子,需要AndroidManifest.xml中增加Activity的声明,并设置对应的Intent Filter和Action,才能被Android的应用程序框架所匹配。 MainActivity.java package com.android.change.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.btn); // 响应按钮btn事件 btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 实例化Intent Intent it = new Intent(); //设置Intent的Action属性 it.setAction("com.android.activity.MY_ACTION"); // 启动Activity startActivity(it); } }); } } SecondActivity.java package com.android.change.activity; import android.app.Activity; import android.os.Bundle; public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); } } main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="转到SecondActivity" /> </LinearLayout> seond.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/second" /> </LinearLayout> AndroidManifest.xml文件的18,19行修改了Intent Filter,这样SecondActivity才能够接收到MainActivity发送的Intent。因为在MainActivity的Intent发送的动作为"com.android.activity.MY_ACTION",而在18行里,SecondActivity设置的Action也为"com.android.activity.MY_ACTION",这样就能进行匹配。 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.change.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity" > <intent-filter> <action android:name = "com.android.activity.MY_ACTION" /> <category android:name = "android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest> 效果图: 对于显示Intent,Android不需要再去做解析,因为目标组件很明确。Android需要解析的是隐式Intent,通过解析,将Intent映射给可以处理该Intent的Activity,Service等。Intent的解析机制主要是通过查找已经注册在AndroidManifest.xml中的所有IntentFilter以及其中定义的Intent,最终找到匹配的Intent。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/655132

优秀的个人博客,低调大师

iOS开发-Get请求,Post请求,同步请求和异步请求

标题中的Get和Post是请求的两种方式,同步和异步属于实现的方法,Get方式有同步和异步两种方法,Post同理也有两种。稍微有点Web知识的,对Get和Post应该不会陌生,常说的请求处理响应,基本上请求的是都是这两个哥们,Http最开始定义的与服务器交互的方式有八种,不过随着时间的进化,现在基本上使用的只剩下这两种,有兴趣的可以参考本人之前的博客Http协议中Get和Post的浅谈,iOS客户端需要和服务端打交道,Get和Post是跑不了的,本文中包含iOS代码和少量Java服务端代码,开始正题吧. Get和Post同步请求 Get和Post同步请求的时候最常见的是登录,输入各种密码才能看到的功能,必须是同步,异步在Web上局部刷新的时候用的比较多,比较耗时的时候执行异步请求,可以让客户先看到一部分功能,然后慢慢刷新,举个例子就是餐馆吃饭的时候点了十几个菜,给你先上一两个吃着,之后给别人上,剩下的慢慢上。大概就是这样的。弄了几个按钮先上图: 先贴下同步请求的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 //设置URL路径 NSString *urlStr=[ NSString stringWithFormat:@ "http://localhost:8080/MyWeb/Book?username=%@&password=%@&type=get" ,@ "博客园" ,@ "keso" ]; urlStr=[urlStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding ]; NSURL *url=[ NSURL URLWithString:urlStr]; //通过URL设置网络请求 NSURLRequest *request = [[ NSURLRequest alloc]initWithURL:url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; NSError *error= nil ; //获取服务器数据 NSData *requestData= [ NSURLConnection sendSynchronousRequest:request returningResponse: nil error:&error]; if (error) { NSLog (@ "错误信息:%@" ,[error localizedDescription]); } else { NSString *result=[[ NSString alloc]initWithData:requestData encoding: NSUTF8StringEncoding ]; NSLog (@ "返回结果:%@" ,result); } 代码很多,需要解释一下: ①URL如果有中文无法传递,需要编码一下: 1 [urlStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding ]; ②设置网路请求中的代码,有两个参数,最后一个设置请求的时间,这个不用说什么,重点说下缓存策略cachePolicy,系统中的定义如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 typedef NS_ENUM ( NSUInteger , NSURLRequestCachePolicy ) { NSURLRequestUseProtocolCachePolicy = 0, NSURLRequestReloadIgnoringLocalCacheData = 1, NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData , NSURLRequestReturnCacheDataElseLoad = 2, NSURLRequestReturnCacheDataDontLoad = 3, NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented }; NSURLRequestUseProtocolCachePolicy(基础策略),NSURLRequestReloadIgnoringLocalCacheData(忽略本地缓存); NSURLRequestReloadIgnoringLocalAndRemoteCacheData(无视任何缓存策略,无论是本地的还是远程的,总是从原地址重新下载); NSURLRequestReturnCacheDataElseLoad(首先使用缓存,如果没有本地缓存,才从原地址下载); NSURLRequestReturnCacheDataDontLoad(使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作); NSURLRequestReloadRevalidatingCacheData(如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载); Java服务端代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType( "text/html;charset=utf-8;" ); PrintWriter out = response.getWriter(); System.out.println(request.getParameter( "username" )); System.out.println(request.getParameter( "password" )); if (request.getParameter( "type" ) == null ) { out.print( "默认测试" ); } else { if (request.getParameter( "type" ).equals( "async" )) { out.print( "异步Get请求" ); } else { out.print( "Get请求" ); } } } 最终效果如下: Post请求的代码,基本跟Get类型,有注释,就不多解释了: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //设置URL NSURL *url=[ NSURL URLWithString:@ "http://localhost:8080/MyWeb/Book" ]; //创建请求 NSMutableURLRequest *request = [[ NSMutableURLRequest alloc]initWithURL:url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; [request setHTTPMethod:@ "POST" ]; //设置请求方式为POST,默认为GET NSString *param= @ "Name=博客园&Address=http://www.cnblogs.com/xiaofeixiang&Type=post" ;//设置参数 NSData *data = [param dataUsingEncoding: NSUTF8StringEncoding ]; [request setHTTPBody:data]; //连接服务器 NSData *received = [ NSURLConnection sendSynchronousRequest:request returningResponse: nil error: nil ]; NSString *result= [[ NSString alloc]initWithData:received encoding: NSUTF8StringEncoding ]; NSLog (@ "%@" ,result); Java服务端代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding( "utf-8" ); response.setContentType( "text/html;charset=utf-8" ); PrintWriter out = response.getWriter(); System.out.println( "姓名:" + request.getParameter( "Name" )); System.out.println( "地址:" + request.getParameter( "Address" )); System.out.println( "类型:" + request.getParameter( "Type" )); if (request.getParameter( "Type" ).equals( "async" )) { out.print( "异步请求" ); } else { out.print( "Post请求" ); } } 效果如下: Get和Post异步请求 异步实现的时候需要实现协议NSURLConnectionDataDelegate,Get异步代码如下: 1 2 3 4 5 6 7 8 9 10 //设置URL路径 NSString *urlStr=[ NSString stringWithFormat:@ "http://localhost:8080/MyWeb/Book?username=%@&password=%s&type=async" ,@ "FlyElephant" , "keso" ]; urlStr=[urlStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding ]; NSURL *url=[ NSURL URLWithString:urlStr]; //创建请求 NSURLRequest *request = [[ NSURLRequest alloc]initWithURL:url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; //连接服务器 NSURLConnection *connection = [[ NSURLConnection alloc]initWithRequest:request delegate: self ]; 实现协议的连接过程的方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -( void )connection:( NSURLConnection *)connection didReceiveResponse:( NSURLResponse *)response{ NSHTTPURLResponse *res = ( NSHTTPURLResponse *)response; NSLog (@ "%@" ,[res allHeaderFields]); self .myResult = [ NSMutableData data]; } ////接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次 -( void )connection:( NSURLConnection *)connection didReceiveData:( NSData *)data { [ self .myResult appendData:data]; } //数据传输完成之后执行方法 -( void )connectionDidFinishLoading:( NSURLConnection *)connection { NSString *receiveStr = [[ NSString alloc]initWithData: self .myResult encoding: NSUTF8StringEncoding ]; NSLog (@ "%@" ,receiveStr); } //网络请求时出现错误(断网,连接超时)执行方法 -( void )connection:( NSURLConnection *)connection didFailWithError:( NSError *)error { NSLog (@ "%@" ,[error localizedDescription]); } 异步传输的过程数据需要拼接,所以这个时候需要设置一个属性接收数据: 1 @property (strong, nonatomic ) NSMutableData *myResult; 效果如下: Post异步传递代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //设置URL NSURL *url=[ NSURL URLWithString:@ "http://localhost:8080/MyWeb/Book" ]; //设置请求 NSMutableURLRequest *request = [[ NSMutableURLRequest alloc]initWithURL:url cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; [request setHTTPMethod:@ "POST" ]; //设置请求方式为POST,默认为GET NSString *param= @ "Name=keso&Address=http://www.cnblogs.com/xiaofeixiang&Type=async" ;//设置参数 NSData *data = [param dataUsingEncoding: NSUTF8StringEncoding ]; [request setHTTPBody:data]; //连接服务器 NSURLConnection *connection = [[ NSURLConnection alloc]initWithRequest:request delegate: self ]; 效果如下: 异步的请求比较简单,需要的方法都已经被封装好了,需要注意数据是动态拼接的,请求的代码都是在Java Servlet中实现的,Java项目中的目录如下: Book.java中代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class Book */ @WebServlet ( "/Book" ) public class Book extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public Book() { super (); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType( "text/html;charset=utf-8;" ); PrintWriter out = response.getWriter(); System.out.println(request.getParameter( "username" )); System.out.println(request.getParameter( "password" )); if (request.getParameter( "type" ) == null ) { out.print( "默认测试" ); } else { if (request.getParameter( "type" ).equals( "async" )) { out.print( "异步Get请求" ); } else { out.print( "Get请求" ); } } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub request.setCharacterEncoding( "utf-8" ); response.setContentType( "text/html;charset=utf-8" ); PrintWriter out = response.getWriter(); System.out.println( "姓名:" + request.getParameter( "Name" )); System.out.println( "地址:" + request.getParameter( "Address" )); System.out.println( "类型:" + request.getParameter( "Type" )); if (request.getParameter( "Type" ).equals( "async" )) { out.print( "异步Post请求" ); } else { out.print( "Post请求" ); } } } Get和Post总结 ①同步请求一旦发送,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作(例如登录验证); ②异步请求不会阻塞主线程,会建立一个新的线程来操作,发出异步请求后,依然可以对UI进行操作,程序可以继续运行; ③Get请求,将参数直接写在访问路径上,容易被外界看到,安全性不高,地址最多255字节; ④Post请求,将参数放到body里面,安全性高,不易被捕获; 本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4306786.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

苹果iOS开发深入浅出Cocoa之类与对象

最近打算写一些ObjC中比较底层的东西,尤其是 runtime 相关的。苹果已经将 ObjC runtime 代码开源了,我们可以从:http://opensource.apple.com/source/objc4/objc4-493.9/runtime/浏览源代码,或点此下载源代码。 从哪里入手呢?那当然是最基本的类与对象。与C++相比,ObjC中的类与对象结构要简洁与一致得多(参考《深度探索C++对象模型》,你就知道C++中类与对象结构的复杂)。本文将详细讲解ObjC中类与对象的结构,下回将讲如何在 runtime 时操作类。 我们可以在/usr/include/objc/objc.h 和 runtime.h 中找到对 class 与 object 的定义: typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id; Class 是一个 objc_class 结构类型的指针;而 id(任意对象) 是一个 objc_object 结构类型的指针,其第一个成员是一个 objc_class 结构类型的指针。注意这里有一关键的引申解读:内存布局以一个 objc_class 指针为开始的所有东东都可以当做一个 object 来对待! 那 objc_class 又是怎样一个结构体呢?且看: struct objc_class { struct objc_class* isa; struct objc_class* super_class; const char* name; long version; long info; long instance_size; struct objc_ivar_list* ivars; struct objc_method_list** methodLists; struct objc_cache* cache; struct objc_protocol_list* protocols; } objc_class 结构体的各成员介绍如下: isa:是一个 objc_class 类型的指针,看到这里,想起我前面的引申解读了没?内存布局以一个 objc_class 指针为开始的所有东东都可以当做一个 object 来对待! 这就是说 objc_class 或者说类其实也可以当做一个 objc_object 对象来对待!对象是对象,类也是对象,是不是有点混淆?别急,ObjC发明(or 重用)了一个术语来区分这两种不同的对象:类对象(class object)与实例对象(instance object)。OK,名称混淆的问题解决,下面我将使用这两个术语来区分不同的对象,而使用“对象”这一术语来泛指所有的对象。ObjC还对类对象与实例对象中的 isa 所指向的类结构作了不同的命名:类对象中的 isa 指向类结构被称作 metaclass,metaclass 存储类的static类成员变量与static类成员方法(+开头的方法);实例对象中的 isa 指向类结构称作 class(普通的),class 结构存储类的普通成员变量与普通成员方法(-开头的方法)。 super_class:一看就明白,指向该类的父类呗!如果该类已经是最顶层的根类(如 NSObject 或 NSProxy),那么 super_class 就为 NULL。 好,先中断一下其他类结构成员的介绍,让我们厘清一下在继承层次中,子类,父类,根类(这些都是普通 class)以及其对应的 metaclass 的 isa 与 super_class 之间关系: 规则一:类的实例对象的 isa 指向该类;该类的 isa 指向该类的 metaclass; 规则二:类的 super_class 指向其父类,如果该类为根类则值为 NULL; 规则三:metaclass 的 isa 指向根 metaclass,如果该 metaclass 是根 metaclass 则指向自身; 规则四:metaclass 的 super_class 指向父 metaclass,如果该 metaclass 是根 metaclass 则指向该 metaclass 对应的类; 好吧,文字总是那么乏力,有图有真相! 那么 class 与 metaclass 有什么区别呢? class 是 instance object 的类类型。当我们向实例对象发送消息(实例方法)时,我们在该实例对象的 class 结构的 methodlists 中去查找响应的函数,如果没找到匹配的响应函数则在该 class 的父类中的 methodlists 去查找(查找链为上图的中间那一排)。如下面的代码中,向str 实例对象发送 lowercaseString 消息,会在 NSString 类结构的 methodlists 中去查找 lowercaseString 的响应函数。 NSString * str;[str lowercaseString]; metaclass 是 class object 的类类型。当我们向类对象发送消息(类方法)时,我们在该类对象的 metaclass 结构的 methodlists 中去查找响应的函数,如果没有找到匹配的响应函数则在该 metaclass 的父类中的 methodlists 去查找(查找链为上图的最右边那一排)。如下面的代码中,向 NSString 类对象发送 stringWithString 消息,会在 NSString 的 metaclass 类结构的 methodlists 中去查找 stringWithString 的响应函数。 [NSString stringWithString:@"str"]; 好,至此我们明白了类的结构层次,让我们接着看类结构中的其他成员。 name:一个 C 字符串,指示类的名称。我们可以在运行期,通过这个名称查找到该类(通过:id objc_getClass(const char *aClassName))或该类的 metaclass(id objc_getMetaClass(const char *aClassName)); version:类的版本信息,默认初始化为 0。我们可以在运行期对其进行修改(class_setVersion)或获取(class_getVersion)。 info:供运行期使用的一些位标识。有如下一些位掩码: CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含实例方法和变量; CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法; CLS_INITIALIZED (0x4L) 表示该类已经被运行期初始化了,这个标识位只被 objc_addClass 所设置; CLS_POSING (0x8L) 表示该类被 pose 成其他的类;(poseclass 在ObjC 2.0中被废弃了); CLS_MAPPED (0x10L) 为ObjC运行期所使用 CLS_FLUSH_CACHE (0x20L) 为ObjC运行期所使用 CLS_GROW_CACHE (0x40L) 为ObjC运行期所使用 CLS_NEED_BIND (0x80L) 为ObjC运行期所使用 CLS_METHOD_ARRAY (0x100L) 该标志位指示 methodlists 是指向一个 objc_method_list 还是一个包含 objc_method_list 指针的数组; instance_size:该类的实例变量大小(包括从父类继承下来的实例变量); ivars:指向 objc_ivar_list 的指针,存储每个实例变量的内存地址,如果该类没有任何实例变量则为 NULL; methodLists:与 info 的一些标志位有关,CLS_METHOD_ARRAY 标识位决定其指向的东西(是指向单个 objc_method_list还是一个 objc_method_list 指针数组),如果 info 设置了 CLS_CLASS 则 objc_method_list 存储实例方法,如果设置的是 CLS_META 则存储类方法; cache:指向 objc_cache 的指针,用来缓存最近使用的方法,以提高效率; protocols:指向 objc_protocol_list 的指针,存储该类声明要遵守的正式协议。 总结: ObjC 为每个类的定义生成两个 objc_class ,一个即普通的 class,另一个即 metaclass。我们可以在运行期创建这两个 objc_class 数据结构,然后使用 objc_addClass 动态地创建新的类定义。这个够动态够强大的吧?下回讲演示如何在运行期动态创建新类。 本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/782033,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发8——利用pull解析器读写XML文件

一、基本介绍 对XML解析有SAX和DOM等多种方式,Android中极力推荐xmlpull方式解析xml。xmlpull不仅可用在Android上同样也适用于javase,但在javase环境中需自己获取xmlpull所依赖的类库,kxml2-2.3.0.jar,xmlpull_1_1_3_4c.jar。 jar包下载网址http://www.xmlpull.org/http://kxml.sourceforge.net/ 二、例子 读取到xml的声明返回数字0 START_DOCUMENT; 读取到xml的结束返回数字1 END_DOCUMENT ; 读取到xml的开始标签返回数字2 START_TAG 读取到xml的结束标签返回数字3 END_TAG 读取到xml的文本返回数字4 TEXT <?xmlversion="1.0"encoding="UTF-8"?> <people> <personid="001"> <name>XY1</name> <age>22</age> </person> <personid="002"> <name>XY2</name> <age>22</age> </person> </people> packagecn.xy.service; importjava.io.InputStream; importjava.io.OutputStream; importjava.util.ArrayList; importjava.util.List; importorg.xmlpull.v1.XmlPullParser; importorg.xmlpull.v1.XmlSerializer; importandroid.util.Xml; importcn.xy.model.Person; publicclassPersonService { publicListgetPeople(InputStreamxml)throwsException { Listlst=null; Personperson=null; //利用ANDROID提供的API快速获得pull解析器 XmlPullParserpullParser=Xml.newPullParser(); //设置需要解析的XML数据 pullParser.setInput(xml,"UTF-8"); //取得事件 intevent=pullParser.getEventType(); //若为解析到末尾 while(event!=XmlPullParser.END_DOCUMENT)//文档结束 { StringnodeName=pullParser.getName(); switch(event) { caseXmlPullParser.START_DOCUMENT://文档开始 lst=newArrayList(); break; caseXmlPullParser.START_TAG://标签开始 if("person".equals(nodeName)) { Stringid=pullParser.getAttributeValue(0); person=newPerson(); person.setId(id); } if("name".equals(nodeName)) { Stringname=pullParser.nextText(); person.setName(name); } if("age".equals(nodeName)) { intage=Integer.valueOf(pullParser.nextText()); person.setAge(age); } break; caseXmlPullParser.END_TAG://标签结束 if("person".equals(nodeName)) { lst.add(person); person=null; } break; } event=pullParser.next();//下一个标签 } returnlst; } publicvoidsaveDataToXML(OutputStreamos,Listlst)throwsException { XmlSerializerxs=Xml.newSerializer(); xs.setOutput(os,"UTF-8"); xs.startDocument("UTF-8",true); xs.startTag(null,"people"); for(Personp:lst) { xs.startTag(null,"person"); xs.attribute(null,"person",p.getId()); xs.startTag(null,"name"); xs.text(p.getName()); xs.endTag(null,"name"); xs.startTag(null,"age"); xs.text(p.getAge().toString()); xs.endTag(null,"age"); xs.endTag(null,"person"); } xs.endTag(null,"people"); xs.endDocument(); os.flush(); os.close(); } } publicclassTestClassextendsAndroidTestCase { publicvoidtestPeople()throwsException { PersonServiceps=newPersonService(); InputStreamxml=this.getClass().getClassLoader().getResourceAsStream("person.xml"); Listlst=ps.getPeople(xml); Assert.assertEquals("XY1",lst.get(0).getName()); } publicvoidtestSave()throwsException { PersonServiceps=newPersonService(); Listlst=newArrayList(); lst.add(newPerson("0001","XY0001",20)); lst.add(newPerson("0002","XY0002",20)); FilexmlFile=newFile(this.getContext().getFilesDir(),"xy.xml");//data/data/packagename/files OutputStreamos=newFileOutputStream(xmlFile); ps.saveDataToXML(os,lst); } } 本文参考自金旭亮老师的《.NET 4.0面向对象编程漫谈》有关代理的内容 本文转自IT徐胖子的专栏博客51CTO博客,原文链接http://blog.51cto.com/woshixy/1079595如需转载请自行联系原作者 woshixuye111

优秀的个人博客,低调大师

接口自动化测试PHPUnit-框架代码开发1

经过上一篇的架构设计之后,我们就要开始编写代码了,因为涉及代码较多,所以将分多次进行讲解。 先看一张整体结构图 今天我们先来看看testcase文件里的编写。此处我们以之前的老黄历接口为例。 lhl_test.php内容如下: <?php //代码获取点击链接加入QQ群 522720170:https://jq.qq.com/?_wv=1027&k=5C08ATe //引入一些必要的文件,暂时别管,后面会说到 require_once("../commons/require.php"); use PHPUnitFrameworkTestCase; class LhlTest extends TestCase { //测试用例必须以 test 开头,否则 phpunit 不识别 public function testLhl() { //选择运行环境。此处把host配置到了文件中,直接读取文件内容 $rc=new ReadConfig(); $url=$rc->get_host("online") ; echo $url; //拼接完整的请求串 $get_params="date=2017-11-11&key=填写你申请的key"; $url=$url."?".$get_params; $content=Transfer::get($url); //对返回的json结果进行编码,也就是转换为php可以认识的对象,方便后续使用 $data= json_decode($content,true); print_r($data); if(is_null($data)==false) { //断言,如果返回的error_code为0说明接口成功 $this->assertEquals('0',$data['error_code'],"failed"); print("successed"); } } } ?> 本文转自 小强测试帮 51CTO博客,原文链接:http://blog.51cto.com/xqtesting/1982675,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册