python实现固定尺寸图像拼接

python实现固定尺寸图像拼接

python实现固定尺寸图像拼接
讲解
1、代码效果:固定尺寸图像拼接
代码

import os
import cv2
import numpy as np

def joint(or_path, tar_path, size):
determination = tar_path
if not os.path.exists(determination):
os.makedirs(determination)

path = or_path
folders = os.listdir(path)
folders_name = []
folders.sort(key = lambda x: int(x.split(‘.’)[0]))
for folder in folders:
folders_name.append(path + “\\” + str(folder))
foldler_len = len(folders_name)
joint = []
for i in range(size):
joint.append(cv2.imread(folders_name[i]))
index = 0
for i in range(len(folders_name)):
if i < size:
continue
image = cv2.imread(folders_name[i])
joint[index] = np.hstack((joint[index], image))
index += 1
if index > size – 1:
index = 0
for i in range(1, len(joint)):
joint[0] = np.vstack((joint[0], joint[i]))
cv2.imwrite(tar_path + “/all.jpg”, joint[0])
print(joint[0].shape)

if __name__ == “__main__”:
joint(r””, r””, size)#原图像文件夹路径、新图像存放路径、单方向图像数

运行结果
运行前%title插图%num

运行后

%title插图%num

ArcPy基础之字典(二)

ArcPy基础之字典(二)

文章目录
一、编译环境和编译器
二、字典
1.定义字典,获取字典关键字、值、对象
2.字典的操作:增、删、改、查、复制和创建
一、编译环境和编译器
ArcGIS10.6:Python2.7.14 32-bit
编译器:Visual Studio Code

二、字典
1.定义字典,获取字典关键字、值、对象
代码如下(示例):

# encoding=utf-8

#定义字典{key:value}
dicA={“name”:”Xiao Ming”,”age”:14,”high”:167,”other”:””}
print(dicA)
print(len(dicA))#打印字典长度
#获取关键字、值、对象
print(dicA.keys())#打印字典关键字
print(type(dicA.keys()))#字典关键字类型,list

print(dicA.values())#打印值
print(type(dicA.values()))#字典值类型,list

print(dicA.items())#打印对象
print(type(dicA.items()))#字典对象类型,list
print(“———-0”)

#通过循环获取,以获取对象为例
for item in dicA.items():
print(item)

print(“———-1”)

#根据关键字获取值
print(dicA.get(“name”))#根据关键字”name”获取值Xiao Ming
dicA.get(“name”)#当获取的关键字在原字典中不存在时,get()会返回默认值,但不改变原字典。
print(dicA)

print(dicA.setdefault(‘name’))#根据关键字”name”获取名字Xiao Ming
dicA.setdefault(‘grades’)#当获取的关键字在原字典中不存在时,setdefaul()t会返回默认值None并更新字典
print(dicA)

打印结果:

{‘high’: 167, ‘age’: 14, ‘other’: ”, ‘name’: ‘Xiao Ming’}
4

[‘high’, ‘age’, ‘other’, ‘name’]
<type ‘list’>
[167, 14, ”, ‘Xiao Ming’]
<type ‘list’>
[(‘high’, 167), (‘age’, 14), (‘other’, ”), (‘name’, ‘Xiao Ming’)]
<type ‘list’>
———-0
(‘high’, 167)
(‘age’, 14)
(‘other’, ”)
(‘name’, ‘Xiao Ming’)
———-1
Xiao Ming
{‘high’: 167, ‘age’: 14, ‘other’: ”, ‘name’: ‘Xiao Ming’}
Xiao Ming
{‘high’: 167, ‘age’: 14, ‘other’: ”, ‘grades’: None, ‘name’: ‘Xiao Ming’}

2.字典的操作:增、删、改、查、复制和创建
dicA={‘high’: 167, ‘age’: 14, ‘other’: ”, ‘grades’: None, ‘name’: ‘Xiao Ming’}
#字典的操作
#增
dicA[“sex”]=”boy”#用[]直接添加字典关键字和值,且增加在字典尾部
print(dicA)#打印增加后字典

dicB={“class”:1,34:”ge”}
dicA.update(dicB)#将dicB更新到dicA中
print(dicA)#打印更新后结果
print(“———-2”)

#删
del dicA[“other”]#通过del删除关键词和值
print(dicA)#打印删除后字典

dicA.pop(“age”)#索引并删除关键字为“age”的键值对
print(dicA)#打印pop后字典

dicA.popitem()#索引并删除字典*新加入的键值对
print(dicA)#打印popitem后结果
print(“———-3”)

#改
dicA[“sex”]=”girl”#通过关键字将性别改为girl,它会覆盖原来值
print(dicA)#打印改后字典
print(“———-4”)

#查
print dicA.has_key(“sex”)#查询字典中是否存在关键字sex
print(“———-5”)

#字典的复制
print(dicA.copy())#打印复制后字典
print(“———-6”)

#创建新字典
dic1={}#新建一个空的字典
dic2=dic1.fromkeys((“hair”,”leg”),”long”)#对空的字典添加”hair”和“leg”两个关键值,并将值都赋为long
print(dic2)#打印新建字典

#清除
dic2.clear()#清除dic2
print(dic2)

打印结果:

{‘name’: ‘Xiao Ming’, ‘age’: 14, ‘sex’: ‘boy’, ‘high’: 167, ‘grades’: None, ‘other’: ”}
{34: ‘ge’, ‘name’: ‘Xiao Ming’, ‘age’: 14, ‘sex’: ‘boy’, ‘high’: 167, ‘grades’: None, ‘other’: ”, ‘class’: 1}
———-2
{34: ‘ge’, ‘name’: ‘Xiao Ming’, ‘age’: 14, ‘sex’: ‘boy’, ‘high’: 167, ‘grades’: None, ‘class’: 1}
{34: ‘ge’, ‘name’: ‘Xiao Ming’, ‘sex’: ‘boy’, ‘high’: 167, ‘grades’: None, ‘class’: 1}
{‘name’: ‘Xiao Ming’, ‘sex’: ‘boy’, ‘high’: 167, ‘grades’: None, ‘class’: 1}
———-3
{‘name’: ‘Xiao Ming’, ‘sex’: ‘girl’, ‘high’: 167, ‘grades’: None, ‘class’: 1}
———-4
True
———-5
{‘high’: 167, ‘class’: 1, ‘grades’: None, ‘name’: ‘Xiao Ming’, ‘sex’: ‘girl’}
———-6
{‘hair’: ‘long’, ‘leg’: ‘long’}
{}

ArcGIS开发arcpy教程
07-25
<p> arcgis数据处理过程中使用到的arcpy脚本,基础教程。有助于gis从业人员开发arcpy脚本便捷处理数据。提供基础与案例应用结合方式,讲解arcpy知识。 </p> <p> 1.python基础 </p> <p> 2.基本图形创建 </p> <p> 3.shapefile数据操作 </p> <p> 4.常见数据txt.csv,json,excel数据操作 </p> <p> 5.工具打包 </p> <p> (1)添加脚本方式 </p> <p> (2)ArcCatalog添加代码方式 </p> <p> 6.arcpy案例应用 </p> <p> (1)几何图形面polygon,点point之间关系应用 </p> <p> (2)面四至坐标提取应用 </p> <p> (3)面求交,找出*大相交面应用 </p> <p> (4)逐条记录导出应用 </p> <p> (5)批量裁剪影像应用 </p> <p> (6)栅格数据批量定义投影以及工具打包应用 </p> <p> <br /></p>
arcgis二次开发arcpy视频教程(持续更新中……)
yGIS
3253
https://edu.csdn.net/course/detail/25535 01. 课程概况 02. ArcPy开发-1-python基础–环境搭建、*个程序、练习 03. ArcPy开发-2-python基础–表达式,数据类型、语句、变量 04. ArcPy开发-3-python基础–字符串 05. ArcPy开发-4-python基础–列表 06. ArcPy…

爱码士看,月亮在跳舞:好文章2 小时前回复

爱码士LaoYuanPython:欢迎博主加入CSDN!欢迎博主到本人的Python专栏来交流!2 小时前回复

