iOS NSInteger/NSUInteger与int/unsigned int、long/unsigned long之间的区别!

mikel阅读(910)

在iOS开发中经常使用NSInteger和NSUInteger,而在其他的类似于C++的语言中,我们经常使用的是intunsigned int。我们知道iOS也可以使用g++编译器,那么它们之间是否有什么联系呢?

从NSUInteger和NSInteger的定义文件中 NSObjCRuntime.h发现有这样的语句:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64

typedeflong NSInteger;

typedefunsigned long NSUInteger;

#else

typedefint NSInteger;

typedefunsigned int NSUInteger;

#endif

这里可以清楚的看出NSInteger和int,NSUInteger和unsigned int之间的区别。mac的OS X系统即为__LP64__,而后面则是指具体的目标硬件设备。所以NSInteger/NSUIteger与对应的intunsigned int不是完全相等的,与对应的longunsigned long也不是完全相等的。而是要看具体的运行环境及其硬件设备架构。

为了更好的了解上面的定义,可以参考下面说的:

You usually want to use NSInteger when you don’t know what kind of processor architecture your code might run on, so you may for some reason want the largest possible int type, which on 32 bit systems is just an int, while on a 64-bit system it’s a long.

当你不知道程序运行哪种处理器架构时,你最好使用NSInteger,因为在有可能int在32位系统中只是int类型,而在64位系统,int可能变是long型。

I’d stick with using NSInteger instead of int/long unless you specifically require them.

除非不得不使用intlong型,坚持使用NSInteger。

从上面的定义可以看出NSInteger/NSUInteger是一种动态定义的类型,在不同的设备,不同的架构,有可能是int类型,有可能是long类型。

With regard to the correct format specifier you should use for each of these types, see the String Programming Guide’s section on Platform Dependencies

为了正确的使用这些类型,可以参考String Programming Guide’s section on Platform Dependencies为了更简单的知道NSInteger和long的大小,我们只需要记住它们的大小总是等于指针的大小,即在32bit系统中是32bit,在64bit系统大小总是64bit。NSInteger and long are always pointer-sized. That means they’re 32-bits on 32-bit systems, and 64 bits on 64-bit systems.)
1.当需要使用int类型的变量的时候,可以像写C的程序一样,用int,也可以用NSInteger,但更推荐使用NSInteger,因为这样就不用考虑设备是32位的还是64位的。

2.NSUInteger是无符号的,即没有负数,NSInteger是有符号的。

3.有人说既然都有了NSInteger等这些基础类型了为什么还要有NSNumber?它们的功能当然是不同的。

 NSInteger是基础类型,但是NSNumber是一个类。如果想要存储一个数值,直接用NSInteger是不行的,比如在一个Array里面这样用:
 NSArray *array = [[NSArray alloc]init];
[array addObject:3];//会编译错误

这样是会引发编译错误的,因为NSArray里面放的需要是一个类,但‘3’不是。这个时候需要用到NSNumber:

 NSArray *array = [[NSArray alloc]init];
[array addObject:[NSNumber numberWithInt:3]];

Cocoa提供了NSNumber类来包装(即以对象形式实现)基本数据类型。
例如以下创建方法:

+ (NSNumber *) numberWithChar: (char) value;
+ (NSNumber *) numberWithInt: (int) value;
+ (NSNumber *) numberWithFloat: (float) value;
+ (NSNumber *) numberWithBool: (BOOL) value;

将基本类型数据封装到NSNumber中后,就可以通过下面的实例方法重新获取它:

– (char) charValue;
– (int) intValue;
– (float) floatValue;
– (BOOL) boolValue;
– (NSString *) stringValue;

苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)

mikel阅读(899)

转自holydancer的CSDN专栏,原文地址:http://blog.csdn.net/holydancer/article/details/9219333

 

概述:

苹果的证书繁锁复杂,制作管理相当麻烦,今天决定重置一个游戏项目中的所有证书,做了这么多次还是感觉很纠结,索性直接记录下来,日后你我他查阅都方便;

首先得描述一下各个证书的定位,作用,这样在制作的时候心中有谱,对整个流程的把握也会准确一些;

1、开发者证书(分为开发和发布两种,类型为ios Development,ios Distribution),这个是最基础的,不论是真机调试,还是上传到appstore都是需要的,是一个基证书,用来证明自己开发者身份的;

2、appID,这是每一个应用的独立标识,在设置项中可以配置该应用的权限,比如是否用到了PassBook,GameCenter,以及更常见的push服务,如果选中了push服务,那么就可以创建生成下面第3条所提到的推送证书,所以,在所有和推送相关的配置中,首先要做的就是先开通支持推送服务的appID;

3、推送证书(分为开发和发布两种,类型分别为APNs Development ios,APNs Distribution ios),该证书在appID配置中创建生成,和开发者证书一样,安装到开发电脑上;

4、Provisioning Profiles,这个东西是很有苹果特色的一个东西,我一般称之为PP文件,该文件将appID,开发者证书,硬件Device绑定到一块儿,在开发者中心配置好后可以添加到Xcode上,也可以直接在Xcode上连接开发者中心生成,真机调试时需要在PP文件中添加真机的udid;是真机调试和必架必备之珍品;

平常我们的制作流程一般都是按以上序列进行,先利用开发者帐号登陆开发者中心,创建开发者证书,appID,在appID中开通推送服务,在开通推送服务的选项下面创建推送证书(服务器端的推送证书见下文),之后在PP文件中绑定所有的证书id,添加调试真机等;

具体操作流程如下:

1、开发者证书的制作,首先登陆到开发者中心,找到证书配置的版块,猛戳进入,点进证书,会显示如下界面,点击右上角的加号

会出现以下界面,该操作重复两次,分别创建开发测试证书和发布证书,开发测试证书用于真机调试,发布证书用于提交到appStore,我们以开发测试证书为例,选择第一个红框中的内容;
然后下一步,会提示创建CSR文件,也就是证书签名请求文件,会有很详细的操作说明,如果英文不太好,可以参考下图;

之后将该CSR文件保存到一处;

备注:CSR文件尽量每个证书都制作一次,将常用名称区分开来,因为该常用名称是证书中的密钥的名字;

之后在开发者中心将该CSR文件提交;

提交上去后就会生成一个cer证书,如图所示,有效期为一年;

利用同样的方法配置一下Distribution发布证书,下载保存,双击安装;在钥题串登陆证书中可以查看,其中专用密钥的名字即为CSR请求文件中的常用名称;

2、以上开发者证书的配置完成了,下面我们来配置appID和推送证书;在左边栏中选择appID,勾选右边的push可选项,为该appID所对应的应用添加推送功能,下面会看到创建证书的按钮,分别为开发证书和发布证书,下面的流程就和上述1中创建证书一样了,都是先建立证书请求文件,然后提交生成就行了,需要注意的是,虽然在左边栏证书栏中也可以直接创建推送证书,但是还是建议在appID中,勾选了push服务后在此处创建,这样会避免因为忘了开通push服务而导致推送不可用的情况发生;

证书创建完成后,下载保存,双击安装即可;

3、最后我们来进行PP文件的制作

该流程进行两次,分别创建开发测试用PP文件和发布PP文件,前者用于真机测试,后者用于提交发布;Ad Hoc格式一般用于企业帐号,此处我们忽略;

选择后提交

会自动检测匹配appID,另外下拉项中还可以选择wildCard格式,该格式为自动生成,使用*通配符,适用于批量的,没有推送,PassCard等服务的应用;我们选择我们刚刚创建的appID,之后下一步选择证书;

继续,这里有一个区别,因为PP文件的开发测试版需要真机调试,所以我们需要绑定真机,这里因为之前我添加过一些设备,所以这里就可以直接全选添加,如果没有的话,需要将真机的udid复制出来在此添加,在发布PP文件中,是没有这一步的;

之后就是输入一个PP文件的名字了,然后生成,下载保存,双击添加到Xcode库中,这样在真机调试或者发布时,就可以分别有不同的PP文件与其对应;

