2015-03-06 14:08:31 oqqQuZi1234567 阅读数 988

      在苹果推出iPhone5S时,64位的应用就走到了眼前。当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位。

      我记得自己刚刚接触电脑时还有16位的系统,指针的寻址范围还是16位的。当年用TurboC时,还要根据应用的大小选择是tiny模式还是其他。后来很长一段时间使用32位的模型编程,4G是牢牢记住的一个边界条件。而现在,64位走到了眼前。

      就如同16位转向32位一样,硬件肯定是最先推出的,SDK也会跟进,然后各种第三方的应用才会逐步跟进,这个过程一般都需要持续一段时间。这次苹果在推出之后,很长一阵子也处于32位和64位并行的过渡期,但是,随着10月份苹果宣布,2015年2月1日起,上传AppStore的应用都需要支持ARM64了,具体消息请猛戳这里

      于是开始看了一下32位应用如何转成64位应用

1. 基础知识

      Xcode 5.0.1开始支持编译32-bit和64-bit的Binary

      同时支持32-bit和64-bit,我们需要选择的minimum deployment target为 iOS 5.1.1

      64-bit的Binary必须运行在支持64-bit的CPU上,并且最小的OS版本要求是 7.0.3

 

2. 让应用兼容64位的基本步骤

      安装Xcode5.0.1或者以后——其实现在能提交AppStore的Xcode版本最少也要5.1.1

      在Xcode中打开工程,编译,修正错误以及警告,尤其是针对32位和64

      在Project Setting里面,把最小应用使用的SDK改到5.1.1或者更高的版本

      把Architectures参数设置成“Standard Architectures (including 64-bit).”

      这样你的应用就支持了64位的CPU,再次修复编译器的错误和警告,请注意,有些问题编译器是没有警告的

      在64位的真机上测试你的应用

      使用Instruments查看内存使用的状况


3. 从32位到64位的变化

3.1 数据类型的变化

      这里主要是语言内置类型所占的字节数以及字节对齐的不同。在32位的年代,使用的是IPL32的规范,到了64位之后,改成了LP64规范。

      

      除了这些以外,还有浮点类型

            

      数据类型里面,NSInteger在32位时等同于int,在64位时等同于long,而这个数据结构使用很广,很多不规范的时候会直接和int替换使用,在32位是毫无问题,但在64位时,这就是隐患了。CGFloat也有同样的问题,所以代码的检查修改必须仔细。

      至于对齐,如果使用了偏移量来访问struct的项,那么需要认真仔细的检查,其余的还算好,当然如果你用了malloc,那么也请检查一下分配的内存大小,建议是多使用sizeof来帮助计算。

      还有,针对存储的文件,比如存储在iCloud上的文件,你无法确定是一个32位应用还是64位的应用会去访问,那么请一定把数据内容的解释写成一模一样。


3.2 方法调用上的变化

      64位应用要求所有函数都有原型,这本身就是一个好的编码习惯

      函数的造型必须和原型完全一致,尤其要避免参数个数未定的函数指针造型(printf一类)

      在64位系统在运行时调用函数和32位系统是不同的。主要的区别在于传递具有可变参数个数的函数的参数时,我们来看下面的代码:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int fixedFunction(int a, int b);  
  2. int variadicFunction(int a, ...);  
  3.    
  4. int main  
  5. {  
  6.     int value2 = fixedFunction(5,5);  
  7.     int value1 = variadicFunction(5,5);  
  8. }  
      第一个函数是固定传入2个参数,第二个函数是参数个数不定的,在使用中,也传入了2个参数。在32位系统下,这两个函数的参数传递是非常类似的,而在64位系统下,这两者就是截然不同了。


3.3 汇编的不同

      因为是不同的指令集,汇编当然会不同。不过我们一般的应用不会用到汇编,所以这一项比较少遇到。


4. 第三方库

      最后,我们项目中使用的第三方库肯定需要支持64位系统,否则还是白搭。所以大家在升级时需要检查自己使用的第三方的库,看是否已经有64位的版本出现了。


      苹果目前的系统中(iOS7/iOS8),32位的framework和64位的framework是共存的,所以如果所有的应用都是64位的话,系统就自动不加载32位的framework,这样可以少占用资源,另外对运行的速度是有好处的,也就是说,你会感觉手机运行的快了一点。

      应用在兼容64位系统后,内存的占用肯定会变多一点,不过性能也有相应的提升。

