精华内容
下载资源
问答
  • 客户端:Swift iOSJava Android,JS webapp,可编写脚本的命令行; chatbots Tinode即时消息服务器即时消息服务器。 纯Go(授权GPL 3.0)后端,Java,Javascript和Swift的客户端绑定以及对C ++,C#,Go,Java,...
  • JAVA-ios流与文件编写

    2020-08-02 22:34:07
    Java中通过流来读写文件,流是指一连串流动的字符,是以先进先出方式发送信息的通道。 输入/输出流与数据源: Java流的分类: 输入输出流是相对于计算机内存来说的。 字节流与字符流的区别 字符流的底层就是字节流。...

    IO流与文件读写

    学习目标
    掌握File类的常用方法
    掌握文件读写操作
    掌握字节流与字符流的区别
    文件读写
    Java中通过流来读写文件,流是指一连串流动的字符,是以先进先出方式发送信息的通道。

    输入/输出流与数据源:

    Java流的分类:

    输入输出流是相对于计算机内存来说的。

    字节流与字符流的区别
    字符流的底层就是字节流。而字符流主要是读取文本文件内容的,可以一个字符一个字符的读取,也可以一行一行的读取文本文件内容,而字节流读取单位为byte。byte作为计算机存储最基本单位,可以用字节流来读取很多其他格式的文件,比如图片视频等等。基于B/S和C/S的文件传输都可以采用字节流的形式。在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。只是读写文件,和文件内容无关的,一般选择字节流。
    字节流就是按照字节来进行传输,字符流是按照字符来传输.最基本的是字节流,字符流可以说是对字节流的一个包装流,比如你知道了一个字符是8个字节,那么你让字节流一次传输8个字节,那不就相当于一次传输一个字符,也就是字符流了。

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?
    实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件,如图:

    下面以两个写文件的操作为主进行比较,但是在操作时字节流和字符流的操作完成之后都不关闭输出流。
    范例:使用字节流不关闭执行:
    // 通过字节流 写文件
    public static void ByteWrite() {
    File file = new File(“d:\test\test.txt”);
    try {
    OutputStream outputStream = new FileOutputStream(file);
    String textString = “Hello World!!!”;
    byte[] data = textString.getBytes();
    outputStream.write(data);
    //outputStream.close();
    } catch (IOException e) {
    System.out.println(“字节流写入文件出错。”);
    e.printStackTrace();
    }
    }

    此时没有关闭字节流操作,但是文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的。而下面继续使用字符流完成,再观察效果。
    范例:使用字符流不关闭执行:
    // 通过字符流 写文件
    public static void StringWrite() {
    File file = new File(“d:\test\test.txt”);
    try {
    FileWriter writer = new FileWriter(file);
    String textString = “Hello World!!!”;
    writer.write(textString);
    // writer.flush();
    // writer.close();
    } catch (IOException e) {
    System.out.println(“字符流写入文件出错.”);
    e.printStackTrace();
    }
    }
    程序运行结果:

    程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。

    在开发中是使用字节流好还是字符流好呢?
    回答:使用字节流更好。所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所以在开发中,字节流使用较为广泛。
    如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)。
    使用FileInputStream读取文本文件
    示例代码:
    /**

    • 文件读取
      /
      public static void readFile(){
      File file=new File(“D:/test/students.txt”);
      try {
      InputStreamReader read = new InputStreamReader(new FileInputStream(file), “utf8”);
      BufferedReader bufferedReader = new BufferedReader(read);
      String lineTxt = null;
      //循环输出每一行内容
      while ((lineTxt = bufferedReader.readLine()) != null) {
      System.out.println(lineTxt);
      }
      read.close();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      或者:
      /
      • 读取文件
        */
        public static String read(String fileName) {
        File f = new File(fileName);
        if (!f.exists()) {
        return “File not found!”;
        }
        FileInputStream fs;
        String result = null;
        try {
        fs = new FileInputStream(f);
        byte[] b = new byte[fs.available()];
        fs.read(b);
        fs.close();
        result = new String(b);
        } catch (Exception e) {
        e.printStackTrace();
        }

        return result;
        }

    InputStream类常用方法及解析:
    public void close() throws IOException{}
    关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。
    protected void finalize()throws IOException {}
    这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。
    public int read(int r)throws IOException{}
    这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。
    public int read(byte[] r) throws IOException{}
    这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。
    public int available() throws IOException{}
    返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。
    使用FileOutputStream 写文本文件
    示例代码:
    import java.io.FileOutputStream;
    import java.io.IOException;

    public class FileOutputStreamTest {

    public static void main(String[] args) {
    	FileOutputStream fos=null;
    	 try {
    		 String str ="好好学习Java";
             byte[] words  = str.getBytes();
             fos = new FileOutputStream("D:\\myDoc\\hello.txt");
             fos.write(words, 0, words.length);
             System.out.println("hello文件已更新!");
          }catch (IOException obj) {
        	  System.out.println("创建文件时出错!");
          }finally{
        	  try{
        		  if(fos!=null)
        			  fos.close();
        	  }catch (IOException e) {
    	    	 e.printStackTrace();
        	  }
          }
    }
    

    }
    OutputStream类常用方法及解析:
    public void close() throws IOException{}
    关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。
    protected void finalize()throws IOException {}
    这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。
    public void write(int w)throws IOException{}
    这个方法把指定的字节写到输出流中。
    public void write(byte[] w)
    把指定数组中w.length长度的字节写到OutputStream中。

    File类
    Java程序通过java.io.File 类对文件进行访问。File 类的常用方法如下:
    方法名称
    说 明

    boolean exists( )
    判断文件或目录是否存在

    boolean isFile( )
    判断是否是文件

    boolean isDirectory( )
    判断是否是目录

    String getPath( )
    返回此对象表示的文件的相对路径名

    String getAbsolutePath( )
    返回此对象表示的文件的绝对路径名

    String getName( )
    返回此对象表示的文件或目录的名称

    boolean delete( )
    删除此对象指定的文件或目录

    boolean createNewFile( )
    创建名称的空文件,不创建文件夹

    long length()
    返回文件的长度,单位为字节, 如果文件不存在,则返回 0L

    File类的操作示例如下:
    import java.io.*;
    public class FileMethods {
    public static void main(String[] args) {
    FileMethods fm=new FileMethods();
    File file=null;
    file=new File(“D:\myDoc\test.txt”);
    //fm.create(file);
    fm.showFileInfo(file);
    //fm.delete(file);
    }
    /**
    * 创建文件的方法
    * @param file 文件对象
    /
    public void create(File file){
    if(!file.exists()){
    try {
    file.createNewFile();
    System.out.println(“文件已创建!”);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    /
    *
    * 删除文件
    * @param file 文件对象
    */
    public void delete(File file){
    if(file.exists()){
    file.delete();
    System.out.println(“文件已删除!”);
    }
    }

    /**
    * 显示文件信息
    * @param file 文件对象
    */
    public void showFileInfo(File file){
    if(file.exists()){ //判断文件是否存在
    if(file.isFile()){ //如果是文件
    System.out.println(“名称:” + file .getName());
    System.out.println("相对路径: " + file.getPath());
    System.out.println(“绝对路径: " + file.getAbsolutePath());
    System.out.println(“文件大小:” + file.length()+ " 字节”);
    }
    if(file.isDirectory()){
    System.out.println(“此文件是目录”);
    }
    }else
    System.out.println(“文件不存在”);
    }
    }

    创建目录
    File类中有两个方法可以用来创建文件夹:
    mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。
    mkdirs()方法创建一个文件夹和它的所有父文件夹。

    下面的例子创建 “/tmp/user/java/bin"文件夹:
    import java.io.File;
    public class CreateDir {
    public static void main(String args[]) {
    String dirname = “/tmp/user/java/bin”;
    File d = new File(dirname);
    // 现在创建目录
    d.mkdirs();
    }
    }
    编译并执行上面代码来创建目录 “/tmp/user/java/bin”。
    注意:Java 在 UNIX 和 Windows 自动按约定分辨文件路径分隔符。如果你在 Windows 版本的 Java 中使用分隔符 (/) ,路径依然能够被正确解析。
    读取目录
    一个目录其实就是一个 File 对象,它包含其他文件和文件夹。
    如果创建一个 File 对象并且它是一个目录,那么调用 isDirectory() 方法会返回 true。可以通过调用该对象上的 list() 方法,来提取它包含的文件和文件夹的列表。下面展示的例子说明如何使用 list() 方法来检查一个文件夹中包含的内容:
    import java.io.File;
    public class DirList {
    public static void main(String args[]) {
    String dirname = “/tmp”;
    File f1 = new File(dirname);
    if (f1.isDirectory()) {
    System.out.println(“目录 " + dirname);
    String s[] = f1.list();
    for (int i = 0; i < s.length; i++) {
    File f = new File(dirname + “/” + s[i]);
    if (f.isDirectory()) {
    System.out.println(s[i] + " 是一个目录”);
    } else {
    System.out.println(s[i] + " 是一个文件”);
    }
    }
    } else {
    System.out.println(dirname + " 不是一个目录");
    }
    }
    }

    删除目录或文件
    删除文件可以使用 java.io.File.delete() 方法。
    以下代码会删除目录 /tmp/java/,需要注意的是当删除某一目录时,必须保证该目录下没有其他文件才能正确删除,否则将删除失败。
    import java.io.File;

    public class DeleteFileDemo {
    public static void main(String args[]) {
    // 这里修改为自己的测试目录
    File folder = new File("/tmp/java/");
    deleteFolder(folder);
    }

    // 删除文件及目录
    public static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteFolder(f);
                } else {
                    f.delete();
                }
            }
        }
        folder.delete();
    }
    
    展开全文
  • Appium For Android and IOS By Java

    千次阅读 2016-10-29 13:54:44
    如何编写一个Case Android Example IOS Example 总结 一. 前言 自动化测试趋势近几年也越来越火了,在APP泛滥的时代,对APP进行自动化测试也备受测试人员追捧,我也不例外。二. 项目介绍 项目名称:...

    目录:

    1. 前言
    2. 项目介绍
    3. 项目结构
    4. 如何编写一个Case
    5. Android Example
    6. IOS Example
    7. 总结

    一. 前言
    自动化测试趋势近几年也越来越火了,在APP泛滥的时代,对APP进行自动化测试也备受测试人员追捧,我也不例外。

    二. 项目介绍
    项目名称:YYAPPAutomation
    名称介绍:有鱼股票APP自动化
    项目功能:对有鱼股票APP Android版本和IOS版本进行自动化测试
    项目依赖:APPIUM(http://appium.io/
    项目框架:Java + Maven + Testng + Python脚本

    三. 项目结构
    这里写图片描述

    文件目录介绍:

    1. apps文件夹:安放Android apk和IOS ipa
    2. python文件夹: 安放Python文件,用shell调用python进行安装apk或ipa文件、注册脚本、检查是否注册脚本等
    3. resources-android文件夹:安放Android testng xml
    4. resources-ios文件夹:安放IOS testng xml
    5. screenshot文件夹: 安放失败截图.jpg
    6. src文件夹: 测试代码
    7. target文件夹:
    8. test-output文件夹:安放测试报告

    测试代码:
    这里写图片描述

    文件目录介绍:

    1. debug文件夹:编写调试代码
    2. flow文件夹:编写测试场景
    3. listener文件夹:编写监听器,如:重写测试报告、单个Case执行失败后会进行retry,进行重试的次数可配置
    4. page文件夹:编写单个页面所有元素,即获取元素
    5. service文件夹:编写单个页面所有元素的相关事件,如:点击、获取元素显示文字
    6. testcase文件夹:编写测试用例
    7. util文件夹:公共文件夹,编写静态方法,如:获取appium连接、shell脚本执行、正则匹配APP显示数据的正确性等

    EX. Page文件夹:
    这里写图片描述

    获取Appium连接:

    /**
    * 连接APPIUM SERVER
    * 
    * @param url
    * @param port
    * @param propertyFileName
    * @return
    * @throws MalformedURLException
    */
    @SuppressWarnings("rawtypes")
    public static AppiumDriver getDriver(String url, String port, String device, String udid, String env) throws MalformedURLException {
            File classpathRoot = new File(System.getProperty("user.dir"));
            DesiredCapabilities capabilities = null;
            if (device.equals("ios")) {
                File propertyFile = new File(classpathRoot.getAbsolutePath() + "//resources-ios/based.properties");
                capabilities = getBasedCapabilities(propertyFile);
                if(env.equalsIgnoreCase("beta")) {
                    capabilities.setCapability("app", classpathRoot.getAbsolutePath() + "//apps//RuiFuTech_Beta.ipa");
                }
                if(env.equalsIgnoreCase("live")) {
                    capabilities.setCapability("app", classpathRoot.getAbsolutePath() + "//apps//RuiFuTech_Live.ipa");
                }
                return new IOSDriver(new URL("http://" + url + ":" + port + "/wd/hub"), capabilities);
            }else if (device.equals("android")) {
                capabilities = getBasedCapabilities(new File(classpathRoot, "//resources-android//based.properties"));
                if(env.equalsIgnoreCase("beta")) {
                    packageName = capabilities.getCapability("appPackage").toString() + ".debug";
                    capabilities.setCapability("appPackage", packageName);
                    capabilities.setCapability("app", classpathRoot.getAbsolutePath() + "//apps//RuiFuTech_Beta.apk");
                }
                if(env.equalsIgnoreCase("live")) {
                    packageName = capabilities.getCapability("appPackage").toString();
                    capabilities.setCapability("app", classpathRoot.getAbsolutePath() + "//apps//RuiFuTech_Live.apk");
                }
                 capabilities.setCapability("udid", udid);      
                return new AndroidDriver(new URL("http://" + url + ":" + port + "/wd/hub"), capabilities);
            }else {
                return null;
        }   
    }

    查看一下Android的based.properties

    platformName=Android
    platformVersion=4.4.2
    deviceName=5LM0216111012735
    appPackage=com.ruifusoft.finance.app
    appActivity=com.ruifusoft.ui.SplashActivity
    unicodeKeyboard=true
    resetKeyboard=true

    查看一下IOS的based.properties

    appium-version=1.0
    platformName=iOS
    platformVersion=9.3
    deviceName=iPhone 5s

    四. 如何编写一个Case
    第一步:开启Appium Android服务
    第二步:Android开启android-sdk tool下的uiautomatorviewer进行抓取元素(resourceId形式)/IOS开启Appium inspector进行抓取元素(Xpath形式)
    第三步:将抓取的元素写入Page文件夹相应地方
    第四步:在Service文件夹相应创建对应Page的service文件,对元素进行点击事件编写和获取文字编写,输入框数据文字方法编写等
    第五步:在Flow文件夹创建测试场景,如:注册测试场景 registerFlow,将注册相关联的页面进行调用Service层的方法进行测试场景构建
    第六步:在TestCase文件夹创建相应的测试用例,调用写好的registerFlow

    五. Android Example
    备注:待续…

    六. IOS Example
    备注:待续…

    七. 总结
    “路漫漫其修远兮 吾将上下而求索”自动化APP测试尚未技术成熟,在写APP自动化的过程中也发现了很多难处(如:测试场景无法全部覆盖,一些case需要和外部提供数据进行联调测试、自动化测试场景写多了执行的时间会越来越长、Android机型过多,对于自动化代码需要编写适配、IOS是每对一个元素进行操作就获取一次整个页面数据,导致某个页面数据过多的页面,下面的页面无法很多的获取到,甚至有时候获取不到导致case失败)需要一个一个的测试人员去探索发现解决方案,分享出来,从而提高自动化测试技术的发展。

    整个项目文档:百度网盘

    欢迎加QQ群 -> 阳台测试 -> 239547991(群号)

    展开全文
  • 可以通过编写自定义适配器来支持其他数据库。 Tinode不是XMPP / Jabber。 它与XMPP不兼容。 它是XMPP的替代品。 从表面上看,它很像开源的WhatsApp或Telegram。 版本0.16。 这是beta质量的软件:功能齐全,但可能...
  • 目前iOS开发主推的官方语言有两种:Objective-C 和 Swift。 今天,小编帮助大家更加熟悉Objective-C,并且聊一聊如何才能编写高质量的OC代码。 一、Objective-C的起源 谈到Objective-C语言的出现,可要比Java还要...

    前言:

    目前iOS开发主推的官方语言有两种:Objective-C 和 Swift。

    今天,小编帮助大家更加熟悉Objective-C,并且聊一聊如何才能编写高质量的OC代码。

    一、Objective-C的起源

    谈到Objective-C语言的出现,可要比Java还要早十多年。

    Java在1995年推出,而Objective-C早在1980年代就已经出现了。

    Objective-C (OC)由Smalltalk语言演化而来,后者是消息传递型语言的鼻祖。

    • 消息传递?是的!引入了今天的第一个Key :消息传递。

    OC与C++、Java等面向对象语言类似,但又有很大区别。为什么这么说呢?首先要引入的话题就是OC使用消息传递机制,而并非C++、Java使用函数调用机制。

    // Objective-C : messaging (消息传递)
    Object *obj = [Object new];
    [obj performWith:parameter1 and:parameter2];
    
    // C++: function calling(函数调用)
    Object *obj = new Object;
    obj->perform(parameter1, parameter2);
    

    区别:

    • 消息传递:运行时所执行的代码由运行时环境决定(runtime)

    • 函数调用:运行时所执行的代码由编译器决定

    简单来说,OC总在运行时才会去查找真正所要调用的方法,编译器并不用关心接收消息的对象是什么类型,接收消息的对象也是在运行时才工作,其过程叫做动态绑定(dynamic binding)。而其他大部分面向对象语言,会在运行时查找“虚方法表”(virtual table)来查出执行的方法(是调用子类的方法?还是父类的方法?)。

    OC是C语言的超集,如果你熟悉C语言,那C语言里的大部分知识在编写OC代码时依然适用。

    那么,今天的第二个Key:指针。

    OC里的指针主要用来指示对象,基本语法和C语言类似。

    例如:声明一个字符串

    NSString *str1 = @"QiShare";
    

    语法解释:声明了一个名为str1的变量,其类型为NSString *。是一个指向NSString的指针。

    错误案例:

    NSString str2;
    

    报错:error:interface type cannot be statically allocated

    解释:对象不允许声明在栈空间上

    不能在栈中分配OC对象,因为OC对象所占的内存会被分配在堆空间(heap space)上,由程序员来控制它的内存分配。而栈空间的临时基本数据由编译器控制。

    再举一个典型案例:

    NSString *Qi = @"QiShare";
    NSString *Share = Qi;
    

    这里有两个分配在栈空间的NSString指针:Qi和Share指向了堆空间中的同一块内存地址。

    内存结构,图解如下:

    分配在堆中的对象,内存必须由开发者管理。而分配在栈空间上的指针会在其栈帧弹出时自动清理。

    OC将堆内存的管理抽象成了一个机制:ARC(Automatic Reference Counting)。在OC中,不需要用malloc及free来分配或释放对象所占的内存。OC在运行期环境中把这部分工作抽象为一套内存管理架构,我们称之为“引用计数”。之后,我们会有专门的一篇文章讲解ARC机制

    二、为了减少编译时间,.h文件中尽量少引入其他头文件。

    必要时可以考虑在.h文件里"向前声明"该类。

    @class QiShareClass;
    @interface xxx : xxx
    // ...
    @end
    

    在.m文件里再引入该类

    #import "QiShareClass.h"
    // ....
    

    同时,向前声明也解决了两个类可能存在互相引用的问题。

    例如:

    • Qi.h中

    #import "Share.h"
    
    • Share.h中

    #import "Qi.h"
    

    当解析"Qi.h"时,编译器发现"Share.h",再导回自己本身"Qi.h"。

    从而造成循环引用。这样会导致两个类中有一个类不能正确编译。

    推荐:如果用到协议,必要时可以把协议封装在一个单独的头文件里。不仅可以减少编译时间,还能避免循环引用的问题。

    三、多用字面量语法,少用等价方法

    好处:简明易读,提高代码的可读性和可维护性

    局限性:用字面量预防创建数组或字典时,值不能有nil,否则会抛出异常。

    For Example:
    
    // 字面量字符串
    NSString *str = @"QiShare";
    
    // 字面量数值
    NSNumber *num = @(1);
    NSNumber *floatNum = @(1.0);
    int x = 5;
    float y = 3.14;
    NSNumber *num = @(x * y);
    
    // 字面量数组
    NSArray *animals = @[@"cat", @"dog", @"tiger", @"monkey"];
    NSString *cat = animals[0];
    
    // 字面量字典
    NSDictionary *qiShareDic = @{@"englishName": @"QiShare",
                                 @"chineseName": @"奇分享"}];
    NSString *englishName = qiShareDic[@"englishName"];
    NSString *chineseName = qiShareDic[@"chineseName"];
    

    注意:用字面量语法创造出来的对象默认都是不可变对象,如果需要可变对象,执行一步 mutableCopy

    NSMutableString *mutableStr = [@"QiShare" mutableCopy];
    

     

    四、多用类型常量,少用#define预处理指令

    • 好处:定义出来的常量包含类型信息,不可变,可读性高。

    • 而#define定义的值只是在编译前作字符串替换操作,并不包含类型信息。并且如果一不小心被重新定义了常量值,编译器不会产生任何警告⚠️,最终导致常量值不一致。

    For Example:

    #define ANIMATION_DURATION 0.5
    
    // 替换成
    static const NSTimeInterval kAnimationDuration = 0.5;
    
    // 全局常量
    // QiShare.h
    extern const NSTimeInterval QiShareAnimationDuration;
    
    // QiShare.m
    const NSTimeInterval QiShareAnimationDuration = 0.3;
    

     

    五、多用枚举表示状态、选项、状态码

    • 通过枚举表示状态机的状态、传递给方法的选项以及状态码等值,增强了代码的可读性。

    • 枚举的值如果存在多选的可能,将选项值定义为2的幂。便于底层转成二进制存储。

    • 用NS_ENUM 与 NS_OPTIONS 宏来定义枚举类型可以指明底层的数据类型。由开发者决定,而不是编译器决定。

    For Example:

    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone                 = 0,
        UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
        UIViewAutoresizingFlexibleWidth        = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
        UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
        UIViewAutoresizingFlexibleHeight       = 1 << 4,
        UIViewAutoresizingFlexibleBottomMargin = 1 << 5
    };
    

    最后,特别致谢《Effective Objective-C 2.0》第一章

    作者:MrLiuQ

    审校:QiShare团队

    链接:https://www.jianshu.com/p/76ac67f1bd95

    本文转载自CocoaChina,原文链接http://www.cocoachina.com/ios/20180821/24639.html 

    展开全文
  • Cocoa是什么,Cocoa是使用OC语言编写的工具包,里面有大量的类库、结构体,其实就相当于java中的标准API、C++中的标准库。OC中没有命名空间的概念,所以使用加前缀来防止命名冲突,因此你会看到大量的以NS 为前缀的...
    1. Cocoa 是什么 ,  Cocoa是使用OC语言编写的工具包,里面有大量的类库、结构体,其实就相当于java中的标准API、C++中的标准库。 OC中没有命名空间的概念,所以使用加前缀来防止命名冲突,因此你会看到大量的以NS 为前缀的类名、结构体、枚举等。
    2. Cocoa框架由Foundation Kit、App Kit两部分组成,前者是基础工具库,后者主要是UI库、高级对象等。
    3. static 标识的类变量定义在接口的外面,  类变量只能本类访问 ,除非提供类方法给外部访问这个类变量 
    4. @语法是OC特有的一种语法,C是没有的 。 
    5. OC中只有类的成员变量才有访问权限控制 ,@public、@protected、@private,默认是@protected,类变量、类方法、成员方法是没有访问修饰符的,  所有的方法都是public的,所有的类变量都是私有的。
    6. OC中的类方法只能类调用,如果使用对象调用就会报错,而java这只是一个警告而已。
    7. OC中定义类的  @interface 和java中的interface不是一回事,OC的@protocol和java中的interface才是一码事。@interface跟java和C++ class关键字差不多,在OC和C++中,都习惯将类定义写在头文件里,而java却根本没有头文件的概念,至于为什么有这样的差别,想是为了OC和C++编译器方便,大多数时候编译器只需要知道头文件类的定义就知道这个类有哪些属性和方法了。 
    8. get为前缀的方法在OC中有特殊的意义 ,所以尽量使用成员变量名称来作为getter方法的函数名。 
    9. OC是动态语言 ,所以即便是@interface中没有定义的方法在.m文件中实现了也是OK的,一般我们都是给别人提供头文件,这种情况就相当于把方法变相的私有化了,对于我这种喜欢在写代码过程中随时加方法但又不想动头文件的人来说还是比较爽的。 
    10. 在OC中所有对象的存取都是用指针 ,C++中还有引用,OC中没有,我宁愿你强迫我使用一种方法,也不愿你提供给我两种方法我却不知道使用哪一种方法的好。
    11. OC的方法定义和调用算是一大“特色”:
      1. 方法的定义 :-(返回类型) 方法名:(参数1类型)参数1变量 参数2标签:(参数2类型)参数2变量...
      2. [类或者实例的指针方法名: 参数1 标签2: 参数2… …],
      3. 为了好看,第一个参数一般不加标签名,当然, 标签名都可以隐藏的,但不建议这样做 ,因为当你接手了一个离职的人程序,其中的JAVA 程序调用了一个有五个甚至更多的参数的方法,但是你手里没有这个方法的API,那么你很难猜得出来这五个参数到底都干什么用的,但是Objective-C调用的时候,每个参数前面都必须有方法的标签名,这样你便能很容易的从标签名看出这个参数是什么意思。
    12. 调用类方法:
      1. [Fraction t];
      2. [[Fraction class] t];
      3. Class clazz=[Fraction class];[clazz t];
      4. class 来自于NSObject,相当于JAVA 中的getClass()方法,也就是获取这个类的Class 对象,
      5. clazz 前面没有*,这是因为Class 已经是一个指针。另外这种嵌套调用的方式,也要习  惯,这就和JAVA 中的A.b().c()没有什么区别。
      6. 获取Class 有如下几种方法:
        1. [类或者对象 class]
        2. [类或者对象 superclasss]
        3. NSClassFromString(类名的字符串形式)
      7. 你也可以通过如下的函数把Class 转换为字符串形式:
        1. NSStringFromClass(Class)
    13. OC中自定义类最好显示继承NSObject,可以获得alloc、init、release等方法。
    14. OC中使用nil表示null ,但跟java中的null还是有区别的,java中调用null的方法,会报臭名昭著的空指针异常,而OC不会,所以在OC你不必再为空指针而烦恼。
    15. Cocoa中提供的很多函数和java中的api有很大的不一样,  java是纯面向对象的,所有的方法都必须在类中定义,但OC是兼容C语言的,所以C中的面向过程思想在OC中也是行得通的,因此Cocoa中很多东西都不是对象,而是C语言的函数、结构体,比如NSLog()。
    16. 对象的初始化
      1. 前面看到实例化对象最多的方法是:Fraction *frac=[[Fraction alloc] init];
      2. 这跟java不一样,java对象创建只需要new一下,同时调用构造方法(实际上虚拟机层面分为两个步骤:new对象,执行方法(包含构造方法)),但是OC中分为两步:  分配内存(同时给变量赋初值) 、  初始化 。 
        • alloc 是从NSObject 继承而来的类方法,用于给对象分配存储空间,所有的成员变量在此时对确定了自己的内存位置,并被赋初值,整数类型为0,浮点数为0.0,BOOL 为NO,对象类型为nil,alloc 方法返回对象的指针。
        • init这个方法是从NSObject继承而来的,你可以覆盖它,当然init不是构造方法,只是一个普通方法而已,你甚至可以换成其他方法,只不过我们习惯在方法名前缀加上init。
      3. 还记得java中的构造方法没有返回值吧,所以为了达到java这种效果:Test t = new Test(2);  OC中需要你手动在普通方法(相当于构造方法)中return self。
    17. NSObject中的  description 方法相当于java中Object的toString方法,用于获取对象的字符串表示。唯一不同的是  OC中需要使用格式化字符串 %@ ,才会触发description被调用:
      1. Fraction *frac=[[Fraction alloc] init];
      2. NSLog(@"%@",frac);
    18. Objective-C的异常都继承自NSException,当然NSException 本身也继承自NSObject。总体来说,OC中的异常体系和java中的异常体系差不多,唯一的差别就是java中有业务异常,意思就是说你必须捕获他,如果不捕获就会出现编译错误,  OC中的异常基本上都属于java中的运行时异常 ,如果你没有捕获,发生了异常程序就会崩溃,在一些循环批任务中尤其要注意。 
    19. OC中还有一个特色那就是他的  弱类型id,他可以表示任何对象 ,实际上应该是利用了指针地址的通用性,由于OC中操作对象都必须是指针,而指针本身又是一串地址,所以通过指针可以指向一切不同的对象。 
    20. 继承 (感觉和java差不多啊) 
    21. 反射 (这个和异常一样,感觉跟java也很像) 
    22. 选择器 (其实就是C中的函数指针,以及java中的Method类) 
    23. 类别 (Category),扩充类的功能,但不可以声明新的成员变量。 
      • 类别的应用比较广泛,譬如:第三方的Objective-C 库RegexKitLite 就是对NSString、NSMutableString做的类别,为Objective-C 的字符类型增加了正则表达式的功能。
    24. 字符串
      1. -(BOOL) isEqualToString: (NSString*) s
      2. 比较两个字符串是否相等,与JAVA 一致的地方是==比较指针,比较对象是否相同要用到equal 方法。
      3. -(NSMutableString*) appendString: (NSString*) s
      4. 这与JAVA 的StringBuffer 的append 没什么区别。
    25. 数组
      1. Cocoa 使用NSArray 表示数组,但是它不能存储基本数据类型、enum、struct、nil,只能存储Objective-C 的对象。
      2. NSArray *array=[NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];
      3. 从这个类方法arrayWithObjects 的定义可以看出,  它使用nil 表示数组元素结束,这也是nil 不能存储在NSArray 中的原因。 
      4. NSMutableArray 为长度可变的数组,相当于JAVA 中的List:
      5. NSMutableArray *mArray=[NSMutableArray arrayWithCapacity: 10]; 
      6. [mArray addObject: @"Apple"];//添加数组元素
      7. NSEnumerator *e = [mArray objectEnumerator];//获取数组的迭代器,相当于JAVA 中的Iterator,reserveObjectEnumerator 用于获取反转之后的数组迭代器。与JAVA 一致的地方是你在使用迭代器时,不能对数组进行添加、删除操作。 
    26. 字典(哈希表)
      1. NSDictionary 用于存储key-value 的数据结构,与JAVA 中的Map 类似。 
      2. NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys: @"Apple", @"A", @"Google",@"G", nil];//dictionaryWithObjectAndKeys 后的可变参数,每两个为一个value-key,以nil 表示结束。
      3. NSLog(@"%@",[dic objectForKey: @"A"]);//按照指定的key 查询value
      4. 同样的有  NSMutableDictionary 表示长度可变的字典。 
      5. NSMutableDictionary *mDic=[NSMutableDictionary dictionaryWithCapacity: 10];
      6. [mDic setObject: @"Apple" forKey: @"A"];//添加value-key 对
    27. 哈希Set
      1. NSSet 表示以hash 方式计算存储位置的集合,与JAVA 中的HashSet 是一致的。
      2. 在NSSet 中的每个对象都有一个唯一的hash 值,重复的对象将只能保留一个。因此,这引出了Objective-C中的对象比较问题,这需要你实现从NSObject 继承而来的如下两个方法:
        1. - (BOOL)  isEqual : (id) anObject; 
        2. - (NSUInteger)  hash 
      3. 这与JAVA 的对象比较没有什么区别,两个相等的对象必须有相同的hashCode,所以这两个方法必须同时实现。
      4. 同样的,  NSMutableSet 表示长度可变的哈希Set。 
    28. 封装类(相当于java的包装器)
      1. 前面的几个容器类的对象都不能存放基本数据结构、enum、struct、nil,怎么办呢?
      2. 在JAVA中我们知道所有的基本数据类型都有对应的封装类,例如:int---Integer、boolean---Boolean,使用封装类可以把基本数据类型包装为对象,而封装类本身又有方法可以返回原来的基本数据类型。Cocoa 使用  NSValue 作为封装类。 
      3. NSRect rect=NSMakeRect(1,2,30,50);//这个是在前面提到过的一个表示矩形的结构体
      4. NSValue *v=[NSValue valueWithBytes: &rect objCType: @encode(NSRect)];
      5. //java与oc之间的比较 valueWithBytes 要求传入包装数据的地址,也就是变量中存储的数据的首地址,我们依然使用C 语言的&作为地址运算符,计算指针存储的首地址。
      6. //objCType 要求传入用于描述数据的类型、大小的字符串,使用@encode 指令包装数据所属的类型。
      7. 对于基本数据类型,你可以使用简便的  NSNumber 来封装,它是NSValue 的子类。 
      8. 如果你想存储空值到集合类,可以使用NSNull,它使用NSNull *n =[NSNull null];的方式创建。
    29. 日期类型
      • Cocoa 中使用NSDate 类型表示日期。
    30. 数据缓冲区(其实就是java中的字节数组) 
      • Cocoa 中使用NSData 类型来实现缓冲区,用于存储二进制的数据类型,譬如:从网络下载回来的文件等。
      • NSData 是长度不可变的数据缓冲区,还有一个  NSMutableData 用来存储长度可变的数据缓冲区。 
    31. 写入和读取属性(简直就是java序列化和反序列化的翻版)
      1. 在iPhone 的*.ipa 文件中,经常可以看到*.plist 文件,它保存了程序的相关属性,叫做属性列表。其实它就是NSArray、NSDictionary、NSString、NSData 持久化之后的文件。
      2. 这几个类型都有一个成员方法  writeToFile : (NSString*) file atomically: BOOL 用于将自己写入到一个文件。atomically 为YES 表示文件先存储到临时文件区,如果文件保存成功,再替换掉原始文件,这样的好处是可以防止在保存文件过程中出错,但是仅适用于小文件,因为你相当于是在临时文件存储区也放了一份,再加上原始文件,就是两份文件,如果文件比较大,将会占用较多的用户的磁盘空间。 
      3. 如果你要持久化的类型不是上述的数组、字典、缓冲区,那该怎么办呢?Objective-C 中也有和JAVA 一样的序列化、反序列化支持,使用  NSCoding 协议。NSCoding 协议定义了如下两个方法: 
        • -(void) encodeWithCoder : (NSCoder*) coder;
        • -(id) initWithCoder: (NSCoder*) decoder;
        • 第一个方法相当于  编码对象 ,第二个方法是解码回对象,也就相当于给类型定义了一个新的init 方法而已。 
    32. 对象的复制 
      • 对象的复制就相当于JAVA 中的clone()方法,也就是对象的  深度复制 ,所谓深度复制就是重新分配一个存储空间,并将原对象的内容都复制过来,从这些描述可以看出,复制也会分配空间,那就是你要对复制出来的对象release,就是前面所说的alloc、new、copy 操作创建的对象,要手工release。 
      • Objective-C 中的一个对象是否可以被复制,要看它的类型是否遵循NSCopying 协议,这个协议中有个复制方法-(id) copyWithZone: (*NSZone) zone 需要我们去实现。
    33. 多线程
      1. Objective-C 的多线程编程与JAVA 语言极其类似分为原始的线程操作、线程池两种,后者其实就是使用队列等机制对前者的封装。
      2. JAVA 也一样,原始的线程操作使用Thread 类,线程池的操作使用java.util.concurrent.*中的类库。
      3. Objective-C 中  NSThread 类型表示线程,  NSCondition 用于执行同步操作,在功能和用法上相当于JAVA 中的java.util.concurrent.*包中的Lock 对象。 
      4. 另外,Objective-C 也支持@synchronized 指令做代码同步,写法也和JAVA 中的很相似。
      5. 另外比较有趣的是,如果你想更新UI 上的某一个部件,就需要在发起的新线程里调用UI 所在的主线程上的一个方法,  新线程不能直接访问主线程的方法,需要在run 方法中使用如下的方法:
      6. - (void)  performSelectorOnMainThread : (SEL) aSelector withObject: (id) arg waitUntilDone: (BOOL) wait 
      7. 如果对java的swing熟悉的话,应该知道在UI界,大多数更新界面的都必须在一个单线程中执行,因为如果更新界面是多线程的话会很难处理的,java swing处理的方法是更新界面的代码放在专门更新UI的线程下执行,这里IOS也是这么一个思想。
      8. Objective-C 使用  NSOperation 、NSOperationQueue 两个类型实现线程池的操作,  NSOpertion就好比JAVA 中的Runnable ,其中的main(名字有点儿奇怪)方法也就是你要执行的操作,NSOperationQueue 是一个线程池队列,你只需要把NSOperation 添加到NSOperationQueue,队列就会retain 你的NSOperation,然后执行其中的操作,直到执行完毕。 
      9. 队列中会有多个操作,队列会按照你添加的顺序逐个执行,也就说  队列中的任务是串行的。
      10. 跟java一样,如果线程池可以满足你的业务需求,尽量使用线程池,而不是原始的NSThread,因为使用线程池屏蔽了许多线程自身需要处理的问题,代码也更加简洁。
    34. KVC 与KVO(这个话题真高级)
      1. KVC 是 NSKeyValueCoding 的缩写,它是Foundation Kit 中的一个NSObject 的Category,作用可以类比JAVA 中的反射机制,就是  动态访问一个对象中的属性。
      2. KVC 在解析key 的字符串的时候,是会比正常调用setter、getter 要慢的,而且编译器无法在编译器对你的方法调用做出检查(因为你的属性名都是字符串,只有运行时才会知道你有没有写错),出错的几率也会提高,所以请不要随意使用KVC,而省去setter、getter 方法。KVC 一般用于动态绑定,也就是运行时才能确定谁调用哪个方法,编译期并不确定。
      3. KVO就是 NSKeyValueObserving的缩写,它也是Foundation Kit中的一个NSObject的Category,KVO 基于KVC 实现,基于  观察者设计模式 (Observer Pattern)实现的一种通知机制,可以类比JAVA 中的JMS,通过订阅的方式,实现了两个对象之间的解耦,但又可以让他们相互调用。 
    35. 谓词 NSPredicateCocoa 
    • 提供了NSPredicate 用于指定过滤条件
    • 谓词是指在计算机中表示计算真假值的函数,它使用起来有点儿像SQL 的查询条件,主要用于从集合中分拣出符合条件的对象,也可以用于字符串的正则匹配。

    参考文章

    • http://blog.sina.com.cn/s/blog_93742d0d010165qi.html

    转载于:https://www.cnblogs.com/vijozsoft/p/5996754.html

    展开全文
  • java源码葫芦脚本 CalabashScript 是一个用于为原生 iOS 应用编写自动化功能测试的库。 CalabashScript 提供了友好的 ClojureScript API,它基于(可能不是那么友好)UIAutomation API。 CalabashScript 还提供了一...
  • 摘要: 移动开发中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问题...头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为Android和iPhone两个客户端各写一套...
  • 本文作者为 RoboVM 的 CEO 兼联合创始人 Henric Müller,主要介绍选用 Java 编写移动应用的八大理由。文章系国内 ITOM 管理平台 OneAPM 编译呈现。
  • ios开发 如果您使用的是移动应用程序,并且计划在Android和iOS上进行开发,那么首先在Android上编写它可能会少一些。 谷歌最近发布了一个新工具,使将Java代码移植到iOS更加容易。项目(j2objc)可以在这里找到。 ...
  • ios java 3DES 加解密

    千次阅读 2014-10-13 16:38:59
    移动开发中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问题。...头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为Android和iPhone两个客户端各写一套Web
  • java 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费服务。 每个类别中的项目没有预先确定的顺序,顺序是为了贡献。 如果你想贡献...
  • java版qq餐厅源码 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费服务。 每个类别中的项目没有预先确定的顺序,顺序是为了贡献。 ...
  • iOS中类似java抽象类理解。

    千次阅读 2015-09-26 13:10:34
    * 抽象类IOS这边无法规定子类必须实现一个方法,这边只是一个警号,编译依然能过。所以感觉无法控制编写代码的规范。 具体的就是。 通过父类实现对应的协议, 其中必须实现的也就是java中的抽象方法。 而可选...
  • 仿糖堆网java源码 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费服务。 每个类别中的项目没有预先确定的顺序,顺序是为了贡献。 ...
  • 仿糖堆网java源码 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费服务。 每个类别中的项目没有预先确定的顺序,顺序是为了贡献。 ...
  • java切水果源码注释 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费服务。 每个类别中的项目没有预先确定的顺序,顺序是为了贡献...
  • libGDX是基于OpenGL(ES)的跨平台Java游戏开发框架,可在Windows,Linux,macOS,Android,浏览器和iOS上运行。 libGDX为快速原型制作和快速迭代提供了一个经过充分验证的健壮环境。 libGDX不会对您施加特定的设计...
  • java 我们推出了我们的时事通讯!! :check_mark_button: :rocket: :newspaper: 关于 精选的 iOS 框架、库、教程、Xcode 扩展和插件、组件等的精选列表。 该列表分为框架、组件、测试等类别、开源项目、免费和付费...
  • 使用丰富的iOS API,不仅可以编写一次GUI应用程序,还可以编写涵盖大多数移动方面的应用程序,例如推送通知,地理位置,地图,摄像头等。无需编写特定于Android的代码,只需遵循iOS API和所有功能都将由此框架处理...
  • 苹果iOS系统的封闭性一直广为其他语言(如Java)开发者诟病,但随着第三方工具的不断壮大,开发人员逐渐摆脱政策束缚,开始使用自己熟悉的语言来编写iOS本地应用,或将其他平台上的应用移植到iOS上。本文为你介绍5款...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 885
精华内容 354
关键字:

ios编写java

java 订阅