添加到Xcode中的效果如下:

到目前为止,客户端开发和上架所需要的证书文件配置都已经配齐了,天色已晚,明天再配置服务端所用到的推送证书吧,到时候另起一章,将ios诡异的推送流程也捋一捋,本来想写到一篇里的,没想到整了这么长,下班回家开黑去喽!

Android 显示实时时间的方法。

mikel阅读(1299)

一、利用Android自带的模拟时钟和数字时钟。

模拟时钟AnalogClock和数字时钟DigitalClock,用法功能很简单,就是显示一个模拟时钟或是数字时钟

两个时钟都不需要Java代码,只要在layout的xml里插入以下代码即可自动显示时间:

<AnalogClock android:id="@+id/AC"       android:layout_width="wrap_content"        android:layout_height="wrap_content"   />  <DigitalClock      android:id="@+id/DC"      android:layout_width="wrap_content"      android:layout_height="wrap_content"  />

二、利用多线程自己用TextView来显示时间。

先实现Runnable接口,在run方法中获取系统时间,然后用生成Message,在用Handler对象发送消息,在hanler对象中处理消息,即获得系统时间,再显示出来。

实现runnable方法:

public void run()
{
try{
do
{
curTime = dateformat.format(new Date());
sysTime = System.currentTimeMillis();
Thread.sleep(1000);
Message msg = new Message();
msg.what=msg_Key;
mHandler.sendMessage(msg);
}while(tr.interrupted()==false);
}catch(InterruptedException e)
{
e.printStackTrace();
}
}

下面是定义Hanler对象:

                        mHandler = new Handler()
{
public void handleMessage(Message msg)
{
super.handleMessage(msg);
switch(msg.what)
{
case msg_Key:
tv.setText(“当前时间:  “+curTime+ “\n系统时间:”+sysTime+” ms”);
break;
default:
break;
}
}
};
最后,可以用不同的格式来显示时间:

       dateformat = new SimpleDateFormat(“yyyy-mm-dd hh:mm:ss”); //设置显示格式

       curTime = dateformat.format(new Date());   //获得该格式的时间
sysTime = System.currentTimeMillis();    //获得系统时间,ms

java处理日期格式大全Date format SimpleDateFormat - qsfwy - ITeye技术网站

mikel阅读(1149)

Calendar now = Calendar.getInstance();

来源: java处理日期格式大全Date format SimpleDateFormat – qsfwy – ITeye技术网站

Java中日期格式转换

/**
   * 字符串转换为java.util.Date<br>
   * 支持格式为 yyyy.MM.dd G 'at' hh:mm:ss z 如 '2002-1-1 AD at 22:10:59 PSD'<br>
   * yy/MM/dd HH:mm:ss 如 '2002/1/1 17:55:00'<br>
   * yy/MM/dd HH:mm:ss pm 如 '2002/1/1 17:55:00 pm'<br>
   * yy-MM-dd HH:mm:ss 如 '2002-1-1 17:55:00' <br>
   * yy-MM-dd HH:mm:ss am 如 '2002-1-1 17:55:00 am' <br>
   * @param time String 字符串<br>
   * @return Date 日期<br>
   */