参考:点击打开链接


2015-10-26 16:05:00 CrazyZhang1990 阅读数 1296

在我们打印指针变量所占字节数的时候知道指针变量所占的字节数只跟操作系统的位数有关。

int a = 20;
int *p = &a;
printf("SizeA = %lu\n", sizeof(a));
printf("SizeP = %lu\n", sizeof(p));
       
输出结果为:


那么如果我们想看到指针变量输出的字节数是4,应该如何切换操作系统位数呢。

首先打开xcode工程:


如上图所以先点击工程文件LessionEight  ->点击TARGETS下边的文件跟工程名一样 -> 在上边一排选择 Build Setting -> 在下边找到Architectures选项。

点击右边Architectures选项如果所示:

然后我们选择第四项:32 - bit Intel(i386)这个选项。

如果你要以为这样就大功告成那就错了,你command + R 运行一下会发现报错,如图:


最下边红框里边是错误的原因:

error: -fobjc-arc is not supported on platforms using the legacy runtime

大致意思是说你 ARC不支持你当前所选的平台,这时候需要把工程改回MRC。还是在刚才的地方所搜“gar”,然后下边只有一个选择,把右边的YES改为NO即可解决,如图:



改完之后在command + R运行一下,你会发现控制已经输出指针变量所占的字节数变为4:



2015-12-16 17:19:28 IOSWEB 阅读数 2522

1、判断是否是64位系统(iPhone6、5s、6s及以上)

- (BOOL)is64bit

{

#if defined(__LP64__) && __LP64__

  return YES;

#else

  return NO;

#endif

}

2、判断是否是32位系统(iPhone5、4s、4及以下)

- (BOOL)is32bit

{

#if defined(__LP64__) && __LP64__

  return NO;

#else

  return YES;

#endif

}
2017-09-14 11:50:19 qq_33224044 阅读数 654


IOS freerdp 64位系统编译

这是我编译版本

cmake -- version 3.9.1

xcode -- version 8.3.0
ios -- version10.3.3



==================分割线=======================

1.找到freerdp文件中的

iOSToolchain.cmake 用文本编辑器打开  如下图




可以看到ios cmake配置文件中是没有对64位系统做适配的
在armv7s后面需加入arm64  (对64位系统的支持)


2.更新openssl静态库

因为mac os版本的更新  有时会无法下载生成静态库 
这里  有我编译好的静态库(支持arm64) 密码:ohiu
替换项目中openssl文件

注:终端输入lipo -info (xxx.a)可查看当前静态库支持哪些系统编译 



3.cmake生成项目

cmake -DCMAKE_TOOLCHAIN_FILE=cmake/iOSToolchain.cmake -GXcode



完成后运行,编译完成!




2014-07-18 18:00:50 shinancao666 阅读数 1776

最近在要把写的代码打包成Framework包给其他人用,照着网上的博客介绍的过程做出来以后,发现在64位上运行时会崩溃掉,数个小时的google和测试后,最终在github上找到了一位大神写的文章,他自己写了一个脚本,将该问题解决掉了。(32个赞!)


下面是对他文章的翻译,注释是我在制作的工程中发现要注意的地方,原文地址:https://github.com/csexton/ios-framework-builder/blob/master/HOWTO.md


我的灵感极大程度上来自于Jeff VerKoeyen的iOS Framework指南,然而当苹果发布了新的64位架构后,打破了原有的一些事情。主要是我们现在有32位和64位的模拟器架构。不幸地是xcode并没有给你任何的方式来指定你想给模拟器设置的架构,当我在模拟器里编译时,我无法弄清楚如何巧妙地编译一个臃肿的二进制包。我可以用xcodebuild和一些环境变量来解决这个问题。我还希望把所有的框架编译工作放在一起,而不是对不同的target进行不同的编译设置。