相关推荐
python笔记之ArcPy简介
baoqian1993的博客
2万+
第1章 ArcPy简介 1.1什么是 ArcPy? ArcPy 是一个以成功的 arcgisscripting 模块为基础并继承了 arcgisscripting 功能进而构建而成的站点包。目的是为以实用高效的方式通过 Python 执行地理数据分析、数据转换、数据管理和地图自动化创建基础。 该包提供了丰富纯正的 Python 体验,具有代码自动完成功能(输入关键字和点即可获得
ArcPy*章-Python基础
28
学习Arcpy,从零开始积累。1.代码注释: python中,说明部分通常使用注释来实现: 方式: # 或者 ## + 注释部分内容2. 模块导入: 方式: import Eg: import arcpy import os3.变量:(python中定义变量,不需要先声明变量类型,只需要直接命名和赋值即可) Eg: mapsize = “22 x 34″4.内置数据类型:…
python3使用arcpy_Python & ArcPy – 随笔分类 – McDelfino – 博客园
weixin_39622138的博客
109
随笔分类 – Python & ArcPyPython 学习,主要是 ArcGIS 里面有用到!摘要:利用 sklearn.feature_extraction.text 中的 CountVectorizer 来实现 首先获取所有的文本信息 然后将文本信息转化为从 0 开始的数字 获取转换后的字符向量 参见如下代码: >>> text_01 = “My name is A…
视频教程-ArcGIS开发arcpy教程-其他
weixin_33329105的博客
229
ArcGIS开发arcpy教程 从事数字城市、智慧城市、地质灾害、警务等国土…
从Python到空间分析Arcpy || 1.2.1 数据类型是什么,有哪些
jieyoudata的博客
66
今天开始介绍python中的数据类型,这是python中*基础也是*核心的内容,计划分为4-5个小节来介绍。 总的来说python中的数据类型可以分为 9大类(很容易记的数字)。 数值类型(Number) 数值类型又包括:int 整型 float 浮点型 complex复数类型,常用前2个 布尔型(Bool ) 布尔类型在python中是用关键字来定义的,False 和True ,请注意两个单词的*个字母都要大写,python 语言本身是对大小写敏感的语言,A和a在python中是两个不同的对象,bool
access数据放到list中_从Python到空间分析Arcpy || 1.2.1 数据类型

【总结】2020年*新算法工程师技术路线图

这是一份写给公司算法组同事们的技术路线图,其目的主要是为大家在技术路线的成长方面提供一些方向指引,配套一些自我考核项,可以带着实践进行学习,加深理解和掌握。

%title插图%num

工程师能力层级概览

对于不同级别的算法工程师技能要求,我们大致可以分成以下几个层级:

  • 初级:可以在一些指导和协助下独立完成开发任务。具体到算法方面,需要你对于工具框架,建模技术,业务特性等方面有一定的了解,可以独立实现一些算法项目上的需求。
  • 中级:可以基本独立完成一个项目的开发与交付。在初级工程师的基础上,对于深入了解技术原理的要求会更高,并且能够应对项目中各种复杂多变的挑战,对于已有技术和工具进行改造适配。在整体工程化交付方面,对于代码质量,架构设计,甚至项目管理方面的要求会开始显现。另外从业务出发来评估技术选型和方案也变得尤为重要。
  • 高级:可以独立负责一条产品线的运作。在中级工程师的基础上,需要更广阔的技术视野与开拓创新能力,定义整个产品线的前进方向。解决问题已经不是关键,更重要的是提出和定义问题,能够打造出在业界具有*性和差异性的产品,为公司创造更大的价值。

事实上对于不同层级的工程师,非技术部分的要求都有一定占比。本文主要聚焦在技术路线图上,对于其他方面的学习进阶路线不会做覆盖。

阅读建议

以下内容分工程基础,算法基础,算法工程交叉,工程深入方向,算法深入方向几个部分,在各个部分内部会进一步区分一些主题。在各个主题内部,也是有深入程度的区别的,不过限于篇幅没有进行详细的说明。建议学习路线可以先把两个基础部分与工作中较为相关的内容做一个整体基础的夯实,然后可以在后续交叉和深入方向的主题中选择感兴趣的进行深入了解和学习,过程中发现基础部分欠缺的,可以再回到基础部分查漏补缺,迭代前行。

工程基础

编程语言

Python

Python 是算法工程师日常工作中*常用的语言,应该作为必须掌握的一门技术。大致的学习路线如下:

  • 学习掌握 Python 的基本语法,可以通过各类入门教程来看,个人推荐《Learn Python the Hard Way》。
  • 自我考核:能够读懂大多数的内部项目及一些开源项目代码的基本模块,例如 pandas, sklearn 等。
  • 学习 Python 的编程风格,建议学习观远内部的 Python 代码规范。
  • 自我考核:编写的代码符合编码规范,能够通过各类 lint 检查。
  • Python 进阶,这方面有一本非常著名的书《Fluent Python》,深入介绍了 Python 内部的很多工作原理,读完之后对于各类疑难问题的理解排查,以及语言高级特性的应用方面会很有帮助。另外动态语言元编程这块,《Ruby 元编程》也是一本非常值得推荐的书。
  • 自我考核:能够读懂一些复杂的 Python 项目,例如 sqlalchemy 中就大量使用了元编程技巧。在实际工程项目中,能够找到一些应用高级技巧的点进行实践,例如基于 Cython 的性能优化等。
  • 领域应用,Python 的应用相当广泛,在各个领域深入下去都有很多可以学习的内容,比如 Web 开发,爬虫,运维工具,数据处理,机器学习等。这块主要就看大家各自的兴趣来做自由选择了,个人推荐熟悉了解一下 Python web 开发,测试开发相关的内容,开拓视野。
  • 自我考核:以 Web 开发和测试开发为例,尝试写一个简单的 model serving http 服务,并编写相应的自动化测试。

Scala/Java

Java 目前是企业级开发中*常用的软件,包括在大数据领域,也是应用*广泛的语言,例如当年的 Hadoop 生态基本都是基于 Java 开发的。Scala 由于其函数式编程的特性,在做数据处理方面提供了非常方便的 API,也因为 Spark 等项目的火热,形成了一定的流行度。在进行企业级的软件开发,高性能,大规模数据处理等方面,JVM 上的这两门语言有很大的实用价值,值得学习。

顺带一提,Scala 本身是一门非常有意思的语言,其中函数式编程的思想与设计模式又是非常大的一块内容,对于拓宽视野,陶冶情操都是挺不错的选择。

考虑到算法工程师的工作内容属性,这边给出一个 Scala 的学习路线:

  • 学习掌握 Scala 的基本语法,开发环境配置,项目编译运行等基础知识。这里推荐 Coursera 上 Martin Odersky 的课程,《快学 Scala》或《Programming in Scala》两本书也可以搭配着浏览参考。
  • 自我考核:能使用 Scala 来实现一些简单算法问题,例如 DFS/BFS。或者使用 Scala 来处理一些日常数据工作,例如读取日志文件,提取一些关键信息等。
  • 学习使用 Scala 来开发 Spark 应用,推荐 edX 上的《Big Data Analytics Using Spark》或者 Coursera 上的《Big Data Analytics with Scala and Spark》,另外有些相关书籍也可以参考,比如《Spark 快速大数据分析》等。
  • 自我考核:能够使用 Spark 的 Scala API 来进行大规模的数据分析及处理,完成 lag feature 之类的特征工程处理。
  • JVM 的原理学习,Scala/Java 都是 JVM 上运行的优秀语言,其背后是一个非常大的生态,包括在 Web,Android,数据基础架构等方面有广泛的应用。JVM 相比 Python 虚拟机,发展更加成熟,有一套非常完善的 JDK 工具链及衍生的各类项目,便于开发者 debug,调优应用。这方面推荐学习周志明的《深入理解 Java 虚拟机》。
  • 自我考核:理解 JVM GC 原理,能通过 JDK 中相关工具或者优秀的第三方工具如 arthas 等,排查分析 Spark 数据应用的资源使用情况,GC profiling,hot method profiling 等,进而进行参数优化。
  • 计算机语言理论。Programming Language 作为计算机科学的一个重要分支,包含了很多值得深入研究的主题,例如类型论,程序分析,泛型,元编程,DSL,编译原理等。这方面的很多话题,在机器学习方面也有很多实际应用,比如 TVM 这类工作,涉及到大量编译原理的应用,知乎大佬 “蓝色” 也作为这个领域的专家在从事深度学习框架相关的工作。llvm, clang 作者 Chris Lattner 也加入 Google 主导了 Swift for Tensorflow 等工作。Scala 作为一门学术范非常强的语言,拥有*佳的 FP,元编程等能力支持,强大的类型系统包括自动推理,泛型等等高级语言特性,相对来说是一门非常 “值得” 学习的新语言,也是一个进入 PL 领域深入学习的 “gateway drug” 🙂 对这个方面有兴趣的同学,可以考虑阅读《Scala 函数式编程》,《冒号课堂》,以及 Coursera 上《Programming Languages》也是一门非常好的课程。另外只想做科普级了解的同学,也可以读一读著名的《黑客与画家》感受一下。

C/C++/Rust

当前流行的算法框架,例如 TensorFlow, PyTorch, LightGBM 等,底层都是基于 C++ 为主要语言进行实现的。但是 C++ 本身过于复杂,使用场景也比较有限制,建议只需要达到能够读懂一些基础的 C++ 代码逻辑即可。在系统级开发领域,目前有一门新语言逐渐崛起,连续几年被 StackOverflow 投票评选为程序员*喜爱的语言:Rust。从设计理念和一些业界应用(例如 TiKV)来看还是非常不错的,但是我也没有深入学习了解过,就不做具体推荐了。这方面建议的学习内容包括经典的《The C Programming Language》以及 Rust 官方的:https://github.com/rust-lang/rustlings

  • 自我考核:能够读懂 LightGBM 里对于 tweedie loss 的相关定义代码。

操作系统

基本概念

我们所编写的算法应用,都是通过操作系统的环境运行在物理硬件之上的。在实际运作过程中,会碰到不少相关的问题,例如为什么程序报了资源不足的错误,为什么 notebook 在浏览器里打不开,为什么进程 hang 住了没有响应等等,都需要一些操作系统的知识来帮助理解和分析问题,*终排查解决。操作系统涵盖的内容比较多,建议一开始只需要了解一些主要概念(例如硬件结构,CPU 调度,进程,线程,内存管理,文件系统,IO,网络等),对于整体图景有一些感觉即可。后续碰到了实际问题,可以再在各个部分深入学习展开。优秀的学习资料也有很多,基本都是大部头,重点推荐《深入理解计算机系统》,《Operating Systems: Three Easy Pieces》,以及《现代操作系统》。

  • 自我考核:能够基本明确运行一个模型训练任务过程中,底层使用到的硬件,操作系统组件,及其交互运作的方式是如何的。

Linux 基础

平时工作中*常用的两个操作系统 CentOS 和 macOS,都是 Unix/Linux 系的,因此学习掌握相关的基础知识非常重要。一些必须掌握的知识点包括:Shell 与命令行工具,软件包管理,用户及权限,系统进程管理,文件系统基础等。这方面的入门学习资料推荐《鸟哥的 Linux 私房菜》,基本涵盖了 Linux 系统管理员需要掌握知识的方方面面。进阶可以阅读《Unix 环境高级编程》,对于各种系统调用的讲解非常深入,可以为后续性能调优等高级应用打下基础。

  • 自我考核:开发一个 shell 小工具,实现一些日常工作需求,例如定时自动清理数据文件夹中超过一定年龄的数据文件,自动清理内存占用较大且运行时间较久的 jupyter notebook 进程等。

深入应用

工作中碰到的疑难问题排查,性能分析与优化,系统运维及稳定性工程等方面,都需要较为深入的计算机体系和操作系统知识,感兴趣的同学可以针对性的进行深入学习。以性能优化为例,可以学习经典的《性能之巅》,了解其中的原理及高级工具链。像其中的系统调用追踪 (strace),动态追踪(systemtap, DTrace, perf, eBPF) 等技术,对于操作系统相关的问题排查都会很有帮助。

  • 自我考核:能够分析定位出 LightGBM 训练过程中的性能瓶颈,精确到函数调用甚至代码行号的级别。

软件工程

算法与数据结构

暂时先把这块放到软件工程模块下。这里指的算法是计算机科学中的经典算法,例如递归,排序,搜索,动态规划等,有别于我们常说的机器学习算法。这块的学习资料网上有非常多,个人当年是通过普林斯顿的算法课 (需要有 Java 基础) 入门,后来又上了斯坦福的算法分析与设计,开拓了一些视野。书籍方面推荐新手从《算法图解》入门,然后可以考虑阅读 Jeff Erickson 的《Algorithms》,或者选择上面提到的网课。另外像《编程珠玑》,《编程之美》等也可以参阅,里面有不少问题的巧妙解法。除了从书本中学习,还可以直接去 LeetCode 等网站进行实战操作进行练习提高。

  • 自我考核:能够设计相关的数据结构,实现一个类似 airflow 中点击任意节点向后运行的功能。

代码规范

从初级程序员到中高级程序员,其中比较大的一个差异就是代码编写习惯上,从一开始写计算机能理解,能够运行成功的代码,逐渐演化到写人能够理解,易于修改与维护的代码。在这条学习路径上,首先需要建立起这方面的意识,然后需要在实战中反复思考和打磨自己的代码,评判和学习其它优秀的项目代码,才能逐渐精进。推荐的学习书籍有《编写可读代码的艺术》,一本非常短小精悍的入门书籍,后续可以再慢慢阅读那些经典大部头,例如《Clean Code》,《Code Complete》,《The Pragmatic Programmer》等。这方面 Python 也有一本比较针对性的书籍《Effective Python》,值得一读。

  • 自我考核:审视自己写的项目代码,能发现并修正至少三处不符合*佳编码实践的问题。

设计模式

在代码架构方面,设计模式是一个重要的话题,对于日常工作中出现的许多典型场景,给出了一些解决方案的“套路”。这方面*著名的书当属 GoF 的《设计模式》,不过个人并不十分推荐,尤其是以 Python 作为主要工作语言的话,其中很大部分的设计模式可能并不需要。入门可以浏览一下这个网站掌握一些基本概念:https://refactoringguru.cn/design-patterns/python ,后续可以考虑阅读《Clean Architecture》,《重构》等相关数据,理解掌握在优化代码架构过程中思考的核心点,并加以运用。Python 相关的设计模式应用,还可以参考《Python in Practice》。

  • 自我考核:在项目中,找到一处可以应用设计模式的地方,进行重构改进。

质量保障

对于需要实际上线运行的软件工程,质量保障是非常重要的一个环节,能够确保整个产品按照期望的方式进行运作。在机器学习项目中,由于引入了数据这个因素,相比传统的软件测试会有更高的难度,也是业界还在摸索前进的方向。建议可以先阅读《单元测试的艺术》或《Google 软件测试之道》,大致理解软件测试的一些基本概念和运作方式,在此基础上可以进一步阅读 Martin Fowler 对于机器学习领域提出的 CD4ML 中相关的测试环节,学习 sklearn,LightGBM 等开源库的测试开发方式,掌握机器学习相关的质量保障技术能力。

  • 自我考核:在项目中,实现基础的数据输入测试,预测输出测试。

项目管理

软件工程推进过程中,项目管理相关的技能方法与工具运用也非常的关键。其中各种研发流程与规范,例如敏捷开发,设计评审,代码评审,版本管控,任务看板管理等,都是实际项目推进中非常重要的知识技能点。这方面推荐学习一本经典的软件工程教材《构建之法》,了解软件项目管理的方方面面。进一步来说广义的项目管理上的很多知识点也是后续深入学习的方向,可以参考*客时间上的课程《项目管理实战 20 讲》。

  • 自我考核:在某个负责项目中运用项目管理方法,完成一个实际的需求评估,项目规划,设计与评审,开发执行,项目上线,监控维护流程,并对整个过程做复盘总结。

高级话题

软件工程师在技能方向成长的一条路线就是成为软件架构师,在这个方向上对于技能点会有非常高的综合性要求,其中也有不少高级话题需要深入学习和了解,例如技术选型与系统架构设计,架构设计原则与模式,宽广的研发知识视野,高性能,高可用,可扩展性,安全性等等。有兴趣的同学可以了解一下*客时间的《从 0 开始学架构》这门课,逐渐培养这方面的视野与能力。另外如《微服务架构设计模式》还有领域驱动设计方面的一系列书籍也值得参考学习。

  • 自我考核:设计一个算法项目 Docker 镜像自动打包系统。

算法基础

数据分析

数学基础

在进行算法建模时,深入了解数据情况,做各类探索性分析,统计建模等工作非常重要,这方面对一些数学基础知识有一定的要求,例如概率论,统计学等。这方面除了经典的数学教材,也可以参考更程序员向的《统计思维》,《贝叶斯方法》,《程序员的数学 2》等书籍。

  • 自我考核:理解实际项目中的数据分布情况,并使用统计建模手段,推断预测值的置信区间。

可视化

在进行数据分析时,可视化是一个非常重要的手段,有助于我们快速理解数据情况,发掘数据规律,并排查异常点。对于各种不同类型的数据,会对应不同的可视化*佳实践,如选择不同的图表类型,板式设计,分析思路编排,人机交互方式等等。另一方面,可视化与数据报告也是我们与不同角色人群沟通数据 insights 的一个重要途径,需要从业务角度出发去思考可视化与沟通方式。这方面可以参考《Storytelling with Data》,《The Visual Display of Quantitative Information》等经典数据,同时也需要培养自己的商业背景 sense,提升沟通能力。

  • 自我考核:对内沟通方面,能使用可视化技术,分析模型的 bad case 情况,并确定优化改进方向。对外沟通方面,能独立完成项目的数据分析沟通报告。

误差分析与调优

在做算法模型调优改进中,需要从数据分析的基础上出发来决定实验方向,这么做有几个好处:

  • 从分析出发指导调优更有方向性,而不是凭经验加个特征,改个参数碰运气。哪怕是业务方提供的信息,也*好是有数据分析为前提再做尝试,而不是当成一个既定事实。
  • 由分析发现的根源问题,对于结果验证也更有帮助。尤其在预测的数据量*大情况下,加一个单一特征很可能总体只有千分位准确率的提升,无法确定是天然波动还是真实的提升。但如果有分析的前提,那么我们可以有针对性的看对于这个已知问题,我们的调优策略是否生效,而不是只看一个总体准确率。
  • 对于问题的彻底排查解决也更有帮助,有时候结果没有提升,不一定是特征没用,也可能是特征代码有 bug 之类的问题。带着数据分析的目标去看为什么这个特征没有效果,是模型没学到还是特征没有区分度等,有没有改进方案,对于我们评判调优尝试是否成功的原因也更能彻查到底。
  • 数据分析会帮助我们发现一些额外的问题点,比如销量数据清洗处理是不是有问题,是不是业务本身有异常,需要剔除数据等。

这方面在业界有一些关于误差分析的探索研究,不过大多数都是基于分类问题的,例如《Identifying Unknown Unknowns in the Open World》,《A Characterization of Prediction Errors》等。可以在了解这些研究的基础上,结合具体的业务情况,深入思考总结误差分析的思路与方法论。

  • 自我考核:在项目中形成一套可以重复使用的误差分析方案,能够快速从预测输出中定位到目前模型*重要的误差类别,并一定程度上寻找到根本原因。

机器学习基础

传统机器学习

这块大家应该都非常熟悉了,初阶的学习路线可以参考周志华老师的《机器学习》,涵盖了机器学习基础,常用机器学习方法,和一些进阶话题如学习理论,强化学习等。如果希望深化理论基础,可以参考经典的《PRML》,《ESL》和《统计学习方法》。在实战中,需要综合业务知识,算法原理,及数据分析等手段,逐渐积累形成建模调优的方法论,提高整体实验迭代的效率和成功率。

  • 自我考核:结合实际业务和机器学习理论知识,挖掘项目中算法表现不够好的问题,并通过算法改造进行提升或解决。

深度学习

近些年兴起的深度学习,已经成为机器学习领域一个非常重要的分支,在各个应用方向发挥了很大的作用。相对于传统机器学习,对于特征工程要求的降低成了其核心优势。另一方面,深度学习对于大数据量,大规模算力的应用能力很强,也一定程度上提升了整体的产出效果。由于理论方面的研究稍显落后,深度学习在实际应用中对于使用者的经验技能要求相对比较高,需要有大量的实战经验才能达到比较理想的效果。这方面的学习资料推荐 Keras 作者的《Deep Learning with Python》,以及《Hands-on Machine Learning with Scikit-Learn and TensorFlow》,而在理论方面推荐著名的“花书”《Deep Learning》。在学习理论原理的基础上,尤其要注意在实际算法应用中,能够通过观察各种指标与数据分析,找到提升模型的操作改进方向。

  • 自我考核:能够在实际项目中,使用深度学习模型,达到接近甚至超过传统 GBDT 模型的精确度效果,或者通过 ensemble,embedding 特征方式,提升已有模型的精度。

领域建模

目前我们的业务领域在时间序列预测,自然语言处理,推荐等方面,其它类似图像,搜索,广告等领域也都有各自的一些领域建模方法。在时间序列领域,包括了传统时序模型,如 ARIMA, Prophet,机器学习模型,如划动窗口特征构建方法结合 LightGBM,及深度学习模型,例如 LSTM,seq2seq,transformer 等。这方面可以参考 Kaggle 上相关比赛的方案分享,以及 Amazon,Uber,天猫等有类似业务场景公司的分享资料。其它领域也是类似,通过了解历史技术演进,相关比赛,业界的方案分享与开源项目,会议论文来逐渐掌握学习建模方法,结合实际业务进行实践尝试,积累起更加体系性的个人知识技能。

  • 自我考核:在项目中复现一个 Kaggle 获胜方案,检验其效果,分析模型表现背后的原因,并尝试进行改进。

算法框架

数据处理框架

在项目实施过程中,会需要各类复杂的数据处理操作,因此熟练掌握此类框架就显得尤为重要。目前行业的标准基本上会参照 Pandas DataFrame 的定义,在数据量较大的情况下,也有许多类似的框架,如 Spark,Dask,Modin,Mars 等支持分布式运行的 DataFrame,以及 cuDF,Vaex 等提升单机性能的改进实现。这方面经典的书籍可以参考 Wes McKinney 的《Python for Data Analysis》,在掌握基础数据操作的基础上,可以进而了解窗口函数,向量化性能优化等高级话题。另外 SQL 也可以做非常复杂的数据处理工作,有不少公司例如阿里会以 SQL 为主来构建数据处理流程,感兴趣的同学也可以学习一下 SQL 中各种高级计算的使用及优化方法。

  • 自我考核:在已有项目中,能把至少三个使用 apply 方法的 pandas 处理修改成向量化运行,并测试性能提升。使用 window function 或其它方案来实现 lag 特征,减少 join 次数。

机器学习框架

机器学习方面的新框架层出不穷,一方面我们需要掌握经典框架的使用方式,理解其模块构成,接口规范的设计,一定程度上来说其它新框架也都需要遵循这些业界标准框架的模块与接口定义。另一方面对于新框架或特定领域框架,我们需要掌握快速评估,上手使用,并且做一定改造适配的能力。一些比较经典的框架有:

  • 通用机器学习:scikit-learn,Spark ML,LightGBM
  • 通用深度学习:Keras/TensorFlow,PyTorch
  • 特征工程:tsfresh, Featuretools,Feast
  • AutoML:hyperopt,SMAC3,nni,autogluon
  • 可解释机器学习:shap,aix360,eli5,interpret
  • 异常检测:pyod,egads
  • 可视化:pyecharts,seaborn
  • 数据质量:cerberus,pandas_profiling,Deequ
  • 时间序列:fbprophet,sktime,pyts
  • 大规模机器学习:Horovod,BigDL,mmlspark
  • Pipeline:MLflow, metaflow,KubeFlow,Hopsworks

一般的学习路径主要是阅读这些框架的官方文档和 tutorial,在自己的项目中进行尝试使用。对于一些核心接口,也可以阅读一下相关的源代码,深入理解其背后的原理。

  • 自我考核:在 LightGBM 框架下,实现一个自定义的损失函数,并跑通训练与预测流程。

其它框架

其它比较常见且与算法工程师日常工作会有一些联系的有 Web 框架,爬虫框架等,*具有代表性的当属 Flask 和 scrapy。这两者背后各自又是很大一块领域,尤其 web 开发更是保罗万象。感兴趣的同学还可以了解一下一些新兴的基于 Python3 的框架,例如 FastAPI,其背后借鉴的许多现代框架的思想设计,包括数据验证,序列化,自动文档,异步高性能等,开拓一下知识面。

  • 自我考核:实现一个简单的 model serving http 服务。

算法工程交叉

大规模算法运行

分布式训练

在很多项目中,数据量达到十亿级以上的情况下,单机训练会难以支撑。因此分布式训练也是实际工程落地中非常重要的一个主题。分布式训练涉及到多机的通讯协同方式,优化算法的改造,数据及模型的并行与聚合,以及框架的选择和运维等话题,具体可以参考《分布式机器学习》。另外对于分布式系统,也可以参阅《数据密集型应用系统设计》这本神作,了解其背后原理。

  • 自我考核:能够在多机上进行亿级数据的 GBDT 模型训练与预测。

高性能计算

在做大规模的数据训练与推理时,近些年涌现出许多高性能计算优化的方法,例如从硬件方面,有各种超线程技术,向量化指令集,GPGPU,TPU 的应用等,从软件方面,有针对数值计算场景的 OpenBLAS,有自动并行化的 OpenMP,有各种 codegen,JIT 技术下的运行时优化等。这方面可以学习的方向也很多,从基础的并行编程,编译原理及优化的知识开始,到 CUDA,OpenMP 的应用(例如 Nvidia 的 cuDNN,还有 LightGBM 中也用到了 OpenMP),Codegen,JIT 等技术在 Spark,TVM 等项目中的使用等,建议有深度性能优化需求时可以往这些方向做调研和学习。

  • 自我考核:能够通过 LLVM JIT 来优化实现 Spark window function 的执行性能。

模型加速领域

这个方向分两个部分,一块是模型训练方面,能够做到加速,例如使用大 batch size,迁移学习,持续的在线 / 增量学习等手段,另一块在模型预测方面,也有很多加速需求,比如模型参数量优化,模型压缩,混合精度,知识蒸馏等技术手段,都是为了做到更高性能,更低资源消耗的模型预测推理。这方面业界有各个方向的文章和技术实现可以参考,比如经典的《Training ImageNet in 1 Hour》,MobileNet,TensorRT,二值网络等。

  • 自我考核:在典型的销量预测场景中实现增量训练与预测。

MLOps

编排调度

包含各类 pipeline 的编排与调度能力的支持,包括数据 pipeline,训练 pipeline 和 serving pipeline 等。这方面比较常用的框架工具有 Airflow,DolphinScheduler,Cadence 等,需要掌握其基本的工作原理和使用方式,并能够应用于离线实验与线上运行。

  • 自我考核:使用 Airflow 完成一个标准的项目 pipeline 搭建与运行。

数据集成

相对于传统的 DevOps,机器学习项目*大的区别在于数据方面的依赖会更加显著与重要。这方面的话题包括数据血缘,数据质量保障,数据版本控制等,有各类工具可以借鉴使用,例如数据版本管理方面的 DVC,数据质量方面的 TFX Data Validation,Cerberus,Deequ 等。在方法论层面,《The ML Test Score》中给出了不少数据相关的具体测试方法,值得参考学习。

  • 自我考核:在项目中实现输入数据的分布测试,特征工程测试及特征重要性准入测试。

实验管理

这部分也是 ML 项目的独特之处,在开发过程中有大量的实验及相应的结果输出需要记录,以指导后续调整优化的方向,并选择*优结果来进行上线部署。这方面可以参考的项目有 MLflow,fitlog,wandb 等。当然对于单独的项目来说,可能 online Excel 就能满足需求了 🙂

  • 自我考核:在实际项目中实行一套标准的实验记录手段,并能从中找出各类实验尝试带来的精度提升的 top 5 分别是哪些操作。

Serving

目前我们的 serving 大多数是离线 batch 预计算的形式,所以主要依赖的技术手段是各类离线 inference 的方法,例如直接使用 model predict 接口,使用 mmlspark 等做大规模并行 inference 等。如果涉及到在线 serving,情况会更加复杂,例如在线 pipeline 的运行,实时特征获取,low latency/high throughput 的 serving 服务等,可以参考 TF Serving,MLeap,H2O,PredictionIO,PMML/PFA/ONNX 等开发标准模型格式等。

  • 自我考核:部署一个实时预测服务,能够根据用户输入产生相应的预测结果。

CI/CD

软件工程中的持续集成,持续部署已经成为一种标准实践,在算法项目中,额外引入了数据这个维度的复杂性,带来了一些新的挑战。在这个方向上,几个主要话题包括自动化测试,pipeline 打包部署,持续监控运维等,可以参考 Martin Fowler 关于 CD4ML 的文章。工具系统层面,可以学习传统的 Jenkins,也有一些新选择例如 CircleCI,GoCD,VerCD(Uber)等。

  • 自我考核:通过 Jenkins 实现 pipeline 自动测试,打包,上线流程。

系统监控

在整个项目上线后,需要对系统的各个环节进行监控,并对各种异常情况作出响应。例如输入数据的监控,判别测试数据与训练数据的分布是否有偏移,整个运行 pipeline 的监控,判别是否有运行失败抛出异常的情况,对于预测输出的监控,确保没有异常的预测输出值,也包括对于系统计算资源等方面的监控,确保不会因为资源不足导致业务受到影响等。在监控信息收集,基础上,还需要配套一系列的自动告警通知,日志追踪排查等。这方面的工具框架包括 TF data validation 这类专门针对算法项目的新产品,也有 elasicsearch + kibana 这类传统产品。

  • 自我考核:将三个项目中做过的问题排查改造成常规监控手段,支持自动的问题发现,告警通知,如有可能,提供自动化或半自动化的问题排查解决方案。

MLOps 系统

MLOps 整体是一个比较大的话题,在这方面有很多产品和系统设计方面的实践可以参考学习。例如 Uber 的 Michelangelo 系列文章,Facebook 的 FBLearner,neptune.ai,dataiku,domino 等,虽然没有开源,但是其背后的很多设计理念,演进思考,白皮书等都非常值得我们学习。在开源界也有很多可以参考的项目,例如 MLflow,Kubeflow,Metaflow,TFX 等,可以学习他们的设计理念,Roadmap,以及实现细节等。

  • 自我考核:总结各个 MLOps 产品的功能模块矩阵对比,能够根据项目需求来进行产品选型与使用。

工程深入方向

数据库

数据库原理

在平时工作中,我们有大量的场景需要用到数据库。从客户数据的对接,数据集的管理和使用,到各种业务系统的数据表设计及优化等,都需要对数据库的运作原理,适用场景,运维使用,性能优化等方面有一定的了解。常见的需要掌握的概念有 OLTP vs OLAP,事务,索引,隔离级别,ACID 与 CAP 理论,数据同步,数据分片,SQL 语法,ORM 等。从底层原理看,会涉及到数据,索引,及日志等存储引擎方面,以及各种计算查询引擎,包括分布式系统的设计与实现。这方面推荐的学习资料有《数据库系统内幕》及《数据密集型应用系统设计》。

  • 自我考核:能够理解 SQL 执行计划,并能够根据执行计划来做索引或查询调优。

关系型数据库

目前常用的关系型数据库主要是 MySQL 和 PostgreSQL,主要需要掌握的是日常的一些 SQL 操作,例如 DML(增删改查),DDL(创建表,修改索引等),DCL(权限相关)。在此基础上还可以进一步了解一些如数据类型,高级计算,存储引擎,部署运维,范式概念与表结构设计等方面的话题。对于高级话题这块,推荐《高性能 MySQL》与《高可用 MySQL》。

  • 自我考核:在 MySQL 中设计相关表结构,存储实际项目中的一系列中间数据集。

NoSQL 数据库

常用的 NoSQL 数据库有几类,KV 存储(Redis),文档数据库(MongoDB),Wide-column 存储(Cassandra,HBase)以及图数据库(Neo4j)。在目前我们的算法项目中,比较有可能会用到的主要是 Redis 这类 KV 存储(也可能把 Cassandra 之类当泛 KV 来用),或者更新一点的类似 Delta Lake 的存储系统。建议学习了解一下这类 KV 存储,以及分布式数据库的常见操作方式,以及基础的运维排查,性能优化方法。

  • 自我考核:考虑一个线上模型服务的场景,用户输入作为基础特征,使用类似 Redis 的 KV 系统,实现实时获取其它特征,并进行模型预测。

云计算

基础架构

IT 系统总体的发展趋势在往云计算方向演进,即使是自建的基础设施,也会采用云计算的一套构建方式,让开发者不用过多的关注底层计算存储资源的部署运维。对于应用开发者来说,需要了解一些基础架构方面的知识,例如各类虚拟化及容器技术,配置管理,容器编排等,便于在日常工作中使用相关技术来管理和发布应用。从工具层面看,Docker 与 k8s 等技术发展速度较快,主要还是根据官方文档来学习为主。浙大之前出版的《Docker – 容器与容器云》一书中有一些更深入的话题的探讨,另外《Kubernetes in Action》中也值得一读。从方法论层面看,《Infrastructure as Code》和《Site Reiliability Engineering》是两本非常不错的学习资料。与算法应用结合的虚拟化,运维,持续集成等都是比较新的领域,需要我们探索出一条可行路线。

  • 自我考核:对于已有的算法项目,总结制定一套开发,测试,发布,运维的标准流程,且尽可能自动化执行。

分布式存储

前些年*流行的分布式存储是脱胎于 Google 经典的 GFS 论文实现的 HDFS,不过随着硬件技术的发展,计算存储分离思想的逐渐兴起,不但灵活性更高,成本更低,且各自架构的复杂度也大大降低了。因此目前更建议学习简单的 object store 形式的分布式存储,例如 s3,minio 等。在此基础上的一些存储系统,例如 Delta Lake,提供了事务,高效的 upsert,time travel 等功能,也值得关注与学习。原理方面,还是推荐《数据密集型应用设计》这本。

  • 自我考核:在项目中实现不同机器能够访问同一个 s3 路径的文件,并进行正常的数据读写,模型文件读写等功能。

分布式计算

大数据时代的分布式计算的鼻祖来自于 Google 经典的 MapReduce 论文,后续在 Hadoop 系统中做了开源实现,在前几年是非常火热的一项技术。目前业界的主流是 Spark 和 Flink,前者在批处理计算中处于霸者地位,后者是流处理领域的*者。目前我们的业务应用中,Spark 是比较常用的分布式计算引擎,其基本操作相关内容比较简单,参考官方文档或者《Spark 快速大数据分析》即可。后续的主要难点会有大数据量下的问题排查与性能调优,执行复杂计算或与 Python 相关 UDF 的交互配合方式等。这方面需要对 Spark 的系统架构,内部原理有一定了解,例如 master,worker,driver,executor 等之间的关系,lazy evaluation,DAG 的 lineage 与 stage 概念,shuffle 优化,wholestage codegen 等技术细节。这方面暂时没有找到比较好的资料,主要还是依赖实际问题解决的经验积累。

  • 自我考核:用 Spark 来实现项目中的特征工程,并在一定数据量情况下取得比单机 Pandas 更好的性能效果。

其它话题

其它云服务基础设施还包括分布式数据库,消息队列,zk/raft 分布式协作系统,虚拟网络,负载均衡等。这些话题离算法应用方面会比较远一些,基本上达到遇到需求时会使用的能力即可,在这里不做展开。

算法深入方向

AutoML

超参优化

自动化机器学习中比较传统的一块是超参数优化,进而可以推广到整个 pipeline 的超参优化,包括数据预处理,特征工程,特征选择,模型选择,模型调优,后处理等部分。目前业界应用比较广泛的技术手段主要是随机搜索,贝叶斯优化,进化算法,Hyperband/BOHB 等,在特征工程方面有 Featuretools,tsfresh,AutoCrossing 等自动化特征工程工具。学术界有一些进一步的探索研究,包括 multi-fidelity 优化,多任务优化,HPO 结合 ensemble learning,pipeline planning,data diff 自动数据分布探测等方面。可以参考 http://automl.org 上的各类参考资料与书籍进行学习了解。主要难点包括 automl 算法的泛化能力,scalability,整体 pipeline 组合的搜索与生成,针对不同学习算法的自动优化手段等。

  • 自我考核:了解超参优化的基础概念,能够在项目中应用框架工具来实现模型超参的贝叶斯优化流程。

元学习

Meta learning 是近年来非常活跃的一个新兴领域,其主要思路是希望能通过元学习模型方法,去积累建模调优的先验知识,跨任务推断模型效果并 warm start 新的训练任务,或者指导学习算法来进行更高效的具体任务的训练过程。这方面在工业界的主要应用基本上集中在建模调优先验知识的积累方面,比如通过一系列公开数据集搜索寻找出表现较好的起始参数,用于指导在新任务上做超参优化的起始搜索点。学术研究中除了 configuration space 的研究,还包括从 learning curve 中进行学习推断,元特征提取与建模,HTN planning 在 pipeline 构建中的应用,以及 MAML 等 few-shot learning 方向的探索。这方面推荐 Lilian Weng 的一系列文章(https://lilianweng.github.io/lil-log/2018/11/30/meta-learning.html),以及 http://automl.org 网站上的资料。

  • 自我考核:设计一系列 meta feature 与 meta learning 手段,实现对新任务的参数选择的初始化。

NAS

AutoML 领域比较火,但也是比较特别的一个方向,目前需要大量的计算资源投入才能做这方面的研究与尝试,因此主要建议了解一下这个方向的一些工作即可,不做深入探索学习。

AutoML 系统

自动化机器学习相关的框架工具也非常多,比较有代表性的框架有 auto-sklearn(来自 http://automl.org 团队),nni(microsoft),auto-gluon(amazon),H2O,ray tune 等,在工具级别也有如 hyperopt,SMAC3,featuretools 等。可以通过学习这些工具框架,了解 AutoML 系统的架构与实现方式,并应用到实际项目中。

  • 自我考核:使用一种 AutoML 系统来进行项目的模型自动优化,并与手工优化的结果进行比较,看是否有所提升,及寻找背后的原因。

模型解释

模型解释技术

主要有三个方面,一是模型本身的解释性,例如线性回归,决策树等,模型结构简单,根据其原理,可以直接对预测结果,特征使用等方面给出解释。另外一些复杂模型,例如 EBM,神经网络,Bayesian rule lists,SLIMs 等,也可以利用一些本身的特性给出一些解释,例如 GradCAM 方法等。二是模型无关的解释方法,包括经典的 PDP,ICE 等特征图,LIME 等 surrogate model 方法,以及基于博弈论的 Shapley 方法。三是基于 sample 的解释方法,例如 conterfactual explanations,adversarial examples,prototypes,influential instances,kNN 等,不过看起来这类方法对于计算的开销一般都会比较大,不太容易在工程中实现落地。这方面的资料可以学习《Interpretable Machine Learning》和《Explainable AI》(关于深度学习的内容会更多)。另外学术界也有很多前沿探索,比如针对模型解释的降维工作,自动的时间序列分析及报告生成,因果模型,模型公平性及社会影响等方面,可以保持关注。

  • 自我考核:理解 LIME,Shapley 的运作原理,并分析其局限性,尝试提出改进方案。

模型解释应用

从工具框架方面,有许多可以使用的开源项目,例如微软的 interpret,eli5,shap,AIX360 等。另外也有一些非传统意义上的模型解释,例如 manifold,tensorboard 这类模型 debugging 工具,自动化的误差分析与模型改进方案,因果模型框架,模型公平性评估与纠正工具等,都可以涵盖在广义的模型解释领域中。在工具基础上,如何结合业务领域知识,给出更有针对性的解释方案,也是值得思考深挖的方向。

  • 自我考核:使用 shap,eli5 等工具来进行模型解释,并在此基础上形成面向开发者的模型 debug,误差分析及改进方案,或形成面向业务的 what-if 分析看板。

总结

目前机器学习应用领域还在高速发展与演进过程中,除了上述提到的技能方向,后续很可能会不断有新的主题引入进来,需要练就快速学习并应用落地的能力。在掌握前面编程,软件工程,机器学习的基础上,后半部分的研究方向,大家可以根据个人兴趣,选择几个进行深入探索与实践。仅阅读相关书籍和文章,只能对知识内容有一个初步的认识,必须要通过深入的动手实践,反复试错思考和修正,才能逐渐内化为自己的技能,并构建起较为坚实的知识体系。

原文链接:https://zhuanlan.zhihu.com/p/192633890

IOS学习之UITableView表视图控件初步

表视图这个控件学习的时候,发现是目前我接触到*复杂的组件。

在Android中也提供了类似表视图的控件叫ListView。

原生的ListView,支持的操作其实很有限,数据的条目展示,点击或是长按的操作。

后来慢慢的衍生出来的索引,分区,动态改变指定条目位置等。

到了IOS发现,原来都是这些设计概念全是从IOS的表视图移植过去的吧。

因此,IOS的表视图是个挺丰富的控件

以下文章内容我基本是这么个流程划分

*简单的表视图——》自定义Cell表——》可编辑表——》可动态移动表

以下是配合Navigation导航条控件演示的tableView各种实现。

一:基础表视图

我们看下表视图一个大致的界面模型

首先是navc的顶级视图

%title插图%num

这个视图控制器的代码基本很前面提到的导航那章一样,只是多了一个数组容器来保存要显示的三个二级视图控制器

看下m文件

[cpp] view plain copy

  1. // 
  2. //  NonoFirstLevelViewController.m 
  3. //  NavTest 
  4. // 
  5. //  Created by Nono on 12-4-26. 
  6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved. 
  7. // 
  8. #import “NonoFirstLevelViewController.h” 
  9. #import “NonoSecondLevelViewController.h” 
  10. #import “SimpleTableViewController.h” 
  11. #import “CustomCellViewController.h” 
  12. #import “EditViewController.h” 
  13. @interface NonoFirstLevelViewController ()
  14. @end
  15. @implementation NonoFirstLevelViewController
  16. @synthesize controllers = _controllers;
  17. #pragma 实现头文件中自定义方法; 
  18. – (void)initAllSecondControllers:(NSMutableArray *)array
  19. {
  20.     SimpleTableViewController *controller1 = [[SimpleTableViewController alloc] init];
  21.     [controller1 setTitle:@“简单表视图”];
  22.     [array addObject:controller1];
  23.     [controller1 release];
  24.     CustomCellViewController *controller2 = [[CustomCellViewController alloc] init];
  25.      [controller2 setTitle:@“自定义cell视图”];
  26.     [array addObject:controller2];
  27.     [controller2 release];
  28.     EditViewController *controller3 = [[EditViewController alloc] init];
  29.     [controller3 setTitle:@“可编辑视图”];
  30.     [array addObject:controller3];
  31.     [controller3 release];
  32. }
  33. – (id)initWithStyle:(UITableViewStyle)style
  34. {
  35.     self = [super initWithStyle:style];
  36.     if (self) {
  37.     }
  38.     return self;
  39. }
  40. – (void)viewDidLoad
  41. {
  42.     [super viewDidLoad];
  43.     self.title = @“表视图Demo”;
  44.     //实例化一个可变数组 
  45.     NSMutableArray *array = [[NSMutableArray alloc] init ];// 
  46.     self.controllers = array;
  47.     [array release];
  48.     [self initAllSecondControllers:self.controllers];
  49. }
  50. – (void)viewDidUnload
  51. {
  52.     [super viewDidUnload];
  53. }
  54. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  55. {
  56.     return (interfaceOrientation == UIInterfaceOrientationPortrait);
  57. }
  58. #pragma mark – Table view data source 
  59. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  60. {
  61.     return [self.controllers count];
  62. }
  63. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  64. {
  65.     static NSString *CellIdentifier = @“FirstLevelCell”;
  66.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  67.     if (cell == nil) {
  68.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  69.     }
  70.     NSUInteger row = [indexPath row];
  71.     NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];
  72.     cell.textLabel.text = [controller title];
  73.     return cell;
  74. }
  75. #pragma mark – Table view delegate 
  76. – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  77. {
  78.     NSUInteger row = [indexPath row];
  79.     NonoSecondLevelViewController  *secondVC = [self.controllers objectAtIndex:row];
  80.      [self.navigationController pushViewController:secondVC animated:YES];
  81. }
  82. @end
  1. //
  2. // NonoFirstLevelViewController.m
  3. // NavTest
  4. //
  5. // Created by Nono on 12-4-26.
  6. // Copyright (c) 2012年 NonoWithLilith. All rights reserved.
  7. //
  8. #import “NonoFirstLevelViewController.h”
  9. #import “NonoSecondLevelViewController.h”
  10. #import “SimpleTableViewController.h”
  11. #import “CustomCellViewController.h”
  12. #import “EditViewController.h”
  13. @interface NonoFirstLevelViewController ()
  14. @end
  15. @implementation NonoFirstLevelViewController
  16. @synthesize controllers = _controllers;
  17. #pragma 实现头文件中自定义方法;
  18. – (void)initAllSecondControllers:(NSMutableArray *)array
  19. {
  20. SimpleTableViewController *controller1 = [[SimpleTableViewController alloc] init];
  21. [controller1 setTitle:@“简单表视图”];
  22. [array addObject:controller1];
  23. [controller1 release];
  24. CustomCellViewController *controller2 = [[CustomCellViewController alloc] init];
  25. [controller2 setTitle:@“自定义cell视图”];
  26. [array addObject:controller2];
  27. [controller2 release];
  28. EditViewController *controller3 = [[EditViewController alloc] init];
  29. [controller3 setTitle:@“可编辑视图”];
  30. [array addObject:controller3];
  31. [controller3 release];
  32. }
  33. – (id)initWithStyle:(UITableViewStyle)style
  34. {
  35. self = [super initWithStyle:style];
  36. if (self) {
  37. }
  38. return self;
  39. }
  40. – (void)viewDidLoad
  41. {
  42. [super viewDidLoad];
  43. self.title = @“表视图Demo”;
  44. //实例化一个可变数组
  45. NSMutableArray *array = [[NSMutableArray alloc] init ];//
  46. self.controllers = array;
  47. [array release];
  48. [self initAllSecondControllers:self.controllers];
  49. }
  50. – (void)viewDidUnload
  51. {
  52. [super viewDidUnload];
  53. }
  54. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  55. {
  56. return (interfaceOrientation == UIInterfaceOrientationPortrait);
  57. }
  58. #pragma mark – Table view data source
  59. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  60. {
  61. return [self.controllers count];
  62. }
  63. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  64. {
  65. static NSString *CellIdentifier = @“FirstLevelCell”;
  66. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  67. if (cell == nil) {
  68. cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  69. }
  70. NSUInteger row = [indexPath row];
  71. NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];
  72. cell.textLabel.text = [controller title];
  73. return cell;
  74. }
  75. #pragma mark – Table view delegate
  76. – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  77. {
  78. NSUInteger row = [indexPath row];
  79. NonoSecondLevelViewController *secondVC = [self.controllers objectAtIndex:row];
  80. [self.navigationController pushViewController:secondVC animated:YES];
  81. }
  82. @end

顶视图类基本就是一个导航作用。

线面我么先看*简单的这条目

简单表视图:%title插图%num

[cpp] view plain copy

  1. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3.     //控件复用 
  4.     static NSString *CellIdentifier = @“simpleCell”;
  5.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  6.     if (cell == nil) {
  7.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  8.     }
  9.     NSUInteger row = [indexPath row];
  10.     NSString *string = [self.data objectAtIndex:row];
  11.     cell.textLabel.text = string;
  12.     //这个可以定义item右端小图标显示风格,默认是none; 
  13.     //cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; 
  14.     [string release];
  15.     return cell;
  16. }
  1. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. //控件复用
  4. static NSString *CellIdentifier = @“simpleCell”;
  5. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  6. if (cell == nil) {
  7. cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  8. }
  9. NSUInteger row = [indexPath row];
  10. NSString *string = [self.data objectAtIndex:row];
  11. cell.textLabel.text = string;
  12. //这个可以定义item右端小图标显示风格,默认是none;
  13. //cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
  14. [string release];
  15. return cell;
  16. }