public static Date stringToDate(String time){
    SimpleDateFormat formatter;
    int tempPos=time.indexOf("AD") ;
    time=time.trim() ;
    formatter = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss z");
    if(tempPos>-1){
      time=time.substring(0,tempPos)+
           "公元"+time.substring(tempPos+"AD".length());//china
      formatter = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss z");
    }
    tempPos=time.indexOf("-");
    if(tempPos>-1&&(time.indexOf(" ")<0)){
      formatter = new SimpleDateFormat ("yyyyMMddHHmmssZ");
    }
    else if((time.indexOf("/")>-1) &&(time.indexOf(" ")>-1)){
      formatter = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss");
    }
    else if((time.indexOf("-")>-1) &&(time.indexOf(" ")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
    }
    else if((time.indexOf("/")>-1) &&(time.indexOf("am")>-1) ||(time.indexOf("pm")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    }
    else if((time.indexOf("-")>-1) &&(time.indexOf("am")>-1) ||(time.indexOf("pm")>-1)){
      formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    }
    ParsePosition pos = new ParsePosition(0);
    java.util.Date ctime = formatter.parse(time, pos);

    return ctime;
}

/**
   * 将java.util.Date 格式转换为字符串格式'yyyy-MM-dd HH:mm:ss'(24小时制)<br>
   * 如Sat May 11 17:24:21 CST 2002 to '2002-05-11 17:24:21'<br>
   * @param time Date 日期<br>
   * @return String   字符串<br>
   */
  

public static String dateToString(Date time){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
    String ctime = formatter.format(time);

    return ctime;
}

/**
   * 将java.util.Date 格式转换为字符串格式'yyyy-MM-dd HH:mm:ss a'(12小时制)<br>
   * 如Sat May 11 17:23:22 CST 2002 to '2002-05-11 05:23:22 下午'<br>
   * @param time Date 日期<br>
   * @param x int 任意整数如:1<br>
   * @return String 字符串<br>
   */
public static String dateToString(Date time,int x){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy-MM-dd KK:mm:ss a");
    String ctime = formatter.format(time);

    return ctime;
}

/**
   *取系统当前时间:返回只值为如下形式
   *2002-10-30 20:24:39
   * @return String
   */
public static String Now(){
    return dateToString(new Date());
}

/**
   *取系统当前时间:返回只值为如下形式
   *2002-10-30 08:28:56 下午
   *@param hour 为任意整数
   *@return String
   */
public static String Now(int hour){
    return dateToString(new Date(),hour);
}

/**
   *取系统当前时间:返回值为如下形式
   *2002-10-30
   *@return String
   */
public static String getYYYY_MM_DD(){
    return dateToString(new Date()).substring(0,10);

}

/**
   *取系统给定时间:返回值为如下形式
   *2002-10-30
   *@return String
   */
   public static String getYYYY_MM_DD(String date){
    return date.substring(0,10);

}

public static String getHour(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("H");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getDay(){
      SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("d");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getMonth(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("M");
    String ctime = formatter.format(new Date());
    return ctime;
    }

public static String getYear(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("yyyy");
    String ctime = formatter.format(new Date());
    return ctime;
    }
      
public static String getWeek(){
    SimpleDateFormat formatter;
    formatter = new SimpleDateFormat ("E");
    String ctime = formatter.format(new Date());
    return ctime;
    }

在jsp页面中的日期格式和sqlserver中的日期格式不一样,怎样统一?

在页面上显示输出时,用下面的函数处理一下

public class DateUtil(){
    public static String fmtShortEnu(Date myDate) {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
    String strDate = formatter.format(myDate);
    return strDate;
}
}

new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
new java.text.SimpleDateFormat("yyyy-MM-dd")
建议还是把sqlserver的字段类型改成varchar的吧,用字符串处理可以完全按照自己的意愿处理,没有特殊的需求,不要使用date型

字串日期格式转换 
用的API是SimpleDateFormat,它是属於java.text.SimpleDateFormat,所以请记得import进来!

用法: 
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
这一行最重要,它确立了转换的格式,yyyy是完整的西元年,MM是月份,dd是日期, 至於HH:mm:ss就不需要我再解释了吧! 
ps:为什麽有的格式大写,有的格式小写,那是怕避免混淆,例如MM是月份,mm是分;HH是24小时制,而hh是12小时制

1.字串转日期: 
 2002-10-8 15:30:22要把它转成日期,可以用 
 Date date=sdf.parse("2002-10-8 15:30:22"); 
2.日期转字串 
 假如把今天的日期转成字串可用 
 String datestr=sdf.format(new Date()); 
 这个字串的内容便类似2002-10-08 14:55:38

透过这个API我们便可以随心所欲的将日期转成我们想要的字串格式,例如希望将日期输出成2002年10月08日, 
我们可以这麽写: 
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"); 
String datestr=sdf.format(new Date()); 
datestr便会依照我们设定的格式输出

//对日期格式的转换成("yyyy-MM-dd")格式的方法
public java.sql.Date Convert(String str)
{
    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    try
    {
      java.util.Date d = sdf.parse(str);
      java.sql.Date d1 = new java.sql.Date(d.getTime());
      return d1;
    }
    catch(Exception ex)
    {
      ex.printStackTrace();
      return null;
    }
}
应用如下:
ctmt.setDate(7,this.Convert(info.getManBirth())); // @DATETIME

常用日期问题集锦

1、获取服务器端当前日期:
<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
%>

2、获取当前年、月、日:
<%@ page import="java.util.Date"%>

<%
Date myDate = new Date();
int thisYear = myDate.getYear() + 1900;//thisYear = 2003
int thisMonth = myDate.getMonth() + 1;//thisMonth = 5
int thisDate = myDate.getDate();//thisDate = 30
%>

3、按本地时区输出当前日期
<%@ page import="java.util.Date"%>
<%
Date myDate = new Date();
out.println(myDate.toLocaleString());
%>
输出结果为:
2003-5-30

4、获取数据库中字段名为”publish_time“、类型为Datetime的值
<%@ page import="java.util.Date"%>
<%
...连接数据库...
ResultSet rs = ...
Date sDate = rs.getDate("publish_time");
%>


5、按照指定格式打印日期

<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
Date dNow = new Date();

SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is " + formatter.format(dNow));
%>

输出的结果为:
It is 星期五 2003.05.30 at 11:30:46 上午 CST 
(更为详尽的格式符号请参看SimpleDateFormat类)

6、将字符串转换为日期
<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "1222-11-11";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date t = null;
try{
t = formatter.parse(input);
out.println(t);
}catch(ParseException e){
out.println("unparseable using " + formatter);
}
%>
输出结果为:
Fri Nov 11 00:00:00 CST 1222

7、计算日期之间的间隔
<%@ page import="java.util.Date"%>
<%@ page import="java.text.DateFormat"%>
<%
String input = "2003-05-01";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = null;
try{
d1 = formatter.parse(input);
}catch(ParseException e){
out.println("unparseable using " + formatter);
}

Date d2 = new Date();

long diff = d2.getTime() - d1.getTime();
out.println("Difference is " + (diff/(1000*60*60*24)) + " days.");
%>
输出结果为:
Difference is 29 days.

8、日期的加减运算
方法:用Calendar类的add()方法
<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
Calendar now = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
out.println("It is now " + formatter.format(now.getTime()));
now.add(Calendar.DAY_OF_YEAR,-(365*2));
out.println("<br>");
out.println("Two years ago was " + formatter.format(now.getTime()));
%>
输出结果为:
It is now 星期五 2003.05.30 at 01:45:32 下午 CST 
Two years ago was 星期三 2001.05.30 at 01:45:32 下午 CST

9、比较日期
方法:用equals()、before()、after()方法
<%@ page import="java.util.*"%>
<%@ page import="java.text.*"%>
<%
DateFormat df = new SimpleDateFormat("yyy-MM-dd");
Date d1 = df.parse("2000-01-01");
Date d2 = df.parse("1999-12-31");

String relation = null;
if(d1.equals(d2))
relation = "the same date as";
else if(d1.before(d2))
relation = "before";
else
relation = "after";
out.println(d1 +" is " + relation + ' ' + d2);
%>
输出结果为:
Sat Jan 01 00:00:00 CST 2000 is after Fri Dec 31 00:00:00 CST 1999

10、记录一件事所花费的时间
方法:调用两次System.getTimeMillis()方法,求差值
<%@ page import="java.text.*"%>
<%
long t0,t1;
t0 = System.currentTimeMillis();
out.println("Cyc starts at " + t0);
int k = 0;
for(int i =0;i<100000;i++){
k += i;
}
t1 = System.currentTimeMillis();
out.println("<br>");
out.println("Cyc ends at " + t1);
out.println("<br>");
out.println("This run took " + (t1-t0) + "ms.");
%>

输出结果为:
Cyc starts at 1054275312432 
Cyc ends at 1054275312442 
This run took 10ms.

其它:如何格式化小数

<%@ page import="java.text.*"%>
<%
DecimalFormat df = new DecimalFormat(",###.00");
double aNumber = 33665448856.6568975;
String result = df.format(aNumber);
out.println(result);
%>

输出结果为:
33,665,448,856.66

======================

日期比较:

在JAVA中日期的计算与比较可以使用Date和DateFormat来解决,下面是一段示例代码:

import java.text.*;
import java.util.*;

public class Test{

 public static void main(String[] args){
  try{
   Date date=new Date();
   DateFormat df=DateFormat.getDateTimeInstance();
   String now=df.format(date); 
   System.out.println("现在时间:"+now);

   System.out.println("现在时间是否在16:00之前:"+date.before(df.parse("2004-12-24 16:00:00"))); 
  }
  catch(ParseException e){System.out.print(e.getMessage());
  }
 }
}

忙来忙去没有目标

mikel阅读(907)

日志一天不写,就很难开头了。

不知不觉的天天写了这么长时间,结果日志总是要写的,因为每天都忙来忙去,却缺少了目标,世界总是那么大,想去看看的勇气都需要时间。

日志不写不用发布就没了那份坚持。不应该是坚持,应该是享受,其实很想享受这个写日志的过程。记录了自己从无到有的过程,总得记录下来,不说给谁看,权当是给自己一个交代了。

 

FileSystemWatch 对文件的监测 修改 创建 删除 并写入日志 - RunningMan1229 - 博客园

mikel阅读(1238)

来源: FileSystemWatch 对文件的监测 修改 创建 删除 并写入日志 – RunningMan1229 – 博客园

我做的这个主要是用来对文件的监测 修改 创建 删除 并写入日志

此外我做的WinForm程序

首先导入命名空间

1 using System.IO;

申明全局变量

1 private FileSystemWatcher watch = new FileSystemWatcher();
2 private FileStream fs = null;

先写一个写日志的方法,我这里写的路径都是固定的,你们可以给这个路径配置在App.config中,用户可以选择路径,选择完以后

修改config文件,下次用的时候可以默认选择上次的路径,这里我就不做了

复制代码
1 public void write(string message)
2 {
3 string path = “C:\\Log\\”;
4 if (!Directory.Exists(path))
5 {
6 Directory.CreateDirectory(path);
7 }
8 string fileName = path + “Log.txt”;
9
10 if (!File.Exists(fileName))
11 {
12 FileStream file = new FileStream(fileName, FileMode.Create);
13 file.Dispose();
14 }
15 fs = new FileStream(fileName, FileMode.Append, FileAccess.Write);
16 StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
17 sw.WriteLine(message);
18 sw.WriteLine(“———————–“);
19 sw.Dispose();
20 fs.Dispose();
21 }
复制代码

写监测的方法,我这里只是记录了一部分信息

复制代码
1 public void ReNameWatch(object sender, FileSystemEventArgs e)
2 {
3 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” ReName File : ” + e.Name.ToString());
4 }
5
6 public void DeleteWatch(object sender, FileSystemEventArgs e)
7 {
8 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Delete File : ” + e.Name.ToString());
9 }
10
11 public void CreateWatch(object sender, FileSystemEventArgs e)
12 {
13 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Create File : ” + e.Name.ToString());
14 }
15
16 public void ChangeWatch(object sender, FileSystemEventArgs e)
17 {
18 write(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss”) + ” Change File : ” + e.Name.ToString());
19 }
复制代码

写按钮点击事件

复制代码
1 public void Watch(object sender, EventArgs e)
2 {
3 if (this.button1.Text == “Start”)
4 {
5 string path = “C:\\”;
6 watch.Path = path;
7 watch.Filter = “*.txt”;
8 watch.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.LastAccess | NotifyFilters.Security;
9
10 watch.Renamed += new RenamedEventHandler(ReNameWatch);
11 watch.Deleted += new FileSystemEventHandler(DeleteWatch);
12 watch.Created += new FileSystemEventHandler(CreateWatch);
13 watch.Changed += new FileSystemEventHandler(ChangeWatch);
14
15 watch.EnableRaisingEvents = true;
16 this.button1.Text = “Stop”;
17 }
18 else if (this.button1.Text == “Stop”)
19 {
20 watch.EnableRaisingEvents = false;
21 this.button1.Text = “Start”;
22 }
23 }
复制代码