在这篇文章的末尾,你将得到一个单独的aggregate target,它会构建你的二进制包,并把它编译成.framework。原始的target通常只是构建了一个.a文件。


1 制作一个通用的Cocoa Touch Static Library

1.1 创建一个新的工程

如果有必要,那就创建一个新的library工程。

这只会生成一个.a二进制包和hearders文件。我们将添加一个target,这个target将把它转换成一个合适的framework


1.2 Framework Header

你需要创建一个这个framework总的要导入的头文件。这个会提供给你的library的使用者,而不是这个library的本身。

例如我已经有一个叫作"MyFramework"的framework包,还有一个MyFramework/MyFramework头,像下面这样:

#import <Foundation/Foundation.h>
#import <MyFramework/MyFramework.h>

我只要将该头文件添加到工程中即可使用MyFramework包中的功能了。

1.3 公开的文件

首先你需要添加一个Copy Header build phase。到状态栏,然后点击:

  • Editor
  • Add Build Phase
  • Add Copy Headers Build Phase
(注:不知道为什么我这里上面的那一项是不可用的,不过选中target后,在Build Phases中下面搜索框前面的+也是可以的,如下图)

这时你看的界面如下所示:


为了暴露你插件包中的功能,你需要公开对外可见的头文件。用XCode的"Target Membership"来完成。

为了设置membership mash ⌘-⌥-0,然后勾选或不勾选Target Membership,然后设置为"project"


注:当你要把一个头文件放到.framework里时,你就要这样做。

(注:在我测试的过程中发现,要把那一项设置为public的才行,是project的话对外还是不可见的)

更新公开头文件的路径。在build setting中搜索"Public Headers Folder Path",然后将其值改变为:

$(PROJECT_NAME)Headers


(注:这一项一定要设置,否则头文件里任何一个.h文件都没有)
这会把头文件放到一个像MyProjectHeader中的文件夹中,它会被复制到framework包中。

1.4 禁用Code Striping

点击工程名,build settings,选择"combined",然后更新下面的设置:

  • Dead Code Stripping: No
  • Strip Debug Symbols During Copy: No
  • Strip Style: Non-Global Symbols

2 Framework Target

创建一个新的aggregate target

从菜单栏中添加一个新的target:

  • File
  • New
  • Target
  •         Other
  •         Aggregate

像Jeff一样,我喜欢称它为"Framework"

Add Dependencies

现在点击project,然后编辑"Build Settings",在这里你可以把你的library当作framework的一个依赖项。

现在你会看到它列在了你的工程下面:

构建Framework

现在添加build phase,它将运行脚本来完成编译和文件创建。
在菜单栏上选择:
  • Editor
  • Add Build Phase
  • Add Run Script Build Phase
现在你有两个选择,你可以粘贴脚本内容到XCode工程设置中,或者只是使用它调用你的脚本。我更喜欢后者,因为git可以追踪并整合你的编译脚本就像正常的代码一样。


只要粘贴一个命令到你的脚本中,如果有必要再调整路径。

set -e
${PROJECT_DIR}/${PROJECT_NAME}/Scripts/framework-builder

这是真正神奇的地方,这个脚本处理了所有关键的事情。把脚本内容放到一个叫Scripts/framework-builder的文件中,然后添加到工程中。

关于这个脚本有几点要解释一下:

  • 我使用的ruby,很大程度是因为它在bash中处理的大量复杂的边界情况。然后这可以使用包括中Mac OS X系统中的ruby命令,根本无需依赖包。它应该会起作用。他设置避免了任何可能被安装的ruby版本的管理。
  • 这会重新编译所有target来确保满足所有包括进来的架构。这是一个有点笨拙的解决方案,但是却很管用。
  • 假定$PROJECT\_NAME与你的library和framework的名字一样。如果不是就编辑一下这个脚本。
从github standalone/framework-builder上可以下载这个脚本,或者执行如下命令:
curl https://raw.github.com/csexton/ios-framework-builder/master/standalone/framework-builder > Scripts/framework-builder

如果你对这个处理过程有任何更改,请随意发送pull request,我相信苹果会有一天对其进行改善的。