这边主要说如下几点:

1》。控件得复用,这个和Android很像,因此我们在获取cell对象时,先从原来得复用队列里查找(更具指定的标记,这点也告诉我们,我们可以设置多个标记),

若没有,那就新建一个

2》。整个tableview的style分两种,一种就是顶级视图界面的那种: self.tableView.style = UITableViewStylePlain,另一种就是这个视图的风格:

self.tableView.style = UITableViewStyleGrouped

3》.对于每个item,单元格样式使用了3个不同的单元格元素。依次左边开始有个图标,中间就是一个label,右侧会有一个详情栏。

4》。同样的对于每个cell也是有样式风格的 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]

针对3,4设置后得某种效果如下:

%title插图%num%title插图%num

左端可以自己敬爱个图标进去,黑体字就是文本label,灰色的是详细文本标签,小箭头图标是accessoryType

以下就是代码

[cpp] view plain copy

  1. static NSString *CellIdentifier = @“FirstLevelCell”;
  2. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  3. if (cell == nil) {
  4.     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
  5. }
  6. NSUInteger row = [indexPath row];
  7. NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];
  8. cell.textLabel.text = [controller title];
  9. cell.detailTextLabel.text = @“什么情况”;
  10. //这个可以定义item右端小图标显示风格,默认是none; 
  11. cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
  12. return cell;
  1. static NSString *CellIdentifier = @“FirstLevelCell”;
  2. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  3. if (cell == nil) {
  4. cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
  5. }
  6. NSUInteger row = [indexPath row];
  7. NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];
  8. cell.textLabel.text = [controller title];
  9. cell.detailTextLabel.text = @“什么情况”;
  10. //这个可以定义item右端小图标显示风格,默认是none;
  11. cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
  12. return cell;