写加载事件

1 public Two()
2 {
3 InitializeComponent();
4 this.KeyDown += new KeyEventHandler(Two_KeyDown);
5 this.button1.Click += new EventHandler(Watch);
6 }

生成日志文件Log.txt截图

Winform开发——本地磁盘目录树浏览 - Erebus_NET - 博客园

mikel阅读(1261)

来源: Winform开发——本地磁盘目录树浏览 – Erebus_NET – 博客园

这学期的项目做了一堆,几乎都是用Winform(C#)写的,一个大的项目涉及到的Winform控件非常多,基本的控件几乎都要使用一遍,有用VS自带的,有用第三方的,有用自己写的。这篇说一下常用的本地磁盘目录树以及当前文件夹内容浏览“套件”的开发。

本地磁盘内容浏览“套件”涉及到两个基本的控件:TreeView和ListView,其中TreeView用来显示磁盘目录的层次关系,节点为磁盘的某个文件夹,用户可以单击节点展开文件夹浏览其子文件夹的层次关系。ListView的视图类似Windows自带的资源管理器,可以给出当前浏览目录下的文件和文件和问文件夹图标,双击后可以进入下一层目录。

第一步:搞定ListView中每个显示项目的图标

系统中的文件夹和不同扩展名的文件在资源管理器中显示的图标也不同,如果在使用ListView显示当前文件夹下所有项目的图标时都自定义添加,这显然是不现实的。那么我们有没有一种办法可以让系统根据某个文件项目的扩展名自动从系统图标库中选取相应的图标呢?免去我们找各种图标图片的麻烦。答案是肯定的,只是我们需要调用一些Win32的API。

首先申明如下:

#region 图标

public static uint SHGFI_ICON = 0x100;

public static uint SHGFI_DISPLAYNAME = 0x150;

public static uint SHGFI_TYPENAME = 0x400;

public static uint SHGFI_ATTRIBUTES = 0x800;

public static uint SHGFI_ICONLOCATION = 0x1000;

public static uint SHGFI_EXETYPE = 0x1500;

public static uint SHGFI_SYSICONINDEX = 0x4000;

public static uint SHGFI_LINKOVERLAY = 0x8000;

public static uint SHGFI_SELECTED = 0x10000;

public static uint SHGFI_LARGEICON = 0x0;

public static uint SHGFI_SMALLICON = 0x1;

public static uint SHGFI_OPENICON = 0x2;

public static uint SHGFI_SHELLICONSIZE = 0x4;

public static uint SHGFI_PIDL = 0x8;

public static uint SHGFI_USEFILEATTRIBUTES = 0x10;

 

public static uint FILE_ATTRIBUTE_NORMAL = 0x80;

public static uint LVM_FIRST = 0x1000;

public static uint LVM_SETIMAGELIST = LVM_FIRST + 3;

public static uint LVSIL_NORMAL = 0;

public static uint LVSIL_SMALL = 1;

 

[DllImport(“Shell32.dll”)]

public static extern IntPtr SHGetFileInfo(string pszPath,

   uint dwFileAttributes, ref SHFILEINFO psfi,

   int cbfileInfo, uint uFlags);

 

public struct SHFILEINFO

{

   public IntPtr hIcon;

   public int iIcon;

   public int dwAttributes;

   public string szDisplayName;

   public string szTypeName;

}

 

[DllImport(“User32.DLL”)]

public static extern int SendMessage(IntPtr hWnd,

   uint Msg, IntPtr wParam, IntPtr lParam);

 

public void ListViewSysImages(ListView AListView)

{

   SHFILEINFO vFileInfo = new SHFILEINFO();

   IntPtr vImageList = SHGetFileInfo(“”, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SHELLICONSIZE |

      SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

 

   SendMessage(AListView.Handle, LVM_SETIMAGELIST, (IntPtr)LVSIL_NORMAL, vImageList);

   vImageList = SHGetFileInfo(“”, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SHELLICONSIZE |

      SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

   SendMessage(AListView.Handle, LVM_SETIMAGELIST, (IntPtr)LVSIL_SMALL, vImageList);

 

}

public int FileIconIndex(string AFileName)

{

   SHFILEINFO vFileInfo = new SHFILEINFO();

   SHGetFileInfo(AFileName, 0, ref vFileInfo,

      Marshal.SizeOf(vFileInfo), SHGFI_SYSICONINDEX);

   return vFileInfo.iIcon;

}

#endregion

假设现在我们有ListView控件实例testListView,在使用这个控件之前我们对其进行初始化处理:

ListViewSysImages(testListView);

当我们需要向testListView中添加项目时,使用如下语句:

ListViewItem lvi = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

lvi.ImageIndex = FileIconIndex(FileName);

第二步:树形结构添加节点

使用TreeView之前我们需要找到四个基本图标:选定状态的文件夹、未选定状态的文件夹、磁盘图标、CD驱动器图标。将这四个图标添加到ImageList控件中调整好顺序。

#region 树形结构

//树形结构初始化

private void InitialTreeView(TreeNode rootNode)

{

   //将驱动器字符串数组设为空

   string[] drivers = null;

   //检索此计算机上逻辑驱动器的名称

   drivers = Directory.GetLogicalDrives();

   int i = 0;

   //初始化每一个逻辑驱动器

   while (i < drivers.GetLength(0))

   {

      TreeNode newNode = new TreeNode(drivers[i].ToString().Substring(0, 2));

      newNode.Tag = drivers[i];

      //获得驱动器类型,设置图标

      DriveInfo di = new DriveInfo(drivers[i]);

      if (di.DriveType == DriveType.CDRom)

      {

        newNode.ImageIndex = 2;

        newNode.SelectedImageIndex = 2;

      }

      else

      {

        newNode.ImageIndex = 1;

        newNode.SelectedImageIndex = 1;

      }

      rootNode.Nodes.Add(newNode);

      string path = drivers[i];

      string[] dirs = null;

      try

      {

        //获得指定驱动器中第一级目录的名称

        dirs = Directory.GetDirectories(path);

      }

      catch (Exception error)

      {

        dirs = null;

        //错误处理为空,即忽略

      }

      if (dirs != null)

      {

        //为每一个代表驱动器的根节点添加子节点

        for (int j = 0; j < dirs.Length; j++)

        {

           if ((File.GetAttributes(dirs[j]) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           //获得节点去掉路径的目录名

           TreeNode node = new TreeNode(dirs[j].ToString().Substring(dirs[j].ToString().LastIndexOf(“\\”) + 1));

           node.Tag = dirs[j];

           //设置不选定状态下的图标

           node.ImageIndex = 3;

           //设置打开状态下的图标

           node.SelectedImageIndex = 4;

           //添加节点

           rootNode.Nodes[i].Nodes.Add(node);

        }

      }

      //继续下一循环

      i++;

   }

}

//树形结构显示

private void TreeViewShow(TreeNode NodeDir)

{

   try

   {

      string[] dirs = null;

      int i = 0;

      while (i < NodeDir.Nodes.Count)

      {

        //添加子节点

        try

        {

           dirs = Directory.GetDirectories((string)NodeDir.Nodes[i].Tag);

        }

        catch

        {

           dirs = null;

        }

 

        if (dirs != null)

        {

           //删除以前节点

           NodeDir.Nodes[i].Nodes.Clear();

           //为驱动器根节点添加子节点

           for (int j = 0; j < dirs.Length; j++)

           {

              //获得节点去掉路径的目录名

              TreeNode node = new TreeNode(dirs[j].ToString().Substring(dirs[j].ToString().LastIndexOf(“\\”) + 1));

              node.Tag = dirs[j];

              //设置不选定状态下的图标

              node.ImageIndex = 3;

              //设置打开状态图标

              node.SelectedImageIndex = 4;

              //添加节点

              NodeDir.Nodes[i].Nodes.Add(node);

           }

        }

        i++;

      }

   }

 

   catch (Exception e)

   {

      MessageBox.Show(e.Message);

   }

}

//树形结构节点点击事件

private void treeView_AfterSelect(object sender, TreeViewEventArgs e)

{

   currentPath = (string)e.Node.Tag;

   if (currentPath != null && !currentPath.EndsWith(“\\”))

   {

      currentPath += “\\”;

   }

   urlBox.Text = currentPath;

   ListViewShow(e.Node);

}

//树形结构节点展开事件

private void treeView_AfterExpand(object sender, TreeViewEventArgs e)

{

   if (e.Node.Parent != null)

   {

      TreeViewShow(e.Node);

   }

}

#endregion

第三步:显示当前路径下的所有文件项目

#region 文件浏览

//初始化ListView控件,把TrreView控件中的数据添加进来

private void ListViewShow(TreeNode NodeDir)

{

   int itemNum = 0;//统计项目总数

   listView1.Clear();

   listView1.Columns.Add(“名称”, 150);

   listView1.Columns.Add(“修改日期”, 150);

   listView1.Columns.Add(“大小”, 100, HorizontalAlignment.Right);

   try

   {

      if (NodeDir.Parent == null)// 如果当前TreeView的父结点为空,就把我的电脑下的分区名称添加进来

      {

        foreach (string DrvName in Directory.GetLogicalDrives())//获得硬盘分区名

        {

           FileInfo fileInfo = new FileInfo(DrvName.Substring(0, 2));

           ListViewItem ItemList = new ListViewItem(DrvName.Substring(0, 2));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           ItemList.ImageIndex = FileIconIndex(DrvName);

           listView1.Items.Add(ItemList);//添加进来

           itemNum++;

        }

      }

 

      else//如果当前父节点不为空,把点击的结点,做为一个目录文件的总结点

      {

        foreach (string DirName in Directory.GetDirectories((string)NodeDir.Tag))//遍历当前分区或文件夹下所有目录

        {

           if ((File.GetAttributes(DirName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           FileInfo fileInfo = new FileInfo(DirName);

           ListViewItem ItemList = new ListViewItem(DirName.Substring(DirName.LastIndexOf(“\\”) + 1));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           ItemList.ImageIndex = FileIconIndex(DirName);

           ItemList.Tag = DirName;

           listView1.Items.Add(ItemList);

           itemNum++;

        }

 

        foreach (string FileName in Directory.GetFiles((string)NodeDir.Tag))//遍历当前分区或文件夹所有目录的文件

        {

           if ((File.GetAttributes(FileName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

           {

              continue;

           }

           FileInfo fileInfo = new FileInfo(FileName);

           ListViewItem ItemList = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

           ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

           long length = fileInfo.Length / 1024;

           if (length == 0) length = 1;

           ItemList.SubItems.Add(length + ” KB”);

           ItemList.ImageIndex = FileIconIndex(FileName);

           ItemList.Tag = FileName;

           listView1.Items.Add(ItemList);

           itemNum++;

        }//

      }

   }

   catch { }

   itemNumber.Text = itemNum.ToString();

}

//获取当有文件夹内的文件和目录

public void ListViewShow(string DirFileName)

{

   int itemNum = 0;

   listView1.Clear();

   listView1.Columns.Add(“名称”, 150);

   listView1.Columns.Add(“修改日期”, 150);

   listView1.Columns.Add(“大小”, 100, HorizontalAlignment.Right);

   try

   {

      foreach (string DirName in Directory.GetDirectories(DirFileName))//遍历当前分区或文件夹所有目录

      {

        if ((File.GetAttributes(DirName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

        {

           continue;

        }

        FileInfo fileInfo = new FileInfo(DirName);

        ListViewItem ItemList = new ListViewItem(DirName.Substring(DirName.LastIndexOf(“\\”) + 1));

        ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

        ItemList.ImageIndex = FileIconIndex(DirName);

        ItemList.Tag = DirName;

        listView1.Items.Add(ItemList);

        itemNum++;

      }

 

      foreach (string FileName in Directory.GetFiles(DirFileName))//编历当前分区或文件夹所有目录的文件

      {

        if ((File.GetAttributes(FileName) & FileAttributes.Hidden) == FileAttributes.Hidden && showHiden.Value == false)

        {

           continue;

        }

        FileInfo fileInfo = new FileInfo(FileName);

        ListViewItem ItemList = new ListViewItem(FileName.Substring(FileName.LastIndexOf(“\\”) + 1));

        ItemList.SubItems.Add(fileInfo.LastWriteTime.ToString());

        long length = fileInfo.Length / 1024;

        if (length == 0) length = 1;

        ItemList.SubItems.Add(length + ” KB”);

        ItemList.ImageIndex = FileIconIndex(FileName);

        ItemList.Tag = FileName;

        listView1.Items.Add(ItemList);

        itemNum++;

      }//

   }

   catch

   { }

 

   itemNumber.Text = itemNum.ToString();

}

//列表框鼠标双击事件

private void listView1_DoubleClick(object sender, EventArgs e)

{

   string fullName = currentPath + listView1.FocusedItem.Text;

   if (Directory.Exists(fullName))

   {

      currentPath = fullName + “\\”;

      fullName += “\\”;

      ListViewShow(fullName);

      urlBox.Text = currentPath;

   }

}

#endregion

第四步:回到上层目录

//工具栏上层目录

private void parentDir_Click(object sender, EventArgs e)

{

   if (currentPath != “” && currentPath != null)

   {

      currentPath = currentPath.Substring(0, currentPath.Length – 2);

      if (currentPath.LastIndexOf(‘\\’) > 0)

      {

        currentPath = currentPath.Substring(0, currentPath.LastIndexOf(‘\\’) + 1);

        urlBox.Text = currentPath;

        ListViewShow(currentPath);

      }

      else//如果是根节点,则添加磁盘驱动器

      {

        listView1.Items.Clear();

        currentPath = “”;

        urlBox.Text = currentPath;

        TreeNode rootNode = new TreeNode(“My”);

        ListViewShow(rootNode);

      }

   }

}

第五步:添加右键菜单

为了能够对控件组合能够更好的操作,我们通常情况下需要添加右键菜单,首先我们在窗体设计界面上添加ComtextMenuStrip控件listView1Menu:

//列表框鼠标点击事件

private void listView1_MouseClick(object sender, MouseEventArgs e)

{

   if (e.Button == MouseButtons.Right && currentPath != “” && currentPath != null)

   {

      Point position;

      position = new Point(e.X, e.Y);

      listView1Menu.Show(this.listView1, position);

   }

}

此时在运行程序后在ListView控件显示的项目上右键单击鼠标便会弹出listView1Menu菜单。

第六步:初始化,开始运行

运行之前需要在窗体加载事件中写入下面的代码:

#region treelist初始化

//初始化列表图标

ListViewSysImages(listView1);

ListViewSysImages(listView2);

ListViewSysImages(fileDownload);

//初始化树形结构

treeView.ImageList = imageList;

//添加根节点

TreeNode rootNode = new TreeNode(“我的电脑”);//初始化TreeList添加总根节点

rootNode.ImageIndex = 0;

rootNode.SelectedImageIndex = 0;

treeView.Nodes.Add(rootNode);

//初始化树形结构

InitialTreeView(rootNode);

rootNode.Expand();

ListViewShow(rootNode);

#endregion

之后,编译运行。

微博上看到的视频下载到电脑上的方法

mikel阅读(1784)

我们刷微博时经常会看到网友发表视频,看到一些很棒的视频你是不是想下载到电脑上呢?网上可以找到很多所谓的教程,适用范围都不普遍。现在分类介绍下载那些视频的方法。

工具/原料

  • 浏览器(建议使用IE)
  • 迅雷
  • 部分视频网站的专用下载工具(如优酷、土豆)

第一类:有专用下载器的(如优酷、土豆)

  1. 1

    首先,下载视频的第一步就是进入原网页。在微博上就能找到(红框所示)。每一条分享视频的微博都会有一个这样的图标,点它就能进入原网页。

  2. 2

    进入了原网页,接下来就是用那些下载器来下载了。第一类是比较简单的。

    END

第二类:美拍视频

  1. 1

    由美图秀秀推出的“美拍”应用如今越来越受欢迎,使用人数也很多。美拍的视频在电脑上可以用迅雷来下载。第一步依然是进入原网页。

  2. 2

    进入原网页后,在网页内空白处右击鼠标,选择“查看源代码”。

  3. 3

    在源代码界面里你会看到一个“http://…….mp4”的地址,如果找不到,可以按组合键Ctrl+F打开查找功能,输入“.mp4”查找。找 到这个地址后复制它,这时如果你的迅雷已经打开,就会自动弹出建立新任务的提示。这样就能把美拍的视频下载好了。美拍这一类视频的网页在源代码中有完整视 频地址,下载相对也比较方便。

    END

第三类:只能找缓存文件的(如秒拍、微博视频)

  1. 1

    秒拍似乎已经过气了,“微博视频”也是现在手机微博的功能,经常被使用。这两种视频是以Flash的形式播放的,地址在源代码里找不到。很多网友都 说可以在缓存文件里找到,但如今的主流浏览器(如360、百度)为了减少内存占用量,是不保存大部分视频的缓存文件的,实践证明用360看过这两种视频 后,缓存文件里根本找不到对应文件。因此假如你对这个视频有比较执着的喜爱,那就麻烦一下找IE浏览器帮忙吧。

  2. 2

    可以把视频的原网页网址复制到IE打开。在视频播放完后,打开缓存文件夹(浏览器菜单栏上,工具==>Internet选项==>常规==>浏览历史记录==>设置==>查看文件)

  3. 3

    然后会打开一个文件很多的文件夹。这个文件夹的显示方式和一般的文件夹是不一样的。查看方式选择“详细信息”,按“上次访问时间”排序。然后拉到最近的文件,找到一个视频文件(一般是MP4文件)。

  4. 4

    如果你想打开看看这个文件是不是你要找的,一定要注意不要直接打开。一方面这个文件夹是Internet的缓存文件夹,直接打开只能用浏览器;另一方面,这些缓存的媒体文件只要被打开后就会消失。所以先把文件复制到另一个文件夹再打开。

  5. 5

    以上三类可以解决微博上绝大多数视频的下载问题了。希望能对你有帮助。

iphone绘图的几个基本概念CGPoint、CGSize、CGRect、CGRectMake、window(窗口)、视图(view)

mikel阅读(991)

我一般情况下不会使用interface builder去画界面,而是用纯代码去创建界面,不是装B,而是刚从vi转到xcode不久,不太习惯interface builder而已。当然如果需要我也会使用它。一个东西的存在没有绝对的好与坏,只是存在时间与空间决定了它的价值。

(忘了讲了,我的环境是xcode4.2)

首先要弄懂几个基本的概念。

 

一)三个结构体:CGPoint、CGSize、CGRect

1.  CGPoint

  1. /* Points. */
  2. struct CGPoint {
  3.   CGFloat x;
  4.   CGFloat y;
  5. };
  6. typedef struct CGPoint CGPoint;

看到这个想必你已经懂了,不再解释。

 

 

2.  CGSize

 

  1. /* Sizes. */
  2. struct CGSize {
  3.   CGFloat width;
  4.   CGFloat height;
  5. };
  6. typedef struct CGSize CGSize;

不解释。

 

3.CGRect

  1. /* Rectangles. */
  2. struct CGRect {
  3.   CGPoint origin;//偏移是相对父窗口的
  4.   CGSize size;
  5. };
  6. typedef struct CGRect CGRect;

同样 不解释。

 

这三个结构体均在一个头文件里:CGGeometry.h

二)几个方法

1.CGRectMake

  1. CG_INLINE CGRect
  2. CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
  3. {
  4.   CGRect rect;
  5.   rect.origin.x = x; rect.origin.y = y;
  6.   rect.size.width = width; rect.size.height = height;
  7.   return rect;
  8. }

没错,这个方法就是make一个rect,定好origin(起点,左上角),宽与高,就可以画出一个位置与大小确定的rect(矩形)这个函数被声明为内联函数,一是因为它比较小,二是因为在画界面时我们要求一定的效率。这个函数还是藏在刚刚那个头文件里面:CGGeometry.h

 

三)几个基本界面元素:window(窗口)、视图(view)

要在屏幕上显示内容首先要创建一个窗口承载内容,要创建一个窗口,需要一个边框(frame),含有边框信息的底层 结构就CGRect。每个能够在屏幕上显示自己的对象都有一个边框,定义了他的显示区域,不过许多高层的视图类会自动计算这一信息。其他的那些类则在视图初始化时通过一个initWithFrame的初始化方法来设置。

再来认识一个类:UIScreen。UIScreen类代表了屏幕,通过这个类我们可以获取一些想要的东东。

  1. CGrect screenBounds = [ [UIScreen mainScreen]bounds];//返回的是带有状态栏的Rect
  2. CGRect viewBounds = [ [UIScreen mainScreen]applicationFrame];//不包含状态栏的Rect
  3. //screenBounds 与 viewBounds 均是相对于设备屏幕来说的
  4. //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 0.0;   screenBounds.size.width == 320;  screenBounds.size.height == 480(或者其他分辨率有所差异)
  5. //所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 20.0;(因为状态栏的高度是20像素)   screenBounds.size.width == 320;  screenBounds.size.height == 480

 

UIView

下面来认识一下UIView类,这个类继承自UIResponder,看这个名字我们就知道它是负责显示的画布,如果说把window比作画框的话。我们就是不断地在画框上移除、更换或者叠加画布,或者在画布上叠加其他画布,大小当然 由绘画者来决定了。有了画布,我们就可以在上面任意施为了。很多简单的东西我会把库里面的内容贴出来,如果东西太多贴出来就不太好,朋友们自己去库文件里面看吧。这个类在UIView.h里面。下面我们先学习一些基础的东西,其他的东东会在以后慢慢展开。

  1. UIView* myView =[[ UIView alloc]initWithFrame:CGRectMake(0.0,0.0,200.0,400.0)];//这里创建了一块画布,定义了相对于父窗口的位置, 以及大小。

我们可以把这块画布加到其他画布上,具体方法后面会讲到。我们还可以在这块画布上画上其它好玩的东东,具体情形后面会一一讲解。

 

 

UIWindow

UIWindow继承自UIView,关于这一点可能有点逻辑障碍,画框怎么继承自画布呢?不要过于去专牛角尖,画框的形状不就是跟画布一样吗?拿一块画布然后用一些方法把它加强,是不是可以当一个画框用呢?这也是为什么 一个view可以直接加到另一个view上去的原因了。

看一下系统的初始化过程(在application didFinishLauchingWithOptions里面):

  1. self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
  2. self.window.backgroundColor = [UIColor grayColor];//给window设置一个背景色

XCode环境变量及路径设置

mikel阅读(1001)

一般我们在xcode里面配置包含工程目录下头文件的时候,都要关联着相对路径和绝对路径,如果只是自己用这个项目,用绝对路径的问题不大,但是如果你把工程发给别人,别人就要在改这个绝对路径,这时候绝对路径的缺点立马出现。

所以在修改User Header Search Paths这个选项的时候使用
“$(SRCROOT)/当前工程名字/需要包含头文件所在文件夹”
将上面的双引号里面的字符串拷贝之后,你会发现这个“$(SRCROOT)”,会自动变成当前工程所以的目录。

这样就可以了,发给别人,别人也不用在去修改路径了。

xcode4的环境变量,Build Settings参数,workspace及联编设置

一、xcode4中的环境变量

$(BUILT_PRODUCTS_DIR)

build成功后的,最终产品路径--可以在Build Settings参数的Per-configuration Build Products Path项里设置

$(TARGET_NAME)

目标工程名称

$(SRCROOT)

工程文件(比如Nuno.xcodeproj)的路径

$(CURRENT_PROJECT_VERSION)

当前工程版本号

 

其他:

当编译静态库,设备选模拟器(iPhone 5.0 Simulator),未设置任何Build Settings参数时,默认的基础路径:

/Users/xxx/Library/Developer/Xcode/DerivedData/xxxWorkspace-caepeadwrerdcrftijaolkkagbjf

下面用$()代替上面一长串东东

$(SYMROOT) = $()/Build/Products

$(BUILD_DIR) = $()/Build/Products

$(BUILD_ROOT) =  $()/Build/Products

这三个变量中的$()不会随着Build Settings参数的设置而改变

相反,以下可以通过设置而改变

$(CONFIGURATION_BUILD_DIR) = $()/Build/Products/Debug-iphonesimulator

$(BUILT_PRODUCTS_DIR) = $()/Build/Products/Debug-iphonesimulator

$(CONFIGURATION_TEMP_DIR) = $()/Build/Intermediates/UtilLib.build/Debug-iphonesimulator

$(TARGET_BUILD_DIR) = $()/Build/Products/Debug-iphonesimulator

$(SDK_NAME) = iphonesimulator5.0

$(PLATFORM_NAME) = iphonesimulator

$(CONFIGURATION) = Debug

$(TARGET_NAME) = UtilLib

$(EXECUTABLE_NAME) = libUtilLib.a 可执行文件名

${IPHONEOS_DEPLOYMENT_TARGET} 5.0

$(ACTION) = build

$(CURRENTCONFIG_SIMULATOR_DIR) 当前模拟器路径

$(CURRENTCONFIG_DEVICE_DIR) 当前设备路径

$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME =

$()/Build/Products/Debug-iphonesimulator

$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) = $()/Build/Intermediates/UtilLib.build/Debug-iphonesimulator

自定义变量

${CONFIGURATION}-iphoneos 表示:Debug-iphoneos

${CONFIGURATION}-iphonesimulator 表示:Debug-iphonesimulator

$(CURRENTCONFIG_DEVICE_DIR) = ${SYMROOT}/${CONFIGURATION}-iphoneos

$(CURRENTCONFIG_SIMULATOR_DIR) = ${SYMROOT}/${CONFIGURATION}-iphonesimulator

自定义一个设备无关的路径(用来存放各种架构arm6/arm7/i386输出的产品)

$(CREATING_UNIVERSAL_DIR) = ${SYMROOT}/${CONFIGURATION}-universal

自定义变量代表的值

$(CURRENTCONFIG_DEVICE_DIR) = $()/Build/Products/Debug-iphoneos

$(CURRENTCONFIG_SIMULATOR_DIR) = $()/Build/Products/Debug-iphonesimulator

$(CREATING_UNIVERSAL_DIR) = $()/Build/Products/Debug-universal

iphoneos5.0下的编译脚本:

xcodebuild -project “UtilLib.xcodeproj” -configuration “Debug” -target “UtilLib” -sdk “iphoneos5.0” -arch “armv6 armv7″ build RUN_CLANG_STATIC_ANALYZER=NO  $(BUILD_DIR)=”${BUILD_DIR}” BUILD_ROOT=“${BUILD_ROOT}”

iphonesimulator5.0下的编译脚本:

xcodebuild -project “UtilLib.xcodeproj” -configuration “Debug” -target “UtilLib” -sdk “iphonesimulator5.0” -arch “i386″ build RUN_CLANG_STATIC_ANALYZER=NO $(BUILD_DIR)=”${BUILD_DIR}”  BUILD_ROOT=“${BUILD_ROOT}”

加上下面一句表示输出到文件:

“${BUILD_ROOT}.build_output”

lipo脚本工具:合并iPhone模拟器和真机的静态类库,生成通用库

lipo -create -output “${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}” “${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}”         “${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}”

意思是:把”${CURRENTCONFIG_DEVICE_DIR}目录下的.a文件,和${CURRENTCONFIG_SIMULATOR_DIR}目录下的.a文件合并,

在${CREATING_UNIVERSAL_DIR}目录下,生成两个设备都通用的静态库,

例如:lipo -create -output xy.a x.a y.a

二、xcode4中build Settings常见参数解析

1.Installation Directory:安装路径

静态库编译时,在Build Settings中Installation Directory设置“$(BUILT_PRODUCTS_DIR)”

Skip Install设为YES

Installation Directory默认为/usr/local/lib

因为Build Location默认时,.a文件会放在很长(比如:/Users/xxx/Library/Developer/Xcode/DerivedData/xxxProgram

dalrvzehhtesxdfqhxixzafvddwe/Build/Products/Debug-iPhoneos)的路径下,或是我们target指定的路径

Skip Install如果是NO,可能会被安装到默认路径/usr/local/lib

2.Public Headers Folder Path:对外公开头文件路径

设为“include”(具体的头文件路径为:$(BUILT_PRODUCTS_DIR)/include/xx.h)

在最终文件.a同级目录下生成一个include目录

默认:/usr/local/include

Public Headers Folder Path这个路径就是使用这lib的某工程需要依赖的外部头文件.导入这路径后,#include/import “xx.h”才能看到

3.User Header Search Paths:依赖的外部头文件搜索路径

设置为“$(BUILT_PRODUCTS_DIR)/include”

和2中路径对应

4.Per-configuration Build Products Path:最终文件路径

比如设为“../app”,就会在工程文件.xcodeproj上一层目录下的app目录里,创建最终文件

默认为$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

等于$(BUILT_PRODUCTS_DIR)

5.Per-configuration Intermediate Build Files Path:临时中间文件路径

默认为:$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

6.Code Signing Identity:真机调试的证书选择

选一个和Bundle identifier相对应的证书

Library Search Paths:库搜索路径

Architectures:架构,设为 armv6 或 armv7

Valid Architectures:应用框架,可以设为 armv6、 armv7 或i386

Product Name:工程文件名,默认为$(TARGET_NAME)

Info.plist File:info文件路径

Build Variants:默认为normal

Other Linker Flags:其他链接标签

设为“-ObjC”

当导入的静态库使用了类别,需要设为-ObjC

iOS Deployment Target:ios部署对象

比如可以选择设为,ios3到ios5的一种版本

Prefix Header:预编头文件(比如:UtilLib/UtilLib-Prefix.pch)

Precompile Prefix Header:设为“Yes”,表示允许加入预编译头

 

三、workspace(工作区)

作用:管理多个工程(project),多工程联编

 

四、workspace多工程联编设置

一、

1.新建一个静态库工程,比如UtilLib,并生成UtilLib.h和UtilLib.m文件

2.选中需要公开的头文件,

把右侧栏的Target Membership中设置为public

或则,选中工程目录target的Build Phases标签的copy headers项,在public中添加要公开的头文件

3.Architectures设为:armv6 armv7

4.Valid Architectures设为:armv6 armv7 i386

5.Build Products Path设为:$(SRCROOT)/../build

6.Per-configuration Build Products Path设为:

$(SRCROOT)/../build/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

7.Per-configuration Intermediate Build Files Path设为:

$(SRCROOT)/../build/$(TARGET_NAME).build/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

8.设置安装路径:Installation Directory项

9.设置对外公开的头文件路径:Public Headers Folder Path项

10.为静态库添加依赖的shell脚本

选中工程目录target的Build Phases标签,点击由下角的Add Build Phase按钮

在弹出的菜单里选择Add run script项,然后页面中会多出一个Run Script项

在黑框里填写”$SRCROOT/mergeArmSymbols.sh”

建立对此脚本的依赖(编译静态库的后会运行此脚本)

如果编译时设备选的是iphone simulator:

则此脚本会在对应iphone device的产品目录Debug-iphoneos中,生成对device有用的.a静态库,

相反,如果设备选的是iphone device:

则此脚本会在对应iphone simulator的产品目录Debug-iphoneos中,生成对simulator有用的.a静态库

最后,此脚本调用lipo工具,把本工程生成静态库与此脚本生成的静态库合并,生成simulator和device都通用的.a文件

 

11.具体bash shell脚本如下:

mergeArmSymbols.sh
 # Version 2.0 (updated for Xcode 4, with some fixes)

 # Author: Adam Martin - http://twitter.com/redglassesapps
 # Based on: original script from Eonil (main changes: Eonil's script WILL NOT WORK in Xcode GUI - it WILL CRASH YOUR COMPUTER)
 #
 # More info: see this Stack Overflow question: http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4

 #################[ Tests: helps workaround any future bugs in Xcode ]########
 #
 DEBUG_THIS_SCRIPT="true"

 if [ $DEBUG_THIS_SCRIPT = "true" ]
 then
 echo "########### TESTS #############"
 echo "Use the following variables when debugging this script; note that they may change on recursions"
 echo "BUILD_DIR = $BUILD_DIR"
 echo "BUILD_ROOT = $BUILD_ROOT"
 echo "CONFIGURATION_BUILD_DIR = $CONFIGURATION_BUILD_DIR"
 echo "BUILT_PRODUCTS_DIR = $BUILT_PRODUCTS_DIR"
 echo "CONFIGURATION_TEMP_DIR = $CONFIGURATION_TEMP_DIR"
 echo "TARGET_BUILD_DIR = $TARGET_BUILD_DIR"
 echo "SDK_NAME = $SDK_NAME"
 echo "PLATFORM_NAME = $PLATFORM_NAME"
 echo "CONFIGURATION = $CONFIGURATION"
 echo "TARGET_NAME = $TARGET_NAME"
 echo "ARCH_TO_BUILD = $ARCH_TO_BUILD"
 echo "ARCH_TO_BUILD = $ARCH_TO_BUILD"
 echo "ACTION = $ACTION"
 echo "SYMROOT = $SYMROOT"
 echo "EXECUTABLE_NAME = $EXECUTABLE_NAME"
 echo "CURRENTCONFIG_SIMULATOR_DIR = $CURRENTCONFIG_SIMULATOR_DIR"
 echo "CURRENTCONFIG_DEVICE_DIR = $CURRENTCONFIG_DEVICE_DIR"

 echo "#############Other###########"
 echo "BUILD_DIR/CONFIGURATION/EFFECTIVE_PLATFORM_NAME = $BUILD_DIR/$CONFIGURATION$EFFECTIVE_PLATFORM_NAME"

 echo "PROJECT_TEMP_DIR/CONFIGURATION/EFFECTIVE_PLATFORM_NAME = $PROJECT_TEMP_DIR/$CONFIGURATION$EFFECTIVE_PLATFORM_NAME"

 fi

 #####################[ part 1 ]##################
 # First, work out the BASESDK version number
 #    (incidental: searching for substrings in sh is a nightmare! Sob)

 SDK_VERSION=$(echo ${SDK_NAME} | grep -o '.\{3\}$')

 # Next, work out if we're in SIM or DEVICE

 if [ ${PLATFORM_NAME} = "iphonesimulator" ]
 then
 OTHER_SDK_TO_BUILD=iphoneos${SDK_VERSION}
 ARCH_TO_BUILD="armv6 armv7"
 else
 OTHER_SDK_TO_BUILD=iphonesimulator${SDK_VERSION}
 ARCH_TO_BUILD="i386"
 fi

 echo "XCode has selected SDK: ${PLATFORM_NAME} with version: ${SDK_VERSION} (although back-targetting: ${IPHONEOS_DEPLOYMENT_TARGET})"
 echo "...therefore, OTHER_SDK_TO_BUILD = ${OTHER_SDK_TO_BUILD}"
 #
 #####################[ end of part 1 ]##################

 #####################[ part 2 ]##################
 #
 # IF this is the original invocation, invoke whatever other builds are required
 #
 # Xcode is already building ONE target... build ONLY the missing platforms/configurations.

 if [ "true" == ${ALREADYINVOKED:-false} ]
 then
 echo "RECURSION: Not the root invocation, don't recurse"
 else
 # Prevent recursion
 export ALREADYINVOKED="true"

 echo "RECURSION: I am the root... recursing all missing build targets..."
 echo "RECURSION: ...about to invoke: xcodebuild -configuration \"${CONFIGURATION}\" -target \"${TARGET_NAME}\" -sdk \"${OTHER_SDK_TO_BUILD}\" -arch \"${ARCH_TO_BUILD}\" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO"
 xcodebuild -project "${TARGET_NAME}.xcodeproj" -configuration "${CONFIGURATION}" -target "${TARGET_NAME}" -sdk "${OTHER_SDK_TO_BUILD}" -arch "${ARCH_TO_BUILD}" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" > "${BUILD_ROOT}.build_output"
 ACTION="build"

 # Merge all platform binaries as a fat binary for each configurations.

 # Calculate where the (multiple) built files are coming from:
 CURRENTCONFIG_DEVICE_DIR=${SRCROOT}/../build/${CONFIGURATION}-iphoneos
 CURRENTCONFIG_SIMULATOR_DIR=${SRCROOT}/../build/${CONFIGURATION}-iphonesimulator

 echo "Taking device build from: ${CURRENTCONFIG_DEVICE_DIR}"
 echo "Taking simulator build from: ${CURRENTCONFIG_SIMULATOR_DIR}"

 CREATING_UNIVERSAL_DIR=${SRCROOT}/../build/${CONFIGURATION}-universal
 echo "...outputing a universal arm6/arm7/i386 build to: ${CREATING_UNIVERSAL_DIR}"

 # ... remove the products of previous runs of this script
 #      NB: this directory is only created by this script - it should be safe to delete

 rm -rf "${CREATING_UNIVERSAL_DIR}"
 mkdir "${CREATING_UNIVERSAL_DIR}"

 #
 echo "lipo: for current configuration (${CONFIGURATION}) creating output file: ${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}"
 lipo -create -output "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}"

 #######custom########
 #copy universal lib to ../libs
 libsDir=../libs
 includeDir=../include

 rm -rf "${libsDir}"
 mkdir -p "${libsDir}"

 echo "cp -R ${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME} ${libsDir}"

 cp -R "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "${libsDir}"

 echo "cp -R ${CURRENTCONFIG_DEVICE_DIR}/include ${includeDir}"

 cp -R "${CURRENTCONFIG_DEVICE_DIR}/include" "${includeDir}"

 fi

下载右边的图片,然后把后缀改为.sh(其实就是上面的脚本,因为博客园只能上传图片)

静态库编译后的目录结构如下:

 

二、

1.新建主工程,比如Nuno,添加对静态库的依赖

点击工程,在Build Phases标签的Link Binary With Libraries项中点击加号添加UtilLib.a库

选中上面的红色项,在右边栏的Location选Relative to Project,把值设为../libs/libUtilLib.a

2.设置主工程依赖的外部头文件路径:User Header Search Paths项

$(SRCROOT)/../include

3.设置Header Search Paths为:$(SRCROOT)/../include

4.设置Library Search Paths为:$(SRCROOT)/../libs

编译运行即可实现联编

 

(备注:选择模拟器iphone 5.0 simulator,编译静态库的时,最终文件会在Debug-iphonesimulator,就算成功.a文件还是红色,

这是可能是xcode的bug,不会自动切换路径

因为$(BUILT_PRODUCTS_DIR)所指的位置,是build/Debug-iphonesos,不是包含最终.a文件的Debug-iphonesimulator;

选择ios Device,编译成的最终文件才在build/Debug-iphonesos下,.a文件变成非红色

所有得用mergeArmSymbols.sh脚本来解决)


reference:

http://blog.sina.com.cn/s/blog_6de18992010190kk.html

http://www.cnblogs.com/xiaodao/archive/2012/03/28/2422091.html