(注:编译成功之后,那生成的framework包在哪里呢?右击XCode左边的Products组下面的.a文件,然后在Finder中显示,打开以后并没有framework包,它实际上在这个文件夹的上一层,好了,复制好路径,到前往中把它找到吧!)

============翻译完毕,如果有任何不对的地方希望留言指出^_^======================

制作资源Bundle包


写到这还没有结束,因为在我制作的framework包中用到了xib、图片这些资源,这些东西是不能一起放到刚才制作的framework包里的,所以还要把他们一起打包出来一个bundle包,在使用时这个bundle包和framework包一起使用。好了,现在说一下这个bundle包的制作过程吧!

1. 再添加一个target,然后选择Bundle那项,如下:



命名为:Resource。这时在Xcode的左边多了下个组,如下:



为了使我们生成的Resource.bundle里只有需要的资源文件,没有其他的多余项,上面的那些可以完全删除掉。

2. 在Targes中选中Resource,到Build Settings中将Base SDK改为Latest iOS(iOS版本)

3. 还是在Build Settings中到Packaging下将Info.plist File后面的值删掉,否则编译的时候会报找不到.plist文件(因为刚刚到删掉掉了- -)

4. 在Build Phases中将涉及到的xib和图片都放到Copy Bundle Resources中。

5. 再选择Targest的Framework,在Target Dependencies中添加Resouce.bundle,这样在编译Framework时,这个bundle包也会一起被编译的。

6. 现在编译还会出错,之前引用到的图片都多了一层目录,所以所有用的地方都要改一下,例如如下:
NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"MyFrameworkResources" withExtension:@"bundle"]];
    MyViewController *controller = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:bundle];

但是请注意:在IB中对xib上的控件设置的图片并不会收到影响,不用加上这一层路径

7. 选择Framework,然后编译,经过我的测试,选择是模拟器还是Device都是一样的。

8. 找到Framework包和bundle包,一起交给别用去用吧^_^。

有几点要注意的:
  • Resource.bundle一定要放在使用这个资源包的工程下面,否则会找不到资源文件。
  • 我刚才说的是把写好的代码,打包出来一个framework包和bundle包,你在做时最好是直接建一个cocoa touch static library工程,然后再建一个测试的工程,以免文件过多时再打包不好弄。在测试工程中可以直接引用生成的framework,这样在编译完framework后就不用再替换一次测试工程中的framework包了。
  • 如果在framework中用到了category,那么在使用该framework包时要在工程的Build Settings中Linking下的Other Linker Flags设置为-all_load。
  • 尽量在源代码所在的那个目录中只放.m和.h文件,因为这个目录中的所有文件都会被放到framework包中,这样徒增了framework包的大小。
  • 在新建完Cocoa Touch Static Library后,你会发现在Frameworks的组下面少了UIKit.framework,如果你用到了这里面的东西,那在Build Phases中将其添加进来就好。



在这篇文章中作者写的两个category,一个是对NSBundle,一个是对UIImage,用起来很方便:

@interface NSBundle (MyLibrary)
+ (NSBundle*)myLibraryResourcesBundle;
@end

@implementation NSBundle (MyLibrary)

+ (NSBundle*)myLibraryResourcesBundle {
    static dispatch_once_t onceToken;
    static NSBundle *myLibraryResourcesBundle = nil;
    dispatch_once(&onceToken, ^{
        myLibraryResourcesBundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"MyLibraryResources" withExtension:@"bundle"]];
    });
    return myLibraryResourcesBundle;
}

@end

@implementation UIImage (MyLibrary)
+ (UIImage*)myLibraryImageNamed:(NSString*)name;
@end

@implementation UIImage (MyLibrary)

+ (UIImage*)myLibraryImageNamed:(NSString*)name {
    UIImage *imageFromMainBundle = [UIImage imageNamed:name];
    if (imageFromMainBundle) {
        return imageFromMainBundle;
    }

    UIImage *imageFromMyLibraryBundle = [UIImage imageWithContentsOfFile:[[[NSBundle myLibraryResourcesBundle] resourcePath] stringByAppendingPathComponent:name]];
    return imageFromMyLibraryBundle;
}

@end


没有更多推荐了,返回首页