最近前同事问我react-native方面的问题,几年前我粗略地学习过react-native的开发,时至今日,差不多又还回去了。于是就搜索react-native方面的文章看。看到这篇文章,对评论区一个掘友的留言很好奇,这款用react-native开发的仿掘金APP的应用,界面到底长什么样子?文中的作者并没有截屏展示。于是打算把文中的项目下载下来,运行一下,看看效果。过程没有我想得那么顺利,一波三折,踩了一些坑,好在最后跑起来了,在Android Studio模拟器中的运行效果如下图所示。现在我们回溯一个过程,把遇到的问题的解决方法给大家分享一下。
npx react-native init react-native-junjin生成的目录结构如下图所示:
react-native-junjin/
├── __tests__/ // 测试目录,包含测试文件
├── android/ // Android 项目的原生代码
├── ios/ // iOS 项目的原生代码
├── node_modules/ // Node.js 模块目录,包含所有依赖包
├── .eslintrc.js // ESLint 配置文件,用于 JavaScript 代码风格检查
├── .gitignore // Git 忽略文件配置
├── .prettierrc.js // Prettier 配置文件,用于代码格式化
├── .watchmanconfig // Watchman 配置文件,用于监视文件变化
├── App.tsx // 主要的 React 组件文件,使用 TypeScript 编写
├── app.json // 应用的配置文件
├── babel.config.js // Babel 配置文件,用于 JavaScript 转译
├── index.js // JavaScript 入口文件,注册根组件
├── metro.config.js // Metro bundler 配置文件
├── package.json // 项目的包管理配置文件,定义项目依赖及脚本
├── README.md // 项目说明文件
├── yarn.lock // Yarn 锁定文件,确保依赖版本一致
├── .bundle/ // 这个文件夹通常包含打包配置和缓存,用于优化打包过程
├── Gemfile // Ruby 的依赖管理文件,,通常与 CocoaPods 一起使用,以管理 iOS 项目的依赖。
├── jest.config.js // Jest 配置文件,用于测试设置
├── tsconfig.json // TypeScript 配置文件
└── .yarnrc.yml // Yarn 配置文件,定义 Yarn 的行为别的文件都好理解,对于初学者,可能不知道Metro和Gemfile是干什么的。
Metro 是 React Native 项目中开发工具链的重要组成部分。Metro 是 React Native 的 JavaScript 打包器,将所有的 JavaScript 文件打包成一个或多个文件,以便应用程序可以在设备或模拟器上运行。它会解析项目中的依赖关系树,将所有依赖项捆绑在一起,生成一个高效的包。它具有快速增量构建、热重载和代码拆分等功能使得开发过程更加高效和便捷。项目的根目录下有一个 metro.config.js 文件,用于配置 Metro 的行为。这个文件可以包含如下配置:
配置示例:
module.exports={
transformer: {
babelTransformerPath: require.resolve('react-native-typescript-transformer'),
},
resolver: {
sourceExts: ['jsx', 'js', 'ts', 'tsx'], // 支持的文件扩展名
},
};Gemfile 在一个 React Native 项目中,Gemfile 通常用于管理 iOS 开发所需的 RubyGems。RubyGems 是 Ruby 的包管理系统,Gemfile 的主要作用是列出项目所依赖的所有 gems(RubyGems所管理的包或者依赖,我们称之为 gem),并确保在不同环境下这些依赖项的一致性,其中一个比较重要的gem是 CocoaPods,这是一个流行的依赖管理器,用于管理和集成 iOS 项目的第三方库。
一个典型的 Gemfile 文件结构如下:
# 指定 gem 的源,这通常是 `https://rubygems.org`,这是官方的 RubyGems 仓库
source "https://rubygems.org"
# 指定 Ruby 版本
ruby ">=2.6.10"
# 指定项目所需的 gem 及其版本
gem 'cocoapods', '>=1.13', '< 1.15'
gem 'activesupport', '>=6.1.7.5', '< 7.1.0'
# 可以定义不同的组,例如开发环境和测试环境
group :development, :test do
gem "rspec"
end
先介绍一个检测工具react-native doctor ,它是 React Native 开发环境中一个非常有用的命令行工具,能帮助开发者检测和修复本机系统中的各种开发工具和依赖项,确保安装正确且版本合适。会检查 Node.js、yarn, Metro,JDK,Android Studio、Android SDK,Xcode 以及其它相关工具,并提供自动修复问题的选项。如果 doctor 无法自动解决问题,它将显示消息和链接,说明如何手动修复此问题。
执行下面的命令,就会开始检查React Native开发依赖的大多数软件和工具是否正确安装且版本正确
npx react-native doctor这是检查结果,因为笔者已经安装好了各种软件和工具,所以只有一项是打叉的。这一项打叉是因为没有在Android Studio中启动模拟器。
要在PC端运行一下Android应用,如果你是初学者,百分之百会遇到一些跟Android平台相关的专业名词如JDK、Android Studio,Android SDK,Gradle、Gradlew,不知道这些名称概念的含义的话,就算效果运行正确,也不代表你会了。别人对你谈起这些名词,你会感觉一头雾水,不知所以然, 无法与别人交流。所以我们先夯实一下基础,了解一下这些名词概念。
在 React Native 和 Android 开发中,JDK、Android Studio、Android SDK 和 Gradle 是几个核心组件,它们之间相互关联,为开发和构建 Android 应用提供完整的支持。它们各自的功能和彼此的关系如下:
总结一下就是:
它们共同构成了 Android 应用开发和构建的完整工具链,相互依赖且紧密集成。
ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
去Oracle官网,下载win版的jdk安装包 。注意版本jdk版本,doctor提示jdk的版本必须是>=17,<=20, 去官网一看, 只有22,21,17三个版本可以下载,那只能选择jdk17。衍生问题-jdk下载过慢。解决方法: 将下载链接的协议头由https改成http,由于下载时默认是https,所以会慢一些,使用http之后会好很多,速度能稳定在400k左右,十分钟之内就可以下完,速度还可以。另外,配置JAVA_HOME环境变量的时候,路径后面不能带bin。
安装Android Studio时,直接搜索Android Studio下载地址,去官网下载,发现国内用户直接下载不了。访问这个地址,界面的语言默认是英文,却可以正常下载,默认打开的Android Studio页面语言是中文的话,就下载不了。莫非是美国佬不让大陆开发者使用Android Stduio.
安装好Android Studio之后,需要创建一个模拟器。就不会报这个错误了。Android模拟器查看和启动方法
emulator -list-avds
emulator -avd 模拟起名称用 java -version命令查看发现返回为空,是因为安装了两个版本的JDK所致。一个是本次在Android Studio安装中,一个是以前手动安装的。要删除一个。删除jdk时,搜索的应用名称应该是Java,此外,手动删除JDK的安装目录文件,是不行的,必须用系统的软件卸载功能进行卸载。
安装Android Studio时不要自定义安装路径,安装到默认路径。
出现这个报错是因为下载gradle-8.6-all.zip包超时引起的,可以修改一下项目根目录下的 android\gradle\wrapper\gradle-wrapper.properties文件配置,把gradle的下载路径改成本地路径,然后手动下载这个压缩包,放到配置的本地路径中。
distributionUrl=gradle-8.6-all.zip这个错误的意思是在 Gradle 构建过程中,尝试将临时工作空间移动到最终位置时出错,错误原因通常与文件系统权限或路径问题有关。默认配置下载的gradle-8.6-all.zip会报这个错误,将gradle工作包降级为gradle-8.5-bin.zip后,此问题消失。
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip操作菜单路径 File==> Settings==> Languages & Frameworks==>Android SDK==>Edit,如下图所示。
SDK安装目录为:
C:\Users\Administrator\AppData\Local\Android\Sdk如果用pnpm安装会出现这个问题,用yarn安装则不会,因为yarn会安装自动隐式依赖。
Settings file 'D:\juejin-main\android\settings.gradle' line: 2 apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) Could not read script '项目路径\node_modules@react-native-community\cli-platform-android\native_modules.gradle' as it does not exist.
补充安装这两个包
pnpm add -D @react-native-community/cli-platform-android @react-native/gradle-pluginWhat went wrong: A problem occurred configuring project ':react-native-screens'. [CXX1101] NDK at C:\Users\Administrator\AppData\Local\Android\Sdk\ndk.1.10909125 did not have a source.properties file
Android NDK(Native Development Kit)是一个工具集,允许开发者使用 C 和 C++ 代码来构建 Android 应用程序的一部分。NDK 提供了构建和打包原生代码的工具和库,帮助开发者创建高性能的应用程序,尤其是在涉及到计算密集型任务时,如游戏、图形处理和信号处理等。
通过 Android Studio 安装 NDK,操作步骤:
注意下载版本要与报错的NDK版本保持一致。
解决方法:修改项目下的android\build.gradle项目依赖项的像源地址。添加阿里云镜像地址,并配置在前面,优先使用。
buildscript {
// 定义了 Gradle 构建脚本所需的依赖项应该从哪些存储库中获取。常见的存储库有 `google()` 和 `mavenCentral()`。
repositories {
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/jcenter" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/google" }
google()
jcenter()
mavenCentral()
}
// ...
}
allprojects {
// 定义了所有子项目在解析依赖项时使用的存储库
repositories {
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/jcenter" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/google" }
google()
jcenter()
mavenCentral()
}
}
apply plugin: "com.facebook.react.rootproject"没动手实践之前,本以为依葫芦画瓢,能很快把效果做出来。实际在做的时候,发现自己把这件事想得简单了。在运行项目的过程中,出现了许多报错,上面的这些问题我把解决方法都记录下来了,有些也遗漏了。我踩过的坑,希望你看完这篇文章之后,就不要再重蹈覆辙了。这样才能体现出你阅读本文的价值。还有就是看完一篇技术文章,不能看一看就觉得自己会了,最好动手做一做。有许多潜在的技术问题在看的过程中是无法暴露出来的,你以为你会了,实操的时候还是会遇到一大堆问题,平时有时间的话要提前扫雷, 这样将来遇到相关问题时就不会手忙脚乱。
原文:https://juejin.cn/post/7382891974942048282
息的怎样了?是否已经迫不及待的想要继续新的学习了呢?
好吧,接下来我们就做点实际的事情。
添加其它控件
到目前为止,我们的界面上只有以背景和一个按钮,接下来还是添加一些其它界面控件吧。下面是我们所创建的界面的最终效果。
如你所见,我在部分标签处放了一些占位用的数值(比如999)。之所以这样做,是为了方便查看标签实际使用时在界面上的显示效果。玩家的得分可能会非常高(永远不要低估或高估玩家的智商~),因此最好预留足够的空间。
好了,现在该你自己出手了。如果你是个设计人员,相信你会喜欢下面的操作。打开Main.storyboard,尝试从Xcode的对象库拖曳不同的控件放到视图上。也不用那么精确。
实际上,要添加的三种界面元素是Label,Button和Slider。
需要注意的是,在这些标签里面我放了一些占位用的标签(比如999999),这样是为了预留足够多的空间,以便玩家实际体验的时候有足够的发挥空间~
为了调整界面中UI控件元素的设置,我们需要用到所谓的Attributes inspector。我们可以在Xcode的右侧面板中找到该视图,也就是Inspector(检视)视图。
Inspector(检视)视图中会显示所选中的视觉元素的各种属性,其中Attributes inspector可以用来更改表情的背景颜色,或是按钮上的文字大小。另外我们之前曾在Connections inspector视图中检查按钮的动作方法连接。当你逐渐熟悉Interface Builder之后,可能会用到各种Inspector视图。
提示:
1.需要注意的是,类似”i”形状的界面元素其实也是一个Button,只是需要把它的类型设置为Info Light。
2.如何设置滑动条的数值。
选中Slider,切换到Attributes Inspector,把它的最小数值设为1,最大数值设为100,当前数值设为50.
当你完成以上操作后,界面已经有了12个用户界面元素:1个滑动条,3个按钮,还有一堆标签。怎么样,很有成就感吧。
点击Run运行应用,然后好好玩上一会儿。除了之前的按钮,其它控件现在还做不了具体的事情,不过起码你可以拖着滑动条来回玩。
到目前为止,我们已经完成了界面的基本布局,而且不需要写一行代码。如果你是一个设计师,肯定要为此欢呼雀跃。可惜好日子到头了,很快我们就需要使用Swift编写代码让这些控件变得可交互。
乔帮主到目前为止对你的工作还比较满意,暂时没有召唤你去天国猛批一顿的意思。
不过按照他一向的完美标准,你还有很多工作要做。
让滑动条变得可交互
在我们to-do list上的下一个待办项目是:当玩家触碰按钮时读取滑动条上的数值。
如果你在Interface Builder的时候没有故意搞一些麻烦,比如装作不经意间把按钮和showAlert动作的关联取消,那么此时就可以更改代码让应用在弹出警告框中显示滑动条的数值。(如果你的确取消了按钮到动作的关联,那么首先需要再次将其关联起来。)
还记得如何在视图控制器中添加一个动作,从而让它可以识别用户对按钮的触碰吗?对于滑动条我们可以做同样的事情。一旦用户拖曳滑动条的手柄,就会触发这个动作。
要实现这一切,跟之前的操作几乎完全相同。
首先在Xcode中点击ViewController.swift,然后在最后一个花括号前面添加下面的代码:
@IBAction func sliderMoved(_ slider: UISlider){
print("滑动条的当前数值是: \(slider.value)")
}
再次强调:输入代码的时候一定要注意全角和半角的切换,特别是代码中既有中文又有英文的时候,要切记代码一律用半角,要打印或输出的中文(包含标点)才用全角。这个问题是新手开发者甚至是部分老手很容易犯的错误。
注意到此时@IBAction func sliderMoved(slider:UISlider)这行代码的左侧有个空心圆,代表它还没有跟storyboard中的界面元素关联起来。
此时在Xcode中点击Main.storyboard,按住Ctrl键不放,点击鼠标左键从视图中的slider滑动条上拖一条线到对象面板(Outline pane)的View Controller(注意不是View Controller Scene)上,然后从弹出菜单中选择sliderMoved:。
此时如果你通过Xcode右侧的面板切换到Connections inspector,就可以看到sliderMoved:动作和滑动条的Value Changed事件关联在一起。
这就意味着每当滑动条的数值发生变化时(用户拖动滑动条),就会调用sliderMoved()方法。
再次提醒大家,在Interface Builder的canvas左侧,是所谓的Document Outline,其中列出了当前视图中的所有视觉元素。
记住,如果你看不到Document Outline,可以点击Xcode窗口底部的小图标来显示:
现在点击Run运行游戏,然后拖动滑动条看看反应。
一旦你开始拖动,Xcode窗口会在底部打开一个新面板,也就是传说中的Debug Area(调试区),然后显示下面的信息:
如果你把滑动条拖到最左边,会看到上面显示的数值变成1.0,如果拖到最右边,那么显示的数值变成100.0.
print()函数可以帮忙我们了解应用的逻辑是否正常。它的作用就是在Debug调试区显示一条文本信息。这里我们用它来验证滑动条是否和指定的动作关联在一起。在我每次要添加新的功能前,我都会用print()来确保之前一切都OK.
提醒:
你是否注意到sliderMoved:方法的名称后面有一个冒号,而showAlert却没有?这是因为sliderMoved:方法有一个参数slider,而showAlert则没有任何参数。如果某个动作方法有一个参数,那么Interface Builder就会在名称后面添加一个冒号。很快我们就将了解更多关于参数的问题。
科普时间
好了,马上又要到科普时间了。这样免得你太累,不过如果还是那句话,如果你对理论知识无爱,可以跳过去无视。
首先我们来科普几个东西,所谓的iOS开发,App Store,Mac开发,Xcode,Objective-C, Swift,Cocoa, Cocoa Touch究竟是什么关系。
在我初学苹果开发的时候,经常把这些东西搞混,因为早期的各种编程书籍中既有iOS开发,又有Objective-C开发,还有Cocoa 开发。
程序猿最NB之处,同时也是最让人讨厌的地方就是,喜欢用各种术语,各种缩写让你觉得自己是个白痴。虽然我们的目标不是成为最NB的程序猿,但了解一些相关的开发术语没有坏处。
我并不指望你一下子就看懂它们的真正用处和区别,但起码先留下点印象,然后在后面的教程中再逐步熟悉。对于教程中的其它抽象概念,哥也是类似的做法,先简单介绍,然后让你反复接触,直到彻底进入你的盗梦空间。
iOS开发,在2010年推出iPad之前其实就是iPhone开发。所以很多早期的iOS教程都写的是iPhone应用开发。相信大家都知道2007年macworld上帮主的那次惊天地泣鬼神的神级演讲,如果没看过的强烈建议去重温一下,绝对是我心目中商业产品发布演讲中无可争议的第一。
2008年前第三方只允许开发Safari上的网页应用。2008年开始,苹果在当时的SVP Scott Forstall的带领下向开发者正式推出了iPhone SDK,并直接打造了一个完整的生态系统。
2010年帮主发布了耶稣之本iPad,同年的WWDC上将iPhone OS更名为iOS。iOS基于Mac OS X系统开发,但针对移动设备特有的硬件特性做了大量的改善和优化。
如今的iOS开发泛指针对所有安装了iOS操作系统的设备(当然只限苹果生产)开发应用或游戏。主要包括:iPhone全系列,iPod touch全系列,iPad全系列。当然,相信还在用iPod touch的童鞋已经不多了,这又是一条注定会消失在历史中的产品线~
目前除了iOS,还有了针对Apple Watch的Watch OS,还有针对Apple TV的TV OS,不过它们都是基于iOS衍生而来的~
App Store,顾名思义就是苹果卖针对iOS设备上应用和游戏的软件商城。
Mac开发,指的是开发Mac操作系统下的应用和游戏软件。在iOS和App Store取得了巨大的成功后,苹果把iOS的一些成功特性开始反哺给Mac操作系统,同时在2011年推出Mac版的 App Store。
不过目前看来Mac开发并没有吸引足够多的开发者。也没有多少非常成功的案例。
Cocoa和Cocoa Touch上一次的内容中提过,同样是编程环境,一个用于Mac开发,一个用于iOS开发。
Swift和Objective-C属于编程语言,和C,C++,Java,C#,Javascript,PHP,Python,Ruby等相似。
Xcode是Mac 平台下的软件开发环境,可以开发Mac和iOS应用。
如果和其它开发平台做一下对比,可能很多人就明白了。
Xcode类似于Visual Studio或者Eclipse
Swift和Objective-C类似于C,C++,Java,C#这些开发语言,
Cocoa 和Cocoa Touch 类似于微软开发中的MFC或.NET.
Swift/Objective-C和Cocoa/Cocoa Touch的关系类似于C++和MFC,或者C#和.NET的关系。
继续科普-什么是字符串
在刚才的print()那行代码里,我们用到了这样的一个东西,
"滑动条的当前数值是: \(slider.value)"
这就是个字符串,到目前为止我们已经用了好几个类似的东西。比如UIAlertController(提示对话框)里面的就是字符串。
通常来说,这样一连串的文字被成为字符串,因为我们可以把文字看做字母,数字,标点符号的一个序列,就好像用串在一起的珠子。
在我们开发应用的过程中,将会大量使用字符串,所以很快你就会熟悉它的用法。
在Swift里面,为了创建一个字符串,只需要把文字放到双引号里面就好了。这个@符号很重要!如果你之前用其它的编程语言写过代码,或许在生成字符串的时候可以使用双引号或单引号(比如python),但是Swift只能使用双引号。
而且很重要的一点是你必须使用半角输入,不要使用中文输入法的全角双引号。
总结一下:
// 在Swift 中正确使用字符串的方法:
"I am a good string"
// 下面都是错的:
'I should have double quotes'
''Two single quotes do not make a double quote’'
“My quotes are too fancy”
@"I am an Objective-C string"
在print()这行代码里面,用到的字符串是"滑动条的当前数值是: \(slider.value)”
所有在符号 \(…)之间的字符串都是特殊的占位符。
比如下面的这个占位符:"滑动条的当前数值是:: X”,这里的X将被滑动条的数值所替代。
让变量来帮忙
在调试面板中用print()打印信息对于开发和测试非常有用,不过玩家对这种消息可是毫无兴趣。因此让我们来改进一下这个动作方法,让它在一个提示对话框里面显示滑动条的数值。那么我们该如何把滑动条的数值送给showAlert()呢?
当我们在sliderMoved()中读取滑动条的数值时,一旦这个动作方法结束,这个数据信息也就丢失了。我们需要记住这个数据,直到玩家触碰了按钮为止。
幸运的是,Swift(其它语言也是)为我们提供了一个很好的工具-变量。
在Xcode中打开ViewController.swift,在class ViewController这行代码的下面添加一行代码:
var currentValue: Int=0
添加完成后的代码如下:
import UIKit
class ViewController: UIViewController {
var currentValue: Int=0 //定义了一个变量
override func viewDidLoad() {
…
}
override func didReceiveMemoryWarning() {
…
}
@IBAction func showAlert(){
…
}
@IBAction func sliderMoved(slider: UISlider){
…
}
}
注意:上面唯一添加注释的代码是刚刚新添加的代码,其它一切都保持不变。省略号…其实就是之前的代码内容,千万不要以为哥把那些代码都删掉了。如果你不确定的话,最简单的方式就是参考本章的参考项目源代码,对比下就知道了~
现在我们就添加了一个名为currentValue的变量到视图控制器中。变量被添加到方法的上面,通常我们需要让这行代码缩进显示,使用tab键或者用空格键。
至于使用两个空格还是4个空格取决于你的个人习惯,我们可以通过Xcode的偏好设置来设置这一点。在Xcode的顶部菜单中点击Xcode -Preferences..-Text Editing,然后跳转到Indentation选项卡即可。
还记得帮主当年的话吗?由内到外都要美。哪怕是代码的缩进显示这样小的细节,以后也会给你节省很多时间,让你读代码没那么累。更重要的是,真正的美,由内到外。
很多偷懒的程序猿在这方面都过于随意,我毫不奇怪他们的代码里面经常会出现各种bug。这个无关技术,和心态有关。用心做,才能成为食神;用心演,才能成为喜剧之王~
很多事情谈不上需要多高深的技巧,谈不上拼爹和干爹,谈不上苦逼和潜规则,唯用心与否而已。
在之前的教程中曾提过视图控制器,或是任何一个对象都有自己的数据和功能。
showAlert()和sliderMoved()动作就是功能的典型例子,而currentValue变量则是数据的一部分。
通过使用变量,可以让我们的应用拥有记忆。你可以把变量看做是存储某个数据的临时储物箱。正如储物箱有各种类型和尺寸的一样,数据也五花八门。
你不能把东西扔到储物箱里面然后撒手不管,因为经常会放入一些新的东西。当你的应用需要记住一些变化时,就需要把旧的数据拿出来,然后把新的数据放进去。
这就是变量(variable)的本质-变(vary)。比如说,每次玩家拖动滑动条的时候,我们都会使用滑动条的当前位置来更新currentValue。
储物箱的大小和变量可以保存的数值种类由datatype(数据类型)决定。这里我们指定currentValue这个变量的数据类型为Int(也就是integer),意味着储物箱里面可以放入整数(又称为integer),范围在正负20亿之间。Int是最经常用到的数据类型,不过很快我们会接触到其它的类型。
变量就象小孩的玩具积木一样:
我们需要把正确的形状放到正确的储物箱里面。储物箱就是变量,而它的数据类型(datatype)决定了里面能放什么形状的东西。形状就是你可以放入变量的可能数值。
我们可以随后更改每个箱子里面的内容,可以拿出蓝色的方块积木,放进红色的方块积木,但前提是它们都是方块形状的。你不能把方块积木放到一个圆孔里面去:数值的数据类型和变量的数据类型必须是匹配的。
刚才也说了,变量是一个临时的储物箱。既然是临时,那么能保存多久呢?每个变量都有自己的生命周期(或者叫scope,术语狗滚粗),它的生命长短取决于你在程序的哪个位置定义变量。在这里,currentValue的声明和它的拥有者一样长,它的拥有者是ViewController。它们的命运交织在一起。在这里,只要我们不退出应用,这个视图控制器,还有currentValue就会活着。当然,很快我们就会了解到寿命很短的变量。
在程序这样一个虚拟世界中,每个变量,每个视图控制器都是一个虚拟的生命。世界毁了,所有的生命都会消亡。世界没有毁,有的生命也会消亡。这方面似乎可以和人类与宇宙的关系类比。
八卦时间:
刚才在谈到变量的时候,举了个例子,说是’不能把方块积木放到一个圆孔里面去’,英文原文是,you can’t put a square in a round hole
这让我想到了苹果著名的品牌广告Think Different的台词,人跟变量终究还是不同的。
变量不能做到随心所欲不逾矩,而人需要与众不同。
Think Different
Here's to the crazy ones.献给狂放不羁的一群人
The misfits. 他们是:不和主流的怪才
The rebels. 叛逆传统的勇士
The troublemakers. 制造麻烦的一小撮
The round pegs in the square holes. 方凿圆枘、特立独行
The ones who see things differently. 他们观察问题与众不同
They are not fond of rules. 他们不喜欢条条框框
And they have no respect for the status quo. 更不把正统放在眼里
You can quote them, 你可以引用他们,
disagree with them, 也可以否决他们,
glorify or vilify them. 赞扬或是诋毁他们
About the only thing you can't do, 但只有一件事你不能做
is ignore them. 那就是漠视他们
Because they change things. 因为他们改变了事物
They push the human race forward. 他们推动了人类的进程
And while some see them as the crazy ones, 虽然有些人把他们当作疯子
We see genius. 但我们看见的却是天才
Because the people who are crazy enough to think 因为只有那些足够疯狂认为
they can change the world, 可以改变世界的人
Are the ones who do. 才能真正做到这一点
本人联系方式:
微信:iseedo
邮件:eseedo@gmail.com
QQ讨论群: 375143733
示例项目:eseedo/iOSCourse
如有疑问,请先发送邮件到我的邮箱:eseedo@gmail.com
我会在收到邮件后尽早答复。
也可以加微信,但可能不是很合适的答疑途径。
另外,为了节省大家的宝贵时间,提高沟通效率,请在提问的时候尽量附上项目源代码以及以下信息:
1.开发环境(系统版本,Xcode和iOS版本)
2.问题描述及重现(想实现什么效果,结果是怎样的,具体涉及到什么操作)
3.为解决问题所做的努力(做了哪些尝试,分别是怎样的结果)
迎继续我们的iPhone开发学习,接下来的内容应该是产品和设计人员的最爱-美化界面。
为了让玩家得到更好的沉浸体验,我们必须让产品的外在和内在一样美,甚至更美。
在这部分的内容中,我们将完成三个小的任务:
1.继续优化横屏显示
2.使用定制化的UI替代系统默认的界面
3.添加一个关于界面,来介绍这款应用~
在本篇内容中,我们首先完成第一个小任务- 优化横屏显示。
还记得我们的to-do list(待办事务清单)吗?里面有一条是“让应用在横屏模式下运行“。我们已经完成了这一任务,不过还可以进一步的优化。
在横屏状态下运行的应用不会显示IPhone的状态栏,除非我们强制显示。这一点会给我们的应用带来更多的展示空间,这当然是好事。
不过即便系统会自动隐藏状态栏,但我们仍然可以改进这款游戏处理状态栏的方式。
在Xcode中点击TARGETS下面的BullsEye,并在General设置的Deployment Info中找到Status Bar Style,然后勾选Hide status bar。
当应用运行时隐藏状态栏是比较恰当的做法。操作系统需要花上一会儿将应用加载到内存中并将其启动,在这段时间里状态栏会保持可见,除非我们通过这个选项将其隐藏。
虽然这只是一个很小的可能不为人所注意的细节,不过真正伟大的应用和平庸之作的区别就在于这些细节。
好了,搞定了。
点击Run跑一下,会看到游戏界面的状态栏已经消失了。
接下来是科普时间,如果你是新手,很可能会看不懂。你可以选择现在来攻坚,也可以选择等以后熟悉iOS开发了再深入去了解。
科普:关于Info.plist文件
在任何一个iOS应用或游戏中,如同AppDelegate类一样,都有一个以项目名称开头的Info.plist文件,比如这里的Info.plist文件。
Info.plist是每个iOS应用都会有的配置文件,比如设备的朝向、状态栏是否在启动时可见等等,这些信息其实都保存在Info.plist文件中。
在之前的Xcode版本中,我们经常需要手动来编辑Info.plist文件。不过从Xcode之后基本上不需要这么做了,我们可以直接从刚才的Project Setting界面上完成。
不过了解下Info.plist的作用倒也没有什么坏处。
在Project navigator中找到Info.plist,点击并查看其中的内容:
它的内容通常由三列组成,最左边是Information Property List(属性列表),中间是Type(属性值的类型),而最右边则是Value(属性值)。
Info.plist文件其实是一个XML文档。XML其实就是可扩展性标记语言(extensible markup language),它并非iOS中所特有的,在几乎任何一种编程语言的使用过程中,我们都会碰到XML文档。XML是所谓标准通用标记语言(SGML)的子集,其作用是以规范的形式(成对出现的标记)来保存数据。XML与传统的Access,Oracle,SQL Server, MySQL数据库不同。传统的数据库功能强大,提供了强大的数据存储和分析能力,而XML仅仅用来存储数据,需要自行编写代码来进行数据的分析和处理。但XML的好处是它超级简单易用,可以在任何语言编写的任何应用程序中读写数据,已经成了网络数据交互的唯一公共语言。
你可能不知道XML文档,但或许多半听说过HTML文档吧。XML文档只不过是HTML文档的规范式表达。它们的区别在于,XML的核心是数据内容本身,而HTML的核心是如何显示数据。
plist文件的本质就是XML文档,只不过其中的内容都和iOS应用的相关设置有关。
在Xcode中右键单击Info.plist,选中open as,选中source code,就可以看到下面的内容:
很显然,plist文档其实就是满足苹果DTD标准的XML文档。
那么,Info.plist文件中这些键值的作用是什么呢?
这里大概说明一下,更详细的可以参考苹果的官方文档( https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html )
Localization native development region --- 本地化相关,如果用户所在地没有相应的语言资源,则用这个key的value来作为默认.
Executable file -- 程序安装包的名称
Bundle identifier --- 该束的唯一标识字符串,该字符串的格式类似com.yourcompany.yourapp,如果使用模拟器跑你的应用,这个字段没有用处,如果你需要把你的应用部署到设备上,你必须生成一个证书,而在生成证书的时候,在apple的网站上需要增加相应的app IDs.这里有一个字段Bundle identifier,如果这个Bundle identifier是一个完整字符串,那么文件中的这个字段必须和后者完全相同,如果app IDs中的字段含有通配符*,那么文件中的字符串必须符合后者的描述。
设置程序安装后显示的名称。应用程序名称限制在10-12个字符,如果超出,将被显示缩写名称。
InfoDictionary Version- Info.plist格式的版本信息
Bundle name-产品名称
Bundle OS Type code-用来标识束类型的四个字母长的代码,
Bundle version string, short- 面向用户市场的束的版本字符串
Bundle version-应用程序版本号,每次部署应用程序的一个新版本时,将会增加这个编号,在app store上用的。
Application requires iPhone environment-用于指示程序包是否只能运行在iPhone OS 系统上。Xcode自动加入这个键,并将它的值设置为true。您不应该改变这个键的值。
Launch screen interface file base name -启动界面的文件名称
Main storyboard file base name- 一个字符串,指定应用的主storyboard文件名称
Required device capabilities-跟设备相关的属性设置
Status bar is initially hidden-这个字符串的作用应该很清楚了,就是刚才是否隐藏状态栏
Supported interface orientations- 程序默认支持的方向。
Supported interface orientations(iPad)- 程序默认支持的方向(iPad)。
好了,又见福利时间。
本人联系方式:
微信:iseedo
邮件:eseedo@gmail.com
QQ讨论群: 375143733
不喜欢QQ的童鞋可以加微信,然后进群。
*请认真填写需求信息,我们会在24小时内与您取得联系。