默认风格的cell是不能显示详情标签内容的。

其实很多效果,代码都走一边就看出来了,具体就自己改动下代码就ok了

二:自定义的Cell

%title插图%num%title插图%num

自定义的cell,xib实现

%title插图%num%title插图%num

基本没什么好说的,看下该类额控制器文件

[cpp] view plain copy

  1. // 
  2. //  CustomCellViewController.m 
  3. //  NavTest 
  4. // 
  5. //  Created by Nono on 12-5-4. 
  6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved. 
  7. // 
  8. #import “CustomCellViewController.h” 
  9. @interface CustomCellViewController ()
  10. @end
  11. @implementation CustomCellViewController
  12. @synthesize customCell = _customCell;
  13. – (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  14. {
  15.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  16.     if (self) {
  17.         // Custom initialization 
  18.     }
  19.     return self;
  20. }
  21. – (void)viewDidLoad
  22. {
  23.     [super viewDidLoad];
  24.     NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@“陈凯”,@“Nono”,@“Lilith”,@“窗前明月光”,@“疑是地上霜”,@“举头望明月”,@“低头思故乡”,@“锄禾日当午”,@“汗滴禾下土”,@“谁知盘中餐”,@“粒粒皆幸苦”,nil];
  25.     self.data = array;
  26.     [array release];
  27.     // Do any additional setup after loading the view from its nib. 
  28. }
  29. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  30. {
  31.     return (interfaceOrientation == UIInterfaceOrientationPortrait);
  32. }
  33. #pragma mark_ 
  34. #pragma 数据源方法 
  35. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  36. {
  37.     return [self.data count];
  38. }
  39. // Row display. Implementers should *always* try to reuse cells by setting each cell’s reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: 
  40. // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) 
  41. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  42. {
  43.     static NSString *CellIdentifier = @“CustomCell”;
  44.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  45.     if (cell == nil) {
  46.         NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@“CustomCell” owner:self options:nil];
  47.         if([nib count] > 0){
  48.             cell = self.customCell;
  49.             cell.backgroundColor = [UIColor redColor];
  50.         }else{
  51.             NSLog(@“加载 nib文件失败”);
  52.         }
  53.     }
  54.     NSUInteger row = [indexPath row];
  55.     NSString *string = [self.data objectAtIndex:row];
  56.     UILabel *customlabel =(UILabel*) [cell viewWithTag:11];
  57.     customlabel.text = string;
  58.     [string release];
  59.     return cell;
  60. }
  61. @end
  1. //
  2. // CustomCellViewController.m
  3. // NavTest
  4. //
  5. // Created by Nono on 12-5-4.
  6. // Copyright (c) 2012年 NonoWithLilith. All rights reserved.
  7. //
  8. #import “CustomCellViewController.h”
  9. @interface CustomCellViewController ()
  10. @end
  11. @implementation CustomCellViewController
  12. @synthesize customCell = _customCell;
  13. – (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  14. {
  15. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  16. if (self) {
  17. // Custom initialization
  18. }
  19. return self;
  20. }
  21. – (void)viewDidLoad
  22. {
  23. [super viewDidLoad];
  24. NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@“陈凯”,@“Nono”,@“Lilith”,@“窗前明月光”,@“疑是地上霜”,@“举头望明月”,@“低头思故乡”,@“锄禾日当午”,@“汗滴禾下土”,@“谁知盘中餐”,@“粒粒皆幸苦”,nil];
  25. self.data = array;
  26. [array release];
  27. // Do any additional setup after loading the view from its nib.
  28. }
  29. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  30. {
  31. return (interfaceOrientation == UIInterfaceOrientationPortrait);
  32. }
  33. #pragma mark_
  34. #pragma 数据源方法
  35. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  36. {
  37. return [self.data count];
  38. }
  39. // Row display. Implementers should *always* try to reuse cells by setting each cell’s reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
  40. // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
  41. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  42. {
  43. static NSString *CellIdentifier = @“CustomCell”;
  44. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  45. if (cell == nil) {
  46. NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@“CustomCell” owner:self options:nil];
  47. if([nib count] > 0){
  48. cell = self.customCell;
  49. cell.backgroundColor = [UIColor redColor];
  50. }else{
  51. NSLog(@“加载 nib文件失败”);
  52. }
  53. }
  54. NSUInteger row = [indexPath row];
  55. NSString *string = [self.data objectAtIndex:row];
  56. UILabel *customlabel =(UILabel*) [cell viewWithTag:11];
  57. customlabel.text = string;
  58. [string release];
  59. return cell;
  60. }
  61. @end

提几个注意点:

1》。cell的xib文件得拥有者设置成该类,在该类得头文件中定义一个输出口。

2》 我们看到cell的xib文件有3个label视图我们能看到,其实还有一个没有title的label视图,也就我们要动态添加数据的那个视图,

在xib文件中需要给他设置一个tag,这样我们在代码里才能根据tag找出该对象(和Android中得id很像)。这边我定义了11,所以

 UILabel *customlabel =(UILabel*) [cellviewWithTag:11];

    customlabel.text = string;

3》。xib文件加载,我是根据书上得列子方法。根据应用的束来获取。

4》。哦,还有点就是 static NSString *CellIdentifier = @”CustomCell”;。这个在xib文件得指定器中定义,因为原本我们新建一个cell是有个传入指定标签,
而现在这个新建一个cell说白了就是直接从xib中加载一个实例化了,那么指定器怎需要在xib中定义下。
对于cell简单的自定义就是这样。

三:可编辑的tableView(删除,添加,移动)

%title插图%num%title插图%num

[cpp] view plain copy

  1. // 
  2. //  EditViewController.m 
  3. //  NavTest 
  4. // 
  5. //  Created by Nono on 12-5-4. 
  6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved. 
  7. // 
  8. #import “EditViewController.h” 
  9. @interface EditViewController ()
  10. @end
  11. @implementation EditViewController
  12. @synthesize edittableView;
  13. – (void)editButtonPressed:(id)sender
  14. {
  15.     [self.edittableView setEditing:!self.edittableView.editing animated:(YES)];
  16.     if (edittableView.editing) {
  17.         [self.navigationItem.rightBarButtonItem setTitle:@“完成”];
  18.     }else {
  19.         [self.navigationItem.rightBarButtonItem setTitle:@“编辑”];
  20.     };
  21.     NSLog(@“点击了按钮”);
  22. }
  23. – (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  24. {
  25.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  26.     if (self) {
  27.         // Custom initialization 
  28.     }
  29.     return self;
  30. }
  31. – (void)viewDidLoad
  32. {
  33.     [super viewDidLoad];
  34.     NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@“陈凯”,@“Nono”,@“Lilith”,@“窗前明月光”,@“疑是地上霜”,@“举头望明月”,@“低头思故乡”,@“锄禾日当午”,@“汗滴禾下土”,@“谁知盘中餐”,@“粒粒皆幸苦”,nil];
  35.     self.data = array;
  36.     [array release];
  37.     UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc]  initWithTitle:@“编辑”  style:UIBarButtonItemStyleBordered  target:self  action:@selector(editButtonPressed:)];
  38.     self.navigationItem.rightBarButtonItem = rigthButton;
  39.     //self.navigationItem.prompt = @”加载”; 
  40.     [rigthButton release];
  41.     // Do any additional setup after loading the view from its nib. 
  42. }
  43. – (void)viewDidUnload
  44. {
  45.     [super viewDidUnload];
  46.     // Release any retained subviews of the main view. 
  47.     // e.g. self.myOutlet = nil; 
  48. }
  49. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  50. {
  51.     return (interfaceOrientation == UIInterfaceOrientationPortrait);
  52. }
  53. #pragma mark – Table view data source 
  54. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  55. {
  56.     // Return the number of rows in the section. 
  57.     return [self.data count];
  58. }
  59. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  60. {
  61.     static NSString *CellIdentifier = @“editLevelCell”;
  62.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  63.     if (cell == nil) {
  64.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  65.     }
  66.     NSUInteger row = [indexPath row];
  67.     NSString *string = [self.data objectAtIndex:row];
  68.     cell.textLabel.text = string;
  69.     [string release];
  70.     return cell;
  71. }
  72. #pragma 实现数据源协议中一些关于编辑操作方法 
  73. – (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
  74. {
  75.     //是否可以编辑,即是tableView setEditing的前提;默认是yes,实现这个方法估计主要是选择性的编辑条目。 
  76.     return YES;
  77. }
  78. – (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
  79. {
  80.     //同理默认其实就是yes,移动模式(会显示可以触摸得移动button)必须是在实现了下面这个方法才有效,否则及时yes了,移动模式条也是不显示的,简单的说,你不能执行移动操作 
  81.     return YES;
  82. }
  83. //移动操作 
  84. – (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
  85. {
  86.     //拖动得思路就是先备份选中行,删除原来那份,将备份的一份插入到目标行 
  87.     NSUInteger fromRow = [sourceIndexPath row];
  88.     NSUInteger toRow = [destinationIndexPath row];
  89.     id ob = [[self.data objectAtIndex:fromRow] retain];
  90.     [self.data removeObjectAtIndex:fromRow];
  91.     [self.data insertObject:ob atIndex:toRow];
  92.     [ob release];
  93. }
  94. – (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
  95. {
  96.       NSUInteger row = [indexPath row];
  97.     //提交操作完的编辑 
  98.     if (editingStyle == UITableViewCellEditingStyleDelete) {
  99.         [self.data removeObjectAtIndex:row]; //删除操作 
  100.         [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
  101.     }
  102.     if (editingStyle == UITableViewCellEditingStyleInsert) {
  103.         [self.data insertObject:@“插入数据” atIndex:row];//插入操作 
  104.         [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
  105.     }
  106. }
  107. #pragma 实现tableView委托中一些方法 
  108. – (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
  109. {
  110.     //设置可编辑得样式:系统提供了三种,一种是删除,一种是插入,一种时是none 
  111.     NSInteger row = [indexPath row];
  112.     if(row %2 == 0)//这边做了小处理,间隔显示删除和插入 
  113.     {
  114.         return UITableViewCellEditingStyleDelete;
  115.     }
  116.     return UITableViewCellEditingStyleInsert;
  117. }
  118. @end
  1. //
  2. // EditViewController.m
  3. // NavTest
  4. //
  5. // Created by Nono on 12-5-4.
  6. // Copyright (c) 2012年 NonoWithLilith. All rights reserved.
  7. //
  8. #import “EditViewController.h”
  9. @interface EditViewController ()
  10. @end
  11. @implementation EditViewController
  12. @synthesize edittableView;
  13. – (void)editButtonPressed:(id)sender
  14. {
  15. [self.edittableView setEditing:!self.edittableView.editing animated:(YES)];
  16. if (edittableView.editing) {
  17. [self.navigationItem.rightBarButtonItem setTitle:@“完成”];
  18. }else {
  19. [self.navigationItem.rightBarButtonItem setTitle:@“编辑”];
  20. };
  21. NSLog(@“点击了按钮”);
  22. }
  23. – (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  24. {
  25. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  26. if (self) {
  27. // Custom initialization
  28. }
  29. return self;
  30. }
  31. – (void)viewDidLoad
  32. {
  33. [super viewDidLoad];
  34. NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@“陈凯”,@“Nono”,@“Lilith”,@“窗前明月光”,@“疑是地上霜”,@“举头望明月”,@“低头思故乡”,@“锄禾日当午”,@“汗滴禾下土”,@“谁知盘中餐”,@“粒粒皆幸苦”,nil];
  35. self.data = array;
  36. [array release];
  37. UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc] initWithTitle:@“编辑” style:UIBarButtonItemStyleBordered target:self action:@selector(editButtonPressed:)];
  38. self.navigationItem.rightBarButtonItem = rigthButton;
  39. //self.navigationItem.prompt = @”加载”;
  40. [rigthButton release];
  41. // Do any additional setup after loading the view from its nib.
  42. }
  43. – (void)viewDidUnload
  44. {
  45. [super viewDidUnload];
  46. // Release any retained subviews of the main view.
  47. // e.g. self.myOutlet = nil;
  48. }
  49. – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  50. {
  51. return (interfaceOrientation == UIInterfaceOrientationPortrait);
  52. }
  53. #pragma mark – Table view data source
  54. – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  55. {
  56. // Return the number of rows in the section.
  57. return [self.data count];
  58. }
  59. – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  60. {
  61. static NSString *CellIdentifier = @“editLevelCell”;
  62. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  63. if (cell == nil) {
  64. cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  65. }
  66. NSUInteger row = [indexPath row];
  67. NSString *string = [self.data objectAtIndex:row];
  68. cell.textLabel.text = string;
  69. [string release];
  70. return cell;
  71. }
  72. #pragma 实现数据源协议中一些关于编辑操作方法
  73. – (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
  74. {
  75. //是否可以编辑,即是tableView setEditing的前提;默认是yes,实现这个方法估计主要是选择性的编辑条目。
  76. return YES;
  77. }
  78. – (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
  79. {
  80. //同理默认其实就是yes,移动模式(会显示可以触摸得移动button)必须是在实现了下面这个方法才有效,否则及时yes了,移动模式条也是不显示的,简单的说,你不能执行移动操作
  81. return YES;
  82. }
  83. //移动操作
  84. – (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
  85. {
  86. //拖动得思路就是先备份选中行,删除原来那份,将备份的一份插入到目标行
  87. NSUInteger fromRow = [sourceIndexPath row];
  88. NSUInteger toRow = [destinationIndexPath row];
  89. id ob = [[self.data objectAtIndex:fromRow] retain];
  90. [self.data removeObjectAtIndex:fromRow];
  91. [self.data insertObject:ob atIndex:toRow];
  92. [ob release];
  93. }
  94. – (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
  95. {
  96. NSUInteger row = [indexPath row];
  97. //提交操作完的编辑
  98. if (editingStyle == UITableViewCellEditingStyleDelete) {
  99. [self.data removeObjectAtIndex:row]; //删除操作
  100. [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
  101. }
  102. if (editingStyle == UITableViewCellEditingStyleInsert) {
  103. [self.data insertObject:@“插入数据” atIndex:row];//插入操作
  104. [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
  105. }
  106. }
  107. #pragma 实现tableView委托中一些方法
  108. – (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
  109. {
  110. //设置可编辑得样式:系统提供了三种,一种是删除,一种是插入,一种时是none
  111. NSInteger row = [indexPath row];
  112. if(row %2 == 0)//这边做了小处理,间隔显示删除和插入
  113. {
  114. return UITableViewCellEditingStyleDelete;
  115. }
  116. return UITableViewCellEditingStyleInsert;
  117. }
  118. @end

基本代码如上。

ios 调用webservice整理

学iphone开发有一段时间了,对于我这个新手来说,学习过程中,遇到不少问题,尤其是webservice的调用一直困扰了很久,赶在光棍前夕之迹,谈谈个人在webservice方面遇到的问题以及解决方案~~跟大家分享一下,对于那些高手来说可以略过~~

也不知道这是人生中的第几个光棍节了,没有妹子,很纠结,没有遇到对的人,在爱情的等待中渐渐的发霉~~~~~~~~

在这里也祝单身的男银、女银们,在光棍节脱”光”~~~~废话不多说~~切入正题

一、简述

要调用webservice你想到的是什么?

(1)写一个调用webservice的类(可以自已写,也可以下载第三方的类库)

(2)对webservice返回的xml解析(ios自带的xml解析真的很烦)

      我在网上度娘了很网,都是看到有些人,要么只提供webservice的类,简单的说明一下,对于返回的数据xml,一字不提~~~用起他们写的类来,真的很冒烟啊~~~~,网上找到的一些答案,我觉得很奇怪,大牛们经常会写一句不明不白的话,要写就写清楚,否则干脆不要写~~~让人希望又失望~~我不觉得这样有多牛B。。。反而我更喜欢把复杂的事件简单化~~~

我个人在调用webservice时遇到几个问题:

  a.webservice的命名空间问题?

     webservice默认的命名空间是:http://tempuri.org/

    我刚开始用得好好的,后来报soapAction不识别http://tempuri.org/~~~~那天花了一上午才找出这个错,原来有人改动了webservice的默认命名空间~~~我去你大爷的,改了命名空间,也不通知我,害我瞎折腾~~

  b.xml如何解析问题?

     本来是想用ios自带的类去解析xml的,网上查了一下,看别人写了一大片,脑门一片大汗,满脸黑线~~~,后来我用的是google写的GDataXML这个类库,还不错~~~,不过对于那些xml有命名空间的如何读取,各种坛子去提问,至今还没有人正确解答我~~~难道天朝就没有人知道吗?我失望至*,后来还是有如神助般醍醐灌顶~~~自已解决了,阿门~~~~

  c.异步调用时发生400错误?

    这个问题搞得我,头脑出现乱码,神经也被打茄了,你们猜这是啥原因~~~~

   soap原本要传递的信息是这样:

     <a>XXX</a><b>XXXX</b>

   我把它传递参数颠倒过来了,变成这样:

    <b>XXX</b><a>XXX</a>

    发现问题后,我傻楞般的笑了~~~~

  二、类的简要说明

(1)webservice(一个是使用NSURLConnection写的类,还有一个是ASIHttpRequest写的webservice调用类)

  a.同步调用

  b.异步调用

  c.返回数据的处理

     soap调用返回的数据经常放在:<webservice方法名Result>XXX</webservice方法名Result>中,我在webservice调用中已经直接提取出来了~~~提取出来的内容还是一个xml,这段内容的处理,我单独写在xml解析类里面

(2)xml解析类

1.读取<方法名Result>XXX</方法名Result>的内容

2.遍历xml的所有内容返回数组

三、使用配置

  (1)使用NSURLConnection写的webservice调用类,类名叫:WebServices.h

     包含的文件如下:

    a.AppConfigure.h文件的配置:

  b.google GDataXml配置如下:

     step1.先添加libxml2.dylib类库,不要告诉我这个都不会,拉去面壁~~~

    step2.操作如下图所示

  (2)借助ASIHttpRequest写的webservice调用类,类名叫:ServiceHelper.h

    跟(1)的配置一样,这里就不再重复说明,ASIHttpRequest要多添加几个类库,如下图所示

 四、文件下载

 (1)NSURLConnection类写的webservice调用类的所有文件下载

     http://dl.vmall.com/c0cld6ey99 [注:请下载demo里面的*新版本,有调整]

 (2)ASIHttpRequest类写的webservice调用类的所有文件下载

    http://dl.vmall.com/c0gx4evjva  [注:请下载demo里面的*新版本,有调整]

 五、demo下载      

demo下载地址: http://dl.vmall.com/c016bva6aw

android应用程序开发环境建立

之前一直在linux下面进行开发,用的都是c语言,自己无java基础,心血来潮只想玩玩,无其他追求,现记录当做笔记。

言归正传,要进行Android应用程序开发,首先的建立开发环境,参考网上资料,建立了一个自己的开发环境(vista系统),步骤如下:

1》安装java开发工具包

java开发工具包包括java开发工具JDK(JDK5 或 JDK6)、java运行环境JRE,在我的vista系统中JRE是随机附带的,而且实时升级,所以只需要安装JDK,window下面JDK的安装相当简单,下载到相应的安装文件并双击等待即可(我下载的JDK安装文件为:jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe,可以用google搜索下载)。之后把JDK、JRE相应的bin目录添加到系统环境变量PATH中,这样在dos的命令窗口中,不需要进入到JDK、JRE的bin目录就可以执行相应的操作。

2》下载Eclipse

进入Eclipse的官网:http://www.eclipse.org/downloads/下载集成开发环境Eclipse,下载时请选择“Eclipse IDE for Java Developers”,我下载了安装文件压缩包eclipse-java-helios-win32.zip,把该包放到某个目录下面如E:/java 解压,在E:/java目录下面出现eclipse目录,其中Eclipse的运行文件Eclipse.exe即在目录E:/java/eclipse中,双击Eclipse.exe即可启动集成开发环境eclipse。

3》安装Android开发工具扩展包ADT

启动eclipse,进入“Help->Install New SoftWare”弹出Install对话框,点击“Add…”弹出Add Repository对话框,在Location中输入ADT的网址http://dl-ssl.google.com/android/eclipse/site.xml ,之后点击ok确认,等待在线等待Eclipse搜索合适的ADT版本,之后搜索到该链接下的ADT:“Developer Tools”,选中该组件,确认“Install”按钮。几个下一步之后eclipse会自动安装ADT包,安装完成后eclipse提示重启,按“Yes”键确认重启,即可完成ADT的在线安装。

4》下载设置Android软件开发包SDK

说明下,我在Android官网上未找到合适的SDK版本,google到了一个地址:http://www.163pan.com/files/g0x000p0y.html,进入该URL,点击下载android-sdk-windows-1.5_r3.zip,把该压缩包放入到E:/java解压,在E:/java目录下出现android-sdk-windows目录。

启动eclipse,进入“Windows->Preferences” ,弹出Preferences对话框,在该对话框左边的树形机构中选择Android,点击“Browse…”按钮,选择刚才SDK解压的目录E:/java/android-sdk-windows确认,在Preferences对话框中确认”ok”,这样就可以把软件开发包SDK设置好。

在完成以上步骤后,Android的开发环境就建立好了,可以启动eclipse,进入“File->New->Project…”弹出New Project对话框,观察对话框是否和下图1一致,若能在该对话框中观测到Android 》Android Project则说明Android开发环境建立成功!

%title插图%num

图1 NewProject对话框

之后,可以利用SDK里面的Android应用程式工程实例,启动Android模拟器,如图2所示,具体步骤以后详述。

%title插图%num

图2 Android模拟器

Android模拟器的启动还需要进行一些设定,由于本文的主要内容在于前4步,所以这个过程将不再详述,在以后的文章中,如果涉及到这个问题我将再介绍。

后续:

又参考了网上的其他几篇文章,把SDK升级到了*新版本,模拟器的现实分辨率可以调到854*480,恰好我*近买了moto的milestone,刚好和我的真机匹配!google的东西做的真棒,模拟器做的这么的逼真,真的很方便开发者!我顺便把手机qq也装入到了模拟器中,详细步骤如下:

1》更新SDK

参考了这篇文章:http://www.javaeye.com/topic/520189,首先进入http://androidappdocs.appspot.com/sdk/index.html下载*新的SDK升级引导包,需要注意的是:首先这个包只有24M,不是真正的SDK包,只是一个引导在线升级的包;其次这个包是实时更新的,所以可能你下载的版本和本文中所述的版本不一致,我所下载的版本为:android-sdk_r06-windows.zip。

把包android-sdk_r06-windows.zip解压到E:/java/android-sdk-windows中,启动eclipse,进入“Window->Preferences” ,弹出Preferences对话框,在该对话框左边的树形机构中选择Android,点击“Browse…”按钮,选择刚才SDK解压的目录E:/java/android-sdk-windows确认;进入“Window->Android SDK and AVD Manager”选项卡,在该选项卡的左边选中“Installed Packages” 之后点击选项卡下发的“Update All…”,之后就可以一致等待直到在线升级SDK升级成功。

2》创建模拟器AVD

在SDK包升级成功后,会在E:/java/android-sdk-windows/目录下出现一个tools子目录,该目录下面存放的是android的命令行工具,*好把E:/java/android-sdk-windows/tools加入到环境变量PATH中,方便命令行操作。

通过命令行可创建模拟器AVD:

1:观察模拟器类型

在命令行中输入android list target ,显示:
Available Android targets:
id: 1 or “android-2”
Name: Android 1.1
Type: Platform
API level: 2
Revision: 1
Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
id: 2 or “android-3”
Name: Android 1.5
Type: Platform
API level: 3
Revision: 4
Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P
id: 3 or “android-4”
Name: Android 1.6
Type: Platform
API level: 4
Revision: 3
Skins: HVGA (default), QVGA, WVGA800, WVGA854
id: 4 or “android-5”
Name: Android 2.0
Type: Platform
API level: 5
Revision: 1
Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854
id: 5 or “android-6”
Name: Android 2.0.1
Type: Platform
API level: 6
Revision: 1
Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854
id: 6 or “android-7”
Name: Android 2.1-update1
Type: Platform
API level: 7
Revision: 2
Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854
id: 7 or “android-8”
Name: Android 2.2
Type: Platform
API level: 8
Revision: 2
Skins: HVGA (default), QVGA, WQVGA400, WQVGA432, WVGA800, WVGA854

2:创建id为7的模拟器avd

在命令行中输入android create avd -p c:/avd –target 7 –name test -s WVGA854

其中:-p代表模拟器的路径;–target代表模拟器的id;–name代表模拟器的名称;-s代表模拟器的皮肤(分辨率等),至此模拟器创建成功。

3》新建工程

启动eclipse,进入“New->Project…”,弹出“New Project”对话框,在该对好框中选择“Android->Android Project”,点击该选项卡的“Next”按钮,进入Android工程的创建,按照图3所示,使用SDK的exmaple目录下的已经存在的资源来创建工程,其中location中选择E:/java/android-sdk-windows/samples/android-8/ApiDemos,其他项按图3填、选。

%title插图%num

图3 利用SDK开发包中资源创建工程

4》设置工程运行/调试参数

进入“Run->Debug Configurations…”弹出Debug Configurations选项卡,右击该选项卡的左边菜单“Android Application”选择“New”,创建一个新的运行配置文件,各项的填、选如图4所示:

%title插图%num

图4 运行配置设置

5》运行工程

在eclipse的导航窗口中选中工程ApiDemos,进入“Run->Run”,刚开始设置好的avd模拟器就会启动起来,如果5所示。在该过程中,我遇到了一个问题,即模拟器显示的过大,撑满了我的电脑显示器,可以通过一下方法解决:http://android.yaohuiji.com/archives/151。

%title插图%num

图5 android模拟器启动画面

6》安装移动qq到模拟器

1.下载移动qq的安装文件:MobileQQ1_0(Android)_beta2_build0151.apk,可以通过google搜索得到;

2.把上述文件放置到SDK开发包相关位置:E:/java/android-sdk-windows/tools;

3.进入dos工具,cd到E:/java/android-sdk-windows/tools目录;

4.输入命令:adb install MobileQQ1_0(Android)_beta2_build0151.apk,等待片刻即可安装好移动qq。

注:应用程序的安装参考http://www.shouji56.com/ruanjian/article/3121.html。

之后就可以在模拟器的桌面上看到移动qq的快捷方式,点击登录,和我用milestone登录移动qq一样,值得体验!!!如图6所示:

%title插图%num

图6 移动qq快捷方式

后记

通过这一两天的折腾,Android应用程序开发环境算是搭建好了,以后的工作就是学习java,Android应用程序开发了。

开发者MAC电脑里的常见兵器

古人常以刀、枪、剑、戟、斧、钺、铲、叉、鞭、锏、锤、戈、镋、棍、槊、棒、矛、钯十八种兵器,样样精通,来形容一个人的武学技能get状态。在开发者的世界里,熟练掌握各种辅助工具,可以达到事半功倍,快速提高工作效率的效果。闲话不扯了,来看看究竟是什么。
道场

习武学道讲经论法总有个场所,这样容易把有意向来学习的人聚集起来,而且有助于信息的传播,精力的集中,技能的修炼,经验的交流和水平高下的切磋。工具的运用也是在一个特定的开发环境里才能发挥出比较好的效果。

我这里的开发环境(DOJO)是苹果公司Apple Inc.()2014年出的一款Mac Pro,具体配置如下:

MacBook Pro(Retina 显示屏,15 英寸,2014 年中)

处理器 2.2 GHz Intel Core i7

内存 16 GB 1600 MHz DDR3

图形卡 Intel Iris Pro 1536 MB

操作系统 OS X EI Capitan

这里描述的工具都是运行在这个硬件以及软件环境的,经过了2年多的开发经验/经历的靠谱验证,所以拿来分享给大家。

如果有朋友的研发环境和这里描述的不太一致,那么仅作参考吧,具体结合自己的情况。

为了方便检索,所以增加了工具分类。

开发*步是做什么?学习文档?画流程图?还是直接写代码?恩,先从学习文档开始吧。

文档查看

Dash

写代码的时候是不是有些API记不住,比如画椭圆该用哪个类?计算开平方用什么函数?怎么连接远程的mysql服务器检索数据?这个时候一般怎么办?问度娘?问谷歌?直接查看在线编程文档?

在国内问谷歌需要*,那么涉及到另外工具的使用。查看在线文档,如果记不住入口网址怎么办?放收藏里啊,如果入口改变了呢?还是需要问搜索引擎啊!那么问题来了,度娘乱贴小广告咋办?用Dash吧,一个APP搜罗了这个世界上几乎所有的编程语言文档,而且更新速度快。

软件主页以及下载地址:https://kapeli.com/dash

流程图设计
OmniGraffle有很多人推荐,不过笔者觉得这个软件太贵了,所以推荐了两款免费的软件流程设计工具。

XMind

主攻脑图(思维导图),流程图也支持,另外还有日程安排计划等额外的功能。

软件主页以及下载地址:http://www.xmind.net/

Gliffy Diagrams
并不是一个独立安装的APP,而是作为Chrome的插件,可以去Chrome的App Store下载安装,很轻量,运行速度快。

软件主页:https://www.gliffy.com/

文本编辑器
不仅限于代码编辑,一款好的编辑器会让你的编辑工作充满愉悦。

MacVim

为什么我一开始不推荐时下流行头牌Sublime呢?因为,我用vi/vim已经超过十年的时间了。当初在学校,vm/emacs二选一,我选择了更容易上手实践的vi,从此一直用它来查看/编译文本/代码。

软件主页以及下载地址:http://macvim-dev.github.io/macvim/

MacDown
一般代码查看和编辑用Vi就够了,剩下其他的文档,恩,现在大多数文章/文档采用的MarkDown语法编写,所以用一款MarkDown编辑器就够了。比如本文的编写,我用的MacDown编辑器,文章语法采用MarkDown语法。既然是MarkDown编辑器,那么有人会提到用Mou,笔者也试用过一段时间,遇到了一些问题,比如语法支持和界面显示,后来改用MacDown,觉得各方面都支持的不错,所以一直使用。

软件主页以及下载地址:http://macdown.uranusjr.com/

Sublime Text
如果你不是一路走着linux从事开发的话,估计很难对Vi/Emacs熟悉。那么,像note++或者ultraedit这类第三方编辑器会是你比较不错的选择。相比于集成开发环境IDE的笨重,运行慢和耗内存,选择一个轻量级的编辑器是在平时比较频繁的非常规查看/编辑代码/文档时一个不错的选择。那么,以前那些用第三方编辑器的用户都去哪儿了?应该就是这个Sublime Text了吧。

软件主页以及下载地址:http://www.sublimetext.com/

图片编辑器
写文章撸代码,除了文字的处理外,还需要有美图的点缀和衬托。更多时候,图是吸引流量和眼球的一种重要手段。

GIMP

为啥不用Adobe Photo Shop呢?太贵,太复杂。那么,好吧,这里笔者推荐用GIMP,PS该有的,它基本都有。

软件主页以及下载地址:http://www.gimp.org/

集成开发环境IDE
集成开发环境一般是集编辑,编译,链接,调试,版本管理和打包发布于一体的大型开发软件。它的特点是功能丰富,上手快,易操作。缺点也显而易见,笨重,运行速度慢,需要更多的CPU,内存资源。

Eclipse

老牌万金油型集成开发环境,上手快,支持几乎所有语言,但是近几年使用人数在下滑,逐渐转向Android Studio和IntelliJ IDEA了。

软件主页以及下载地址:http://www.eclipse.org

Android Studio
安卓程序猿专属开发环境。

软件主页以及下载地址:https://developer.android.com/studio/index.html

IntelliJ IDEA
Eclipse替代品,支持市面上大部分流行的开发语言和框架,上手快,界面更加人性化,现代集成开发环境的典范。

软件主页以及下载地址:https://www.jetbrains.com

Xcode
苹果公司官方唯一指定的Object-C与Swift集成开发环境。

软件主页以及下载地址:https://developer.apple.com/xcode/

分析调试类
APP写好了,安装到设备,但是从网络拉取图片显示失败了,怎么破?APP打安装包后想看下包里面到底有些啥?遇到这样的问题,这个的工具可以帮助你解决上面遇到的问题。

Wireshark

老牌网络抓包利器,各种平台都可以玩耍。

软件主页以及下载地址:https://www.wireshark.org/

tcpdump
这是一个命令行工具,可以看作是Wireshark的命令行版。

系统自带,无需额外安装。使用帮助

Charles

网络抓包利器加上代理功能,并支持自签名证书,所以可以用来在手机上抓取https的包。使用非常方便。付费软件,值得购买。

软件主页以及下载地址:https://www.charlesproxy.com/

JD-GUI
Java的class文件反编译神器,可以从二进制class文件查看它的Java源代码。

软件主页以及下载地址:http://jd.benow.ca/

JADX
JD-GUI的增强版,支持查看安卓apk/dex文件中反编译的Java源代码以及查看apk中其他文件的内容。

软件主页以及下载地址:https://github.com/skylot/jadx

版本管理
频繁的修改,反悔,记录需要管理,所以版本管理是必须的。

SourceTree

Atlassians出品的图形化版本管理工具,支持Git和Mercurial。

软件主页以及下载地:https://www.sourcetreeapp.com/

文件共享
从文件服务器(FTP, Samba etc.)下载资料或者上传文件到服务器上。

FileZilla

老牌Sourceforge开源文件传输软件。

软件主页以及下载地址:https://sourceforge.net/projects/filezilla/

证书管理
证书一般用于https加密,移动APP软件的安装文件签名。

Portecle

图像化管理证书的工具。

软件主页以及下载地址:https://sourceforge.net/projects/portecle/

截屏
截屏是强需求,没错。MAC下有截屏快捷键,只能截屏。一般用户截屏完毕后,不是马上发出去,而是做后期处理。

snip

截屏,编辑。

软件主页以及下载地址:http://snip.qq.com/

数据库
调试APP的时候,如果APP产生了数据,并且把数据保存在数据库(sqlite)中。如果想在开发主机上查看,可以用如下的工具。

Datum

查看sqlite数据库的内容。

软件主页以及下载地址:http://www.datumapps.com/

网络请求
有时候需要自己构造一个http网络请求(GET/POST),并查看输入输出的详细内容。简单的GET用浏览器可以代劳,复杂一点的需要浏览器安装插件支持。用如下的工具可以到达更好的效果。

wget

命令行工具。除了查看发送网络请求,查看结果外。另外一个用途是下载文件,特别是大文件,用浏览器下载经常会断线,而且断点续传做的不是太好。wget命令下载文件,支持断点续传,这个用起来不错。

curl

功能基本同wget,系统自带工具,无需安装。

rest-client

支持restful风格的网络请求构造,请求和结果相应。调试restful接口的好帮手。

软件主页以及下载地址:https://github.com/wiztools/rest-client

虚拟机&模拟器
我的电脑是MAC,可是招商银行的专业版没有MAC的客户端,肿么破?我想在MAC上看到安卓APP运行的情况,怎么办?安装一个虚拟机吧!

VirtualBox

老牌虚拟机软件,支持市面上几乎所有流行的操作系统。

软件主页以及下载地址:https://www.virtualbox.org/

genymotion
安卓模拟器,运行安卓APP如同在手机上一样的速度。

软件主页以及下载地址:https://www.genymotion.com/

MAC专用
有些工具是MAC系统专用的,比如用来管理苹果设备(iPad, iPhone, iMac, Mac etc.)配置文件的工具。

Apple Configurator

上App Store自行搜索下载安装。

使用帮助

服务端工具套件

有时候需要本地调试一些服务端提供的服务,或者是网站后台。这个时候一个开发/调试/模拟环境的选择变的重要了。还是那句不忘初衷的话,好的工具让你事半功倍!

Bitnami服务端套件

本地调试web服务器,nginx, mysql, php-fpm, etc.

软件主页以及下载地址:https://bitnami.com

Kitematic
Docker图形化管理工具。 软件主页以及下载地址:https://kitematic.com/

*利器
我要上谷歌搜索*新的Android开发文档和API,可是目前在国内用不了谷歌,怎么办?*吧!

ShadowsocksX

看标题,不多说,默默的下载,安装然后运行,配置,打开浏览器,访问谷歌,搜索Android就可以啦!

软件主页以及下载地址:https://sourceforge.net/projects/shadowsocksgui/

Lantern
如果上面那个不行,那么试试这个吧,不多说了。

软件主页以及下载地址:https://github.com/getlantern/lantern

iOS appstore审核被拒的各种原因以及相关条款

1. Terms and conditions(法律与条款)

1.1
As a developer of applications for the App Store you are bound by the terms of the Program License Agreement (PLA), Human Interface Guidelines (HIG), and any other licenses or contracts between you and Apple. The following rules and examples are intended to assist you in gaining acceptance for your App in the App Store, not to amend or remove provisions from any other agreement.(作为App Store的应用开发者,你必须接受如下条款:Program License Agreement (PLA),Human Interface Guidelines (HIG),以及任何你与apple签订的许可和合同。以下规则和示例是为了协助你的应用更快通过审核上架,而不是修正或取代之前的条款。)

 

2. Functionality(功能)

2.1
Apps that crash will be rejected(存在Crash(崩溃,死机)的应用会被拒。)

2.2
Apps that exhibit bugs will be rejected(存在明显bug的应用会被拒。)

2.3
Apps that do not perform as advertised by the developer will be rejected(不符合开发者描述的应用会被拒。)

2.4
Apps that include undocumented or hidden features inconsistent with the description of the App will be rejected(有未说明或隐藏特性或有悖描述的应用会被拒。)

2.5
Apps that use non-public APIs will be rejected(使用非公开API的应用会被拒。)

2.6
Apps that read or write data outside its designated container area will be rejected(试图读写非允许范围内的数据的应用会被拒。)

2.7
Apps that download code in any way or form will be rejected(试图以任何方式方法下载代码的应用会被拒。)

2.8
Apps that install or launch other executable code will be rejected(安装或运行其他可执行代码的应用会被拒。)

2.9
Apps that are “beta”, “demo”, “trial”, or “test” versions will be rejected(任何“beta”,“演示(demo)”,“试用(trial)”或“测试(test)”版本的应用会被拒。)

2.10
iPhone Apps must also run on iPad without modification, at iPhone resolution, and at 2X iPhone 3GS resolution(iPhone应用必须可以无条件运行在iPad上,支持普通iPhone分辨率和2倍iPhone 3GS分辨率。)

2.11
Apps that duplicate Apps already in the App Store may be rejected, particularly if there are many of them, such as fart, burp, flashlight, and Kama Sutra Apps.(任何与App Store中上架应用重复的应用会被拒,尤其是已经有了很多的:如放屁,打嗝,手电照明和爱经。)

2.12
Apps that are not very useful, unique, are simply web sites bundled as Apps, or do not provide any lasting entertainment value may be rejected(没有用处的应用,web页面简单组合的应用,或任何哗众取宠,不能提供娱乐价值的应用会被拒。)

2.13
Apps that are primarily marketing materials or advertisements will be rejected(纯粹用于市场推广或广告的应用会被拒。)

2.14
Apps that are intended to provide trick or fake functionality that are not clearly marked as such will be rejected(有意提供隐蔽或虚假功能,却又不能明显标示的应用会被拒。)

2.15
Apps larger than 50MB in size will not download over cellular networks (this is automatically prohibited by the App Store)(大于20MB的应用无法通过蜂窝网络下载安装(App Store自动处理)。)

2.16
Multitasking Apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc.(多任务应用只允许在后台运行如下相应的服务:VoIP,音频播放,地理位置,任务记录,本地提醒等。)

2.17
Apps that browse the web must use the iOS WebKit framework and WebKit Javascript(应用只允许通过iOS WebKit框架和WebKit Javascript访问web页面。)

2.18
Apps that encourage excessive consumption of alcohol or illegal substances, or encourage minors to consume alcohol or smoke cigarettes, will be rejected(鼓励酗酒,使用违法药物,或诱导未成年人饮酒,吸烟的应用会被拒。)

2.19
Apps that provide incorrect diagnostic or other inaccurate device data will be rejected(提供错误的系统信息或设备数据的应用会被拒。)

2.20
Developers “spamming” the App Store with many versions of similar Apps will be removed from the iOS Developer Program(通过许多版本的类似应用对App Store造成干扰的开发者会被取消IDP身份。)

2.21
Apps that are simply a song or movie should be submitted to the iTunes store. Apps that are simply a book should be submitted to the iBookstore.(歌曲和电影应该提交到iTunes store。书籍应该提交到iBookstore。)

2.22
Apps that arbitrarily restrict which users may use the App, such as by location or carrier, may be rejected(随意通过位置或运营商来限制用户使用的应用会被拒。)

2.23
Apps must follow the iOS Data Storage Guidelines or they will be rejected(加入iCloud支持后,应用必须遵守iOS数据存储指南( iOS Data Storage Guidelines)否则将被拒。)

2.24
Apps that are offered in Newsstand must comply with schedules 1, 2 and 3 of the Developer Program License Agreement or they will be rejected(在Newsstand里提交的应用必须遵守Developer Program License Agreement的第1,2和3条,否则将被拒。)

 

2.25
Apps that display Apps other than your own for purchase or promotion in a manner similar to or confusing with the App Store will be rejected(与App Store类似的推荐或为其他应用做广告的应用将无法通过App Store审核。)

 

3. Metadata (name, descriptions, ratings, rankings, etc)(描述数据(名称,描述,评级,分类等))

3.1
Apps or metadata that mentions the name of any other mobile platform will be rejected(应用或者元数据中提到其他任意移动平台会被拒。)

3.2
Apps with placeholder text will be rejected(描述数据有未填写项,存留占位符文本会被拒。)

3.3
Apps with descriptions not relevant to the application content and functionality will be rejected(描述中提到与应用内容和功能无关信息会被拒。)

3.4
App names in iTunes Connect and as displayed on a device should be similar, so as not to cause confusion(应用在iTunes Connect与设备上显示的名称应该类似,否则会造成混淆。)

3.5
Small and large App icons should be similar, so as to not to cause confusion(不同尺寸的icon要一致,否则会造成混淆。)

3.6
Apps with App icons and screenshots that do not adhere to the 4+ age rating will be rejected(图标与截屏不符合4+年龄评级的应用会被拒。)

3.7
Apps with Category and Genre selections that are not appropriate for the App content will be rejected(应用的内容与所选分类和风格不符会被拒。)

3.8
Developers are responsible for assigning appropriate ratings to their Apps. Inappropriate ratings may be changed/deleted by Apple(开发者有责任把应用放到恰当的分级(Rating)。不恰当的评级可能会被Apple修改,甚至删除。)

3.9
Developers are responsible for assigning appropriate keywords for their Apps. Inappropriate keywords may be changed/deleted by Apple(开发者有责任给应用撰写恰当的关键词。不恰当的关键词可能会被Apple修改,甚至删除。)

3.10
Developers who attempt to manipulate or cheat the user reviews or chart ranking in the App Store with fake or paid reviews, or any other inappropriate methods will be removed from the iOS Developer Program(通过伪造,付费评价或其他非正规手段,获取App Store中较好的评价与星级的开发者会被取消IDP身份。)

3.11
Apps which recommend that users restart their iOS device prior to installation or launch may be rejected(任何提示需要用户重启iOS设备来安装或运行的应用会被拒。)

3.12
Apps should have all included URLs fully functional when you submit it for review, such as support and privacy policy URLs(应用在提交审核过程中,所有涉及到的URL都要处于正常运行状态,例如保密协议,相关支持页面等。)

4. Location(位置)

4.1
Apps that do not notify and obtain user consent before collecting, transmitting, or using location data will be rejected(未提示用户且获得用户允许之前收集,传输或使用位置数据的应用会被拒。)

4.2
Apps that use location-based APIs for automatic or autonomous control of vehicles, aircraft, or other devices will be rejected(使用location-based API来自动控制车辆,飞行器或其他设备的应用会被拒。)

4.3
Apps that use location-based APIs for dispatch, fleet management, or emergency services will be rejected(使用location-based API进行调度,队伍管理或应急服务的而应用会被拒。)

4.4
Location data can only be used when directly relevant to the features and services provided by the App to the user or to support approved advertising uses(位置数据只能用于应用提供的直接相关功能或服务,或者有授权的广告。)

5. Push notifications(提醒推送)

5.1
Apps that provide Push Notifications without using the Apple Push Notification (APN) API will be rejected(不使用Apple Push Notification(APN) API提供消息推送的应用会被拒。)

5.2
Apps that use the APN service without obtaining a Push Application ID from Apple will be rejected(使用APN服务却没从Apple获取一个Push Application ID的应用会被拒。)

5.3
Apps that send Push Notifications without first obtaining user consent will be rejected(在首次推送消息之前未取得的用户允许的应用会被拒。)

5.4
Apps that send sensitive personal or confidential information using Push Notifications will be rejected(使用提醒推送服务推送敏感的个人或机密信息的应用会被拒。)

5.5
Apps that use Push Notifications to send unsolicited messages, or for the purpose of phishing or spamming will be rejected(使用提醒推送发送主动消息,欺骗或干扰信息的应用会被拒。)

5.6
Apps cannot use Push Notifications to send advertising, promotions, or direct marketing of any kind(应用不可以使用提醒推送发送广告,活动或任何形式的直接推广信息。)

5.7
Apps cannot charge users for use of Push Notifications(应用不可以提供收费的提醒推送服务。)

5.8
Apps that excessively use the network capacity or bandwidth of the APN service or unduly burden a device with Push Notifications will be rejected(使用APN服务过度占用网络带宽或容量或通过提醒推送大量占用系统资源的应用会被拒。)

5.9
Apps that transmit viruses, files, computer code, or programs that may harm or disrupt the normal opera tion of the APN service will be rejected(传输病毒,文件,代码或程序,导致破坏或扰乱正常的APN服务操作的应用会被拒。)

 

6. Game Center(游戏中心)

6.1
Apps that display any Player ID to end users or any third party will be rejected(向终端用户或第三方展示Player ID的应用会被拒。)

6.2
Apps that use Player IDs for any use other than as approved by the Game Center terms will be rejected(Player ID被用于Game Center条款款意外的用途的应用会被拒。)

6.3
Developers that attempt to reverse lookup, trace, relate, associate, mine, harvest, or otherwise exploit Player IDs, alias, or other information obtained through the Game Center will be removed from the iOS Developer Program(试图通过Game Center反查,跟踪,描述,关联,发掘,收割,或利用Player ID,别名或其他信息的开发者会被取消IDP身份。)

6.4
Game Center information, such as Leaderboard scores, may only be used in Apps approved for use with the Game Center(Game Center信息,例如Leaderboard得分,只能通过Game Center用于应用中。)

6.5
Apps that use Game Center service to send unsolicited messages, or for the purpose of phishing or spamming will be rejected(使用Game Center发送主动消息,欺骗或干扰信息的应用会被拒。)

6.6
Apps that excessively use the network capacity or bandwidth of the Game Center will be rejected(使用Game Center过度占用网络带宽或容量的应用会被拒。)

6.7
Apps that transmit viruses, files, computer code, or programs that may harm or disrupt the normal operation of the Game Center service will be rejected(传输病毒,文件,代码或程序,导致破坏或扰乱正常的Game Center操作的应用会被拒。)

7. Advertising(广告)

7.1
Apps that artificially increase the number of impressions or click-throughs of ads will be rejected(人工刷广告浏览或点击率的应用会被拒。)

7.2
Apps that contain empty iAd banners will be rejected(带有空iAd banner广告的应用会被拒。)

7.3
Apps that are designed predominantly for the display of ads will be rejected(设计主要用来展示广告的应用会被拒。)

8. Trademarks and trade dress(商标权与商标外观)

8.1
Apps must comply with all terms and conditions explained in the Guidelines for Using Apple Trademarks and Copyrights and the Apple Trademark List(应用必须遵守Guidelines for Using Apple Trademarks and Copyrights 和Apple Trademark List中描述的所有条款和条件。)

8.2
Apps that suggest or infer that Apple is a source or supplier of the App, or that Apple endorses any particular representation regarding quality or functionality will be rejected(任何误导或暗示Apple为该应用来源或提供商,或Apple以任何形式认可其质量或功能的应用会被拒。)

8.3
Apps which appear confusingly similar to an existing Apple product or advertising theme will be rejected(外观与现有Apple产品或广告主题类似或混淆的应用会被拒)

8.4
Apps that misspell Apple product names in their App name (i.e., GPS for Iphone, iTunz) will be rejected(应用名称中出现错误的Apple产品拼写(如,GPS for IPhone, iTunz)的应用会被拒。)

8.5
Apps may not use protected third party material such as trademarks, copyrights, patents or violate 3rd party terms of use. Authorization to use such material must be provided upon request.(使用受保护的第三方资源(商标,版权,商业机密,以及其他私有内容),如果要求请提供一份文本形式的使用授权。)

9. Media content(媒体内容)

9.1
Apps that do not use the MediaPlayer framework to access media in the Music Library will be rejected(使用MediaPlayer框架以外的方法访问Music Library中媒体数据的应用会被拒。)

9.2
App user interfaces that mimic any iPod interface will be rejected(用户界面模仿任何iPod界面的应用会被拒。)

9.3
Audio streaming content over a cellular network may not use more than 5MB over 5 minutes(通过蜂窝网络传输的流媒体音频内容不得超过5MB或多余5分钟。)

9.4
Video streaming content over a cellular network longer than 10 minutes must use HTTP Live Streaming and include a baseline 64 kbps audio-only HTTP Live stream(通过蜂窝网络传输超过10分钟流媒体视频内容,必须使用HTTP Live Streaming,并包含一条基线64kbps的音频HTTP Live流。)

10. User interface(用户界面)

10.1
Apps must comply with all terms and conditions explained in the Apple iOS Human Interface Guidelines(应用必须遵守Apple iOS Human Interface Guidelines中的所有条款和条件。)

10.2
Apps that look similar to Apps bundled on the iPhone, including the App Store, iTunes Store, and iBookstore, will be rejected( 外观与iPhone自带应用(如:App Store,iTunes Store和iBookstore)相似的应用会被拒。)

10.3
Apps that do not use system provided items, such as buttons and icons, correctly and as described in the Apple iOS Human Interface Guidelines may be rejected(不按照Apple iOS Human Interface Guidelines中的描述正确使用系统控件比如按钮,图标等的应用会被拒。)

 

10.4
Apps that create alternate desktop/home screen environments or simulate multi-App widget experiences will be rejected(试图创建多桌面/主屏环境或模拟多Widget应用工具的应用会被拒。)

10.5
Apps that alter the functions of standard switches, such as the Volume Up/Down and Ring/Silent switches, will be rejected( 修改标准开关标准功能例如:音量增加/减少,响铃/震动的应用会被拒。)

10.6
Apple and our customers place a high value on simple, refined, creative, well thought through interfaces. They take more work but are worth it. Apple sets a high bar. If your user interface is complex or less than very good, it may be rejected(Apple和我们的用户都界面报以很高期望,希望他设计的超级简洁,精致,充满创造力,深思熟虑。做到这些确实会消耗很多精力,但是值得。Apple在这方面要求非常高。如果你的用户界面过于复杂,甚至仅仅是不够好,都可能被拒。)

11. Purchasing and currencies(购买与流通货币)

11.1
Apps that unlock or enable additional features or functionality with mechanisms other than the App Store will be rejected(通过App Store以外的渠道解锁或开启附加属性或功能的应用会被拒。)

11.2
Apps utilizing a system other than the In-App Purchase API (IAP) to purchase content, functionality, or services in an App will be rejected( 使用In App Purchase API (IAP)以外的系统提供购买内容,功能或服务的应用会被拒。)

11.3
Apps using IAP to purchase physical goods or goods and services used outside of the application will be rejected(使用IAP为与应用无关的实体商品或商品服务收费的应用会被拒。)

11.4
Apps that use IAP to purchase credits or other currencies must consume those credits within the application(应用使用IAP购买积分(Credit)或其他货币,必须在应用中消费。)

11.5
Apps that use IAP to purchase credits or other currencies that expire will be rejected(使用IAP购买的积分(Credit)或货币会过期的应用会被拒)

11.6
Content subscriptions using IAP must last a minimum of 7 days and be available to the user from all of their iOS devices( 使用IAP收费订阅的内容至少要在7天内有效,而且允许在所有iOS设备间共享。)

11.7
Apps that use IAP to purchase items must assign the correct Purchasability type(用到IAP收费项目的应用必须分派到正确的收费类目中。)

11.8
Apps that use IAP to purchase access to built-in capabilities provided by iOS, such as the camera or the gyroscope, will be rejected( 使用IAP向用户收费以获取iOS内建功能(如摄像头,陀螺仪)的应用会被拒。)

11.9
Apps containing “rental” content or services that expire after a limited time will be rejected( 包含“出租”内容或服务的应用,在一段时间实效的会被拒。)

11.10
Insurance applications must be free, in legal-compliance in the regions distributed, and cannot use IAP(保险类应用必须免费,遵守发布地区的法律,并且不允许使用IAP。)

11.11
In general, the more expensive your App, the more thoroughly we will review it(一般来说,越贵的应用审核就越仔细彻底。)

11.12
Apps offering subscriptions must do so using IAP, Apple will share the same 70/30 revenue split with developers for these purchases, as set forth in the Developer Program License Agreement.(提供收费订阅的应用必须使用IAP,Apple将会按照Developer Program License Agreement中约定的70/30的比例与开发者分账。)

11.13
Apps that link to external mechanisms for purchases or subscriptions to be used in the App, such as a “buy” button that goes to a web site to purchase a digital book, will be rejected(应用中如果提供了IAP以外的收费或订阅机制,如:“buy”按钮,跳转到一个购买电子书的web页面,会被拒。)

11.14
Apps can read or play approved content (specifically magazines, newspapers, books, audio, music, and video) that is subscribed to or purchased outside of the App, as long as there is no button or external link in the App to purchase the approved content. Apple will not receive any portion of the revenues for approved content that is subscribed to or purchased outside of the App( 应用可以阅读或播放任何在应用以外取得授权的内容(包括指定的杂志,报纸,书籍,音频,音乐和视频),只要在应用中不允许出现获取授权的收费链接或按钮。Apple不会对在应用外订阅或购买授权项目收取任何费用。)

11.15
Apps may only use auto renewing subscriptions for periodicals (newspapers, magazines), business Apps (enterprise, productivity, professional creative, cloud storage) and media Apps (video, audio, voice), or the App will be rejected.(应用只能自动更新订阅的期刊(报纸、杂志),自动更新商业应用(企业、生产力、专业创意、云存储)和媒体应用(视频、音频,声音)将被拒*。)

12. Scraping and aggregation(抓去与整合)

12.1
Applications that scrape any information from Apple sites (for example from apple.com, iTunes Store, App Store, iTunes Connect, Apple Developer Programs, etc) or create rankings using content from Apple sites and services will be rejected(从Apple的页面(如:apple.com, iTunes Store, App Store, iTunes Connect, Apple Developer Programs, 等)抓取内容,或利用Apple页面和服务中的内容进行排名的应用会被拒。)

12.2
Applications may use approved Apple RSS feeds such as the iTunes Store RSS feed( 应用可以使用授权的Apple RSS,例如iTunes Store RSS。)

 

12.3
Apps that are simply web clippings, content aggregators, or a collection of links, may be rejected(简单的web页面裁剪,内容整合或链接收集应用会被拒。)

13. Damage to device(损害设备)

13.1
Apps that encourage users to use an Apple Device in a way that may cause damage to the device will be rejected(任何怂恿用户做出可能损坏Apple设备的行为的应用会被拒。)

13.2
Apps that rapidly drain the device’s battery or generate excessive heat will be rejected(快速耗光设备电量或产生大量热量的应用会被拒。)

14. Personal attacks(人身攻击)

14.1
Any App that is defamatory, offensive, mean-spirited, or likely to place the targeted individual or group in harms way will be rejected( 任何涉嫌诽谤,侮辱,狭隘内容或打击个人或团体的应用会被拒。)

14.2
Professional political satirists and humorists are exempt from the ban on offensive or mean-spirited commentary(职业政治讽刺家和幽默作家不受该诽谤和狭隘条款约束。)

15. Violence(暴力)

15.1
Apps portraying realistic images of people or animals being killed or maimed, shot, stabbed, tortured or injured will be rejected(展示人或动物被杀戮,致残,枪击,针刺或其他伤害的真实图片的应用会被拒)

15.2
Apps that depict violence or abuse of children will be rejected(描述暴力或虐待儿童的应用会被拒。)

15.3
“Enemies” within the context of a game cannot solely target a specific race, culture, a real government or corporation, or any other real entity(游戏中的“敌人”不能单独的设定为某特定比赛,文化,真实的政府或组织,或者任何现实事物。)

15.4
Apps involving realistic depictions of weapons in such a way as to encourage illegal or reckless use of such weapons will be rejected(含有以鼓励非法或鲁莽使用的方式描述真实武器的应用会被拒。)

15.5
Apps that include games of Russian roulette will be rejected( 带有俄罗斯轮盘游戏的应用会被拒。)

16. Objectionable content(负面内容)

16.1
Apps that present excessively objectionable or crude content will be rejected(介绍过度三俗和粗鲁内容的应用会被拒。)

16.2
Apps that are primarily designed to upset or disgust users will be rejected(设计来惹怒或恶心用户的应用会被拒。)

17. Privacy(隐私)

17.1
Apps cannot transmit data about a user without obtaining the user’s prior permission and providing the user with access to information about how and where the data will be used(在未获得用户事先允许,或未告知用户信息将被如何,在哪里使用的情况下,应用不可以传输用户数据。)

17.2
Apps that require users to share personal information, such as email address and date of birth, in order to function will be rejected(要求用户提供个人信息,如邮箱地址,生日等,才能使用其功能的应用会被拒。)

17.3
Apps that target minors for data collection will be rejected(专门收集未成年人数据的应用会被拒。)

18. Pornography(色情)

18.1
Apps containing pornographic material, defined by Webster’s Dictionary as “explicit descriptions or displays of sexual organs or activities intended to stimulate erotic rather than aesthetic or emotional feelings”, will be rejected(含有韦氏词典中定义的色情素材(explicit descriptions or displays of sexual organs or activities intended to stimulate erotic rather than aesthetic or emotional feelings)的应用会被拒。)

18.2
Apps that contain user generated content that is frequently pornographic (ex “Chat Roulette” Apps) will be rejected(经常有用户提供色情内容(例如:Chat Roulette http://en.wikipedia.org/wiki/Chatroulette )的应用会被拒。)

19. Religion, culture, and ethnicity(信仰,文化和种族)

19.1
Apps containing references or commentary about a religious, cultural or ethnic group that are defamatory, offensive, mean-spirited or likely to expose the targeted group to harm or violence will be rejected(带有对一种信仰,文化或种族进行诽谤,侮辱,狭隘,或以他们为目标的暴力或伤害内容的应用会被拒。)

19.2
Apps may contain or quote religious text provided the quotes or translations are accurate and not misleading. Commentary should be educational or informative rather than inflammatory( 应用若带有或应用对一种信仰的文字描述,那么这个引用或翻译必须是精确,无歧义的。注释内容可以具有教育性,信息性,但不可以为煽动性。)

20. Contests, sweepstakes, lotteries, and raffles(竞赛,赌博,彩票和抽*)

20.1
Sweepstakes and contests must be sponsored by the developer/company of the App(赌博和竞赛必须是由应用开发者或所有公司发起资助的。)

20.2
Official rules for sweepstakes and contests, must be presented in the App and make it clear that Apple is not a sponsor or involved in the activity in any manner( 应用中必须展示赌博和竞赛的官方条款,并声明Apple不是资助者,并且在任何情况下与此事无关。)

20.3
It must be permissible by law for the developer to run a lottery App, and a lottery App must have all of the following characteristics: consideration, chance, and a prize(开发者必须经过法律允许才能上线一款抽*应用,而且抽*应用必须具备以下要素:报酬,机会,和*金。)

 

20.4
Apps that allow a user to directly purchase a lottery or raffle ticket in the App will be rejected(直接允许用户在应用中购买彩票或抽*的应用会被拒。)

21. Charities and contributions(慈善与捐助)

21.1
Apps that include the ability to make donations to recognized charitable organizations must be free(含有向已认证的慈善机构捐助功能的应用必须是免费的。)

21.2
The collection of donations must be done via a web site in Safari or an SMS(慈善募捐必须通过短信息或通过Safari访问web页面完成。)

22. Legal requirements(法律要求)

22.1
Apps must comply with all legal requirements in any location where they are made available to users. It is the developer’s obligation to understand and conform to all local laws(应用必须遵守所有发布地区当地法律。开发者有义务了解和遵守各地的法律。)

22.2
Apps that contain false, fraudulent or misleading representations or use names or icons similar to other Apps will be rejected( 任何带有虚假,欺诈和带有歧义的内容的应用会被拒。)

22.3
Apps that solicit, promote, or encourage criminal or clearly reckless behavior will be rejected( 任何召集,推销和股东犯罪和鲁莽行为的应用会被拒。)

22.4
Apps that enable illegal file sharing will be rejected(非法文件共享应用会被拒。)

22.5
Apps that are designed for use as illegal gambling aids, including card counters, will be rejected(任何设计用来非法赌博工具,包括算牌的应用会被拒。)

22.6
Apps that enable anonymous or prank phone calls or SMS/MMS messaging will be rejected( 提供知识拨打电话或知识发送短消息/彩信功能的应用会被拒。)

22.7
Developers who create Apps that surreptitiously attempt to discover user passwords or other private user data will be removed from the iOS Developer Program(任何开发暗中获取用户密码和私有数据的开发者会被取消IDP身份。)

22.8
Apps which contain DUI checkpoints that are not published by law enforcement agencies, or encourage and enable drunk driving, will be rejected(任何非法律执行部门发布的带有DUI检查点信息,或鼓励且协助酒后驾车的应用会被拒。)

idea自动部署至远程服务器

一、搭建服务器的tomcat环境
二、本地IDEA关联远程服务器
打开IDEA,按如下图配置:

%title插图%num

输入web server的名称

%title插图%num

这里是linux服务器,所以使用的是SFTP(SSH File Transfer Protocol)模式

%title插图%num

%title插图%num

上传本地工程包:这样,我们在本地修改某个java文件,直接提交该class即可,无需打war上传等繁琐的过程。

%title插图%num

python实现滑动验证

做自动化测试的时候,需要自动登录QQ邮箱,在网上找的都是基于selenium的:参考链接,但是代码在本地运行并没有取得满意的效果:滑动不成功!
而且每个滑动解锁的网页不同,编码和格式就不同,复用率太低了!举个例子:

button = browser.find_element_by_id(‘tcaptcha_drag_button’)
x, y = button.location.get(‘x’), button.location.get(‘y’)
print(“location:”,x,y)
%title插图%num
这段代码是获取滑动解锁按钮坐标的,但是返回的是(33,193),而不是根据桌面像素(1920,1080)应该得到的坐标。

查看网页源码发现,这个验证框:width:300px,height:230px,因此坐标是根据这个iframe框架得到的,所以后面的拖动按钮并滑动就会出现问题,(比如拖动一点点就会报错:超出(300,230)边界错误),而且总是拖不到右边,搞了好久都不行(部分原因是我前端基础不牢固)
还有一些其他问题我就不再说了,反正就是心态爆炸:不想用selenium搞滑动了!
我就换了一个方法,按钮的图片定位,然后实现滑动验证:图片定位具体可以参考:ac.find_template识别图片并定位

直接上代码吧:

#coding=utf-8
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import paramiko
import pyautogui
import os
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from Auto_Test.base_action import match

def login_in():
browser = webdriver.Firefox()
browser.maximize_window()
browser.get(“https://mail.qq.com/”)
browser.switch_to.frame(“login_frame”)
browser.find_element_by_class_name(“inputstyle”).clear()
browser.find_element_by_class_name(“inputstyle”).send_keys(“xxxxx”)
browser.find_element_by_class_name(“inputstyle.password”).clear()
browser.find_element_by_class_name(“inputstyle.password”).send_keys(“xxxxx”)
browser.find_element_by_id(“login_button”).click()
browser.find_element_by_class_name(“login_button”).click()
time.sleep(2)
browser.switch_to.frame(“tcaptcha_iframe”)

time.sleep(3)
# 等待图片加载出来
WebDriverWait(browser, 5, 0.5).until(
EC.presence_of_element_located((By.ID, “tcaptcha_drag_button”)))
# button = browser.find_element_by_id(‘tcaptcha_drag_button’)
# x, y = button.location.get(‘x’), button.location.get(‘y’)
# print(“location:”,x,y)
lx,ly=match(“QQmail-slick”)
lz=[x for x in range(120,200,3)]
for i in lz:
pyautogui.moveTo(lx,ly)
pyautogui.dragRel(i,0,duration=2,button=’left’)
time.sleep(1)
pyautogui.moveRel(-i,0)

try:
alert = browser.find_element_by_id(‘guideText’).text
except Exception as e:
print(‘get alert error: %s’ % e)
alert = ”
if alert:
print(u’滑块位移需要调整: %s’ % alert)
sleep(3)
else:
print(‘滑块验证通过’)
browser.switch_to.parent_frame() # 验证成功后跳回*外层页面
break

from Auto_Test.base_action import match中的函数如下:

def match(target, show=True):
target_path = target.split(“-“)[0]
target_name = target.split(“-“)[1]
# 防止截全屏的页面没反应过来
time.sleep(1)
ttime_s = time.time()

global root_dir
appname = root_dir + ‘/APP_Action_Icons/’+target_path+”/”+target_name+’.png’
appname_2 = root_dir + ‘/APP_Action_Icons/’+target_path+”/”+target_name+’_2.png’
appname_3 = root_dir + ‘/APP_Action_Icons/’+target_path+”/”+target_name+’_3.png’
print(appname)
print(“root_dir =”, root_dir)

##根据桌面路径进行截屏
hwnd = win32gui.FindWindow(None, root_dir)
app = QApplication(sys.argv)
screen = QApplication.primaryScreen()
img = screen.grabWindow(hwnd).toImage()

##保存截屏
root_desk = root_dir + ‘/Screen_Shots/Test_Screen_shots/desktop.jpg’
img.save(root_desk)
##等待图片保存
time.sleep(0.5)
# 支持图片名为中英文名,也支持路径中英文
imsrc = cv2.imdecode(np.fromfile(root_desk, dtype=np.uint8), -1)
imobj = cv2.imdecode(np.fromfile(appname, dtype=np.uint8), -1)

##根踞名称匹配截图,只支持图片为英文名
# imsrc = ac.imread(root_desk)
# imobj = ac.imread(appname)

# 匹配图标位置
pos = ac.find_template(imsrc, imobj, 0.5,bgremove=True)
if pos == None and os.path.exists(appname_2):
print(“*张图标没匹配到,现匹配第二张:”, end=””)
print(appname_2)
imobj_2 = cv2.imdecode(np.fromfile(appname_2, dtype=np.uint8), -1)
# imobj_2 = ac.imread(appname_2)
pos = ac.find_template(imsrc, imobj_2, 0.5,bgremove=True)
if pos == None and os.path.exists(appname_3):
print(“第二张图标没匹配到,现匹配第三张:”, end=””)
print(appname_3)
imobj_3 = cv2.imdecode(np.fromfile(appname_3, dtype=np.uint8), -1)
# imobj_3 = ac.imread(appname_3)
pos = ac.find_template(imsrc, imobj_3, 0.5,bgremove=True)

# 如果第三张还未匹配到,用另一种方法重新截图
if pos == None:
print(“2秒后重新截全屏…”)
time.sleep(2)

##保存截屏
root_desk = root_dir + ‘/Screen_Shots/Test_Screen_shots/desktop_2.jpg’
img = ImageGrab.grab()
img.save(root_desk)
##等待图片保存
time.sleep(0.5)
# 支持图片名为中英文名,也支持路径中英文
imsrc = cv2.imdecode(np.fromfile(root_desk, dtype=np.uint8), -1)
imobj = cv2.imdecode(np.fromfile(appname, dtype=np.uint8), -1)

# 匹配图标位置
pos = ac.find_template(imsrc, imobj, 0.5,bgremove=True)
if pos == None and os.path.exists(appname_2):
print(“*张图标没匹配到,现匹配第二张:”, end=””)
print(appname_2)
imobj_2 = cv2.imdecode(np.fromfile(appname_2, dtype=np.uint8), -1)
pos = ac.find_template(imsrc, imobj_2, 0.5,bgremove=True)
if pos == None and os.path.exists(appname_3):
print(“第二张图标没匹配到,现匹配第三张:”, end=””)
print(appname_3)
imobj_3 = cv2.imdecode(np.fromfile(appname_3, dtype=np.uint8), -1)
pos = ac.find_template(imsrc, imobj_3, 0.5,bgremove=True)

if pos == None:
print(“*终没能匹配到:” + target)
else:
ttime_e = time.time()
__time = ttime_e – ttime_s

if show == True:
try:
show_and_save(root_desk, target, pos, __time)
except Exception as e:
print(“保存匹配结果show_and_save这里出错,错误原因为{}”.format(e))
print(pos)
point = pos[‘result’]
pyautogui.moveTo(point)
print(“匹配成功:{}”.format(target))
time.sleep(0.5)
print(pyautogui.position())
pyautogui.click(clicks=2)
return point

亲测有效,如果有问题,可以联系我,看到了就会*时间回复!
互相交流,互相学习,共同进步!

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速