UIKit框架(三十四) —— Accessibility的使用(一)

版本记录

版本号 时间
V1.0 2020.02.17 星期一

前言

iOS中有关视图控件用户能看到的都在UIKit框架里面,用户交互也是通过UIKit进行的。感兴趣的参考上面几篇文章。
1. UIKit框架(一) —— UIKit动力学和移动效果(一)
2. UIKit框架(二) —— UIKit动力学和移动效果(二)
3. UIKit框架(三) —— UICollectionViewCell的扩张效果的实现(一)
4. UIKit框架(四) —— UICollectionViewCell的扩张效果的实现(二)
5. UIKit框架(五) —— 自定义控件:可重复使用的滑块(一)
6. UIKit框架(六) —— 自定义控件:可重复使用的滑块(二)
7. UIKit框架(七) —— 动态尺寸UITableViewCell的实现(一)
8. UIKit框架(八) —— 动态尺寸UITableViewCell的实现(二)
9. UIKit框架(九) —— UICollectionView的数据异步预加载(一)
10. UIKit框架(十) —— UICollectionView的数据异步预加载(二)
11. UIKit框架(十一) —— UICollectionView的重用、选择和重排序(一)
12. UIKit框架(十二) —— UICollectionView的重用、选择和重排序(二)
13. UIKit框架(十三) —— 如何创建自己的侧滑式面板导航(一)
14. UIKit框架(十四) —— 如何创建自己的侧滑式面板导航(二)
15. UIKit框架(十五) —— 基于自定义UICollectionViewLayout布局的简单示例(一)
16. UIKit框架(十六) —— 基于自定义UICollectionViewLayout布局的简单示例(二)
17. UIKit框架(十七) —— 基于自定义UICollectionViewLayout布局的简单示例(三)
18. UIKit框架(十八) —— 基于CALayer属性的一种3D边栏动画的实现(一)
19. UIKit框架(十九) —— 基于CALayer属性的一种3D边栏动画的实现(二)
20. UIKit框架(二十) —— 基于UILabel跑马灯类似效果的实现(一)
21. UIKit框架(二十一) —— UIStackView的使用(一)
22. UIKit框架(二十二) —— 基于UIPresentationController的自定义viewController的转场和展示(一)
23. UIKit框架(二十三) —— 基于UIPresentationController的自定义viewController的转场和展示(二)
24. UIKit框架(二十四) —— 基于UICollectionViews和Drag-Drop在两个APP间的使用示例 (一)
25. UIKit框架(二十五) —— 基于UICollectionViews和Drag-Drop在两个APP间的使用示例 (二)
26. UIKit框架(二十六) —— UICollectionView的自定义布局 (一)
27. UIKit框架(二十七) —— UICollectionView的自定义布局 (二)
28. UIKit框架(二十八) —— 一个UISplitViewController的简单实用示例 (一)
29. UIKit框架(二十九) —— 一个UISplitViewController的简单实用示例 (二)
30. UIKit框架(三十) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的简单示例(一)
31. UIKit框架(三十一) —— 基于UICollectionViewCompositionalLayout API的UICollectionViews布局的简单示例(二)
32. UIKit框架(三十二) —— 替换Peek and Pop交互的基于iOS13的Context Menus(一)
33. UIKit框架(三十三) —— 替换Peek and Pop交互的基于iOS13的Context Menus(二)

开始

首先看下写作内容

在此iOS accessibility教程中,学习如何使用VoiceOverAccessibility inspector使应用程序更易于访问

接着看一下写作环境

Swift 5, iOS 13, Xcode 11

各行各业,各个年龄段,背景不同的人都在使用智能手机应用程序,其中包括残疾人。 在设计应用时要考虑可访问性,以帮助所有人(包括视力,运动,学习或听力障碍者)使用它们。

在本iOS accessibility教程中,您将转换现有的应用程序,以使视力障碍人士更容易使用它。 在此过程中,您将学习如何:

  • 使用VoiceOver
  • 使用Accessibility Inspector检查您的应用。
  • 使用UIKit实现可访问性元素。
  • 为残疾人建立更好的用户体验。

本教程需要Xcode 11.3Swift 5.1。 假定您已经了解Swift开发的基础知识。

注意:您需要使用物理设备才能使用VoiceOver。 目前模拟器中不支持此accessibility功能。

在本教程中,您将使用一个已经完成的名为Recipe的应用程序,其中包含食谱及其难度级别的列表。 它还可以让您评估自己制作的菜肴的质量。

在开始文件夹中打开Recipe.xcodeproj

您需要先配置签名,然后才能在设备上运行该应用程序。

为此,请在导航器中单击Recipe项目,然后选择具有相同名称的目标。 选择Signing & Capabilities标签,然后确保已在顶部选择Debug。 最后,从下拉列表中选择您的团队。


Getting to Know the Recipe App

现在,构建并运行该应用程序以熟悉其功能。

根控制器是配方的表格视图,其中包含图像,说明和难度等级。 点击某个食谱,查看包含食谱的成分和说明的大图。

为了使事情变得更加令人兴奋,您还可以划掉列表中的项目,以确保您拥有所有必需的成分。 如果您喜欢或讨厌自己的作品,则可以切换喜欢/不喜欢的表情符号。


Behind the Scenes of the Recipe App

花几分钟来熟悉一下begin项目中的代码。以下是一些要点:

  • Main.storyboard包含该应用程序的所有storyboard scenes。您会注意到所有UI组件都是标准的UIKit控件和视图。它们已经可以访问,这使您的工作更加轻松。
  • RecipeListViewController.swift管理根表视图,该视图显示所有可用配方的列表。它使用一个Recipe对象数组作为数据源。
  • Recipe.swift是代表配方的模型对象。它包含用于加载一系列食谱的实用程序方法,您将在整个应用程序中使用该食谱。
  • RecipeCell.swift是根控制器的配方列表的单元格。它根据传递的“配方” Recipe模型对象显示配方的难度级别,名称和照片。
  • RecipeInstructionViewController.swift包含详细视图的控制器代码,该代码显示了菜肴的大图及其成分和烹饪说明。它具有一个UISegmentedControl,可在表格视图中的成分和指令之间切换,该表格视图使用InstructionViewModel
  • InstructionViewModel.swift用作RecipeInstructionsViewController的数据源。它包括成分和说明的描述以及复选框的状态信息。
  • InstructionCell.swift定义一个单元格,该单元格包含一个标签和一个复选框,用于说明和成分列表。选中该框时,它会划掉文本。

现在,您已经了解了该应用程序的工作原理,是时候考虑如何使其更易于使用了。


Why Accessibility?

在开始使用代码之前,了解可访问性accessibility的好处很重要。

  • 设计应用程序的可访问性,无论您使用的是KIF框架还是Xcode中的UI Testing,都使编写功能测试变得更加容易。
  • 您还可以通过使更多人使用您的应用来扩大您的市场和用户基础。
  • 如果您在任何政府机构工作,都必须遵守 508 compliance,该法规规定所有用户都必须可以使用任何件或技术。
  • 在您的应用中实现可访问性表明您愿意为每个用户加倍努力,这是一件好事。
  • 很高兴知道您正在为某人的生活带来微小但明显的改变!

说服了吗?然后是时候了解VoiceOver,这是一种针对视障人士的辅助功能工具。


Enabling VoiceOver

iOS随附VoiceOver屏幕阅读工具,该工具可帮助用户与软件进行交互而无需查看屏幕。 专为视力障碍人士设计。

VoiceOver可以使视障用户听到并与屏幕上可见的内容进行互动。 VoiceOver会响应手势,并以声音方式向用户传达屏幕上的内容或用户选择的内容。 本质上,VoiceOver是UI和用户的触摸输入之间的链接。

使用VoiceOver的最快方法是打开iOS设备上的Settings应用程序,选择Accessibility ▸ Accessibility Shortcut ,然后选择VoiceOver

这会创建一个快捷方式,因此您可以在物理设备上点按主屏幕按钮(或用于较新手机的侧面按钮),以打开或关闭VoiceOver

注意:除了VoiceOver之外,还有许多其他辅助功能,包括“反转颜色”,“增加对比度”,“彩色滤镜”,“减少白点”,“缩放”,“切换控制”(Invert Colors, Increase Contrast, Color Filters, Reduce White Point, Zoom, Switch Control )等等。 在本教程中,您将主要关注VoiceOver

现在,您启用了VoiceOver,现在该尝试一下了。


How to Use VoiceOver

VoiceOver带有一些方便的手势预设,可以轻松浏览应用程序。 以下是与VoiceOver一起使用的一些更常见的应用内手势:

  • 轻按一下屏幕上的任意位置,VoiceOver将大声读取该项目的辅助功能属性中的识别信息。
  • 左右滑动一次,VoiceOver将选择下一个可见的辅助功能项目并大声读出。 右挥杆向前和向下移动,而左挥杆则相反。
  • 一次轻扫即可逐字母拼写重点项目。
  • 双击选择重点项目。
  • 左右滑动三指可在页面视图中向前或向后导航。

有关VoiceOver手势的完整列表,请查看Apple在iPhone上的Learn VoiceOver手势 - Apple’s Learn VoiceOver gestures on iPhone。 因此,现在您知道VoiceOver的工作原理了-但是您的应用程序如何运行呢? 您将在下一步中对其进行测试。


Trying VoiceOver With the Recipe App

在物理设备上构建并运行,然后三次单击home按钮以打开VoiceOver。 左右滑动可浏览食谱列表。 VoiceOver从左上到右下读取元素。 它以标题名称开头,后跟每个配方的名称以及相关图像的名称。

但是VoiceOver体验存在一些问题:

  • 1) 图像不是每个单元格中图像视图的有用描述。 您知道其中有图像,但不知道那是什么。
  • 2) VoiceOver并没有说明每种食谱的难度级别,从而使该功能对视力障碍者无效。

现在,您已经确定了问题区域,您可能想直接解决这些问题。 但是在您这样做之前,您需要了解一些有关辅助功能的工作原理。


Accessibility Attributes

Accessibility attributes是您必须实现以支持可访问性的核心组件。 这些属性为VoiceOver提供有关应用程序中元素的信息,因此VoiceOver可以将这些信息大声读出给用户。 如果未正确配置它们,则VoiceOver将无法提供有关您的应用程序的必要详细信息。

Accessibility attributes具有五个属性:

  • 1) Label:标识控件或视图的简洁方法。 例如返回按钮和配方图像。
  • 2) Traits:这些特性描述元素的状态,行为或用法。 例如,可能选择了一个按钮特征。
  • 3) Hint:描述元素完成的操作。 例如:显示配方详细信息。
  • 4) Frame:屏幕内元素的frame,格式为CGRectVoiceOver会说出CGRect的内容。
  • 5) Value:元素的值。 例如,使用进度条或滑块,当前值可能显示为:100中的5。

大多数UIKit组件都为您预置了这些属性。 您只需要提供详细信息即可改善用户体验。 如果创建自定义控件,则必须自己提供大多数属性。

因此,现在您知道VoiceOver在何处获取向用户提供的信息,是时候了解一种新工具,该工具将帮助您查找和修复应用程序中的accessibility weaknesses:Accessibility Inspector


Using the Accessibility Inspector

如果您要对某个应用进行改造以使其更易于访问,则发现weaknesses既耗时又容易出错。 幸运的是,有一个名为Accessibility Inspector的工具可以执行以下操作:

  • 在您的应用中运行,并发现常见的可访问性问题。
  • 使您可以在Inspection Mode下检查UI元素的可访问性属性。
  • 在不离开应用程序的情况下提供可访问性元素的实时预览。
  • 支持所有平台,包括macOS,iOS,watchOStvOS

Recipes上使用Accessibility Inspector之前,请先查看一下该工具。 首先,通过导航至Xcode ▸ Open Developer Tool ▸ Accessibility Inspector,在Xcode菜单中将其打开。

inspector应如下所示:

target chooser使您可以选择要检查的设备。 这可能是您的MacBook Pro,iOS设备或模拟器。

accessibility elements的实时预览可让您在模拟器中进行测试。 由于实时预览比收听VoiceOver更快,因此在本iOS辅助功能教程中,您将在此处完成大部分工作。

在模拟器中构建并运行,然后将Accessibility Inspector目标更改为模拟器:

现在您已经打开了该工具,现在可以查看它的一些最有用的功能。


Using the Inspection Pointer

注意:在撰写本文时,最新版本的Xcode 11.3有一个bug,使您无法可靠地使用此工具。

选择Inspection Pointer,在检查器UI中看起来像是标线瞄准器,类似于在设备上启用VoiceOver。 激活指针时,可以将鼠标悬停在任何UI元素上以检查其属性。 通过按钮直接与模拟器交互将禁用检查指针。

Inspection Detail窗格包含您需要查看并与应用程序中的accessibility attributes进行交互的所有内容:

  • Basic:显示当前突出显示的元素的属性。
  • Actions:使您可以执行诸如点击按钮或滚动视图之类的动作。 按此窗格中的Perform按钮将对目标执行操作。
  • Element:显示当前项目的类,地址和控制器。 在撰写本文时,它不能始终如一地工作。
  • Hierarchy:显示元素的视图层次结构,使您更容易理解复杂的视图。

Using Quicklook to Check Audio in Xcode

Xcode 11Inspection Detail窗格顶部的Quicklook部分中具有一项新功能,可让您在Xcode中模拟您在设备上听到的音频。 这意味着您可以在不使用实际设备的情况下检查用户在使用应用程序时听到的声音。

当应用程序在模拟器中运行时,按播放Play按钮,让Accessibility Inspector循环浏览该应用程序,并大声聆听它描述每个元素的过程。

如果您希望手动浏览每个元素,则可以按“暂停”按钮或按Quicklook部分中的Audio按钮。 按“前进”或“后退”按钮以您自己的步调逐步浏览每个组件。

使用此功能比在设备上运行应用程序和使用VoiceOver更快,尤其是在开发过程中。 与往常一样,您还希望在真实设备上测试您的应用及其所有辅助功能。


Highlighting Problems With the Inspector Audit

Inspector Audit最有用的功能之一是它的audit capability,该功能会向您发出有关应用程序内可访问性问题的警告。 要试用此功能,请确保模拟器仍在运行,并且您在配方列表中。 在检查器中,单击Audit icon,然后单击Run audit

您会看到检查器给出几个警告,包括您的某些元素缺乏描述。

单击警告时,Xcode会突出显示模拟器中以及Inspector Audit屏幕底部的相关元素。

在这种情况下,与单元格关联的图像视图没有描述。 这意味着VoiceOver无法将其描述给您的读者。

单击Suggest Fixes图标(看起来像一个问号,圈出一个警告),inspector将提供有关解决问题的建议。 您稍后将根据这些建议采取行动。

单击Eye图标拍摄该应用程序的快照。 这对于需要创建准确的错误报告的质量保证人员很有用。

您可以在检查器中找到一些有用的accessibility settings。 接下来,您将快速浏览这些功能。


Additional Inspector Settings

尽管它们不在本教程的讨论范围之内,但是很高兴知道Accessibility Inspector还可以让您测试以下辅助功能设置:

  • 1) 反转颜色
  • 2) 增加对比度
  • 3) 降低透明度
  • 4) 减少运动
  • 5) 更改字体大小

您不再需要使用Settings应用来启用这些功能。 Accessibility Inspector当前仅提供这五个选项,但是Apple计划在将来添加更多选项。

Accessibility Inspector可以节省测试应用程序的时间。 但是请记住,您仍然应该手动测试VoiceOver,以尝试实际的用户体验。 最后一步可帮助您发现inspector遗漏的任何问题。

现在,您已经浏览了Accessibility Inspector的功能,是时候开始使用您的应用了。


Making the Recipe App Accessible

使用VoiceOver在设备上测试应用程序时,您注意到图像的描述不是很有用。 audit tool向您显示了原因:图像视图没有可访问性标签。 您现在要解决此问题。

在Xcode中,打开RecipeCell.swift并将以下代码添加到文件的底部:

// MARK: Accessibility

extension RecipeCell {
  func applyAccessibility(_ recipe: Recipe) {
    // 1
    foodImageView.accessibilityTraits = .image
    // 2
    foodImageView.accessibilityLabel = recipe.photoDescription
  }
}

此代码根据单元格的Recipe对象填充缺少的可访问性属性。 运作方式如下:

  • 1) accessibilityTraits掩盖了表征可访问性元素的特征。 在这种情况下,.image表示它是图像。
  • 2) 您可以使用accessibilityLabel来描述VoiceOver中的元素。 在这里,将其设置为recipe.photoDescription,它是描述图像内容的字符串。

现在,您也想将其应用于将来的配方。 在RecipeCell类中找到configureCell(_ :)。 将以下行添加到方法的末尾:

applyAccessibility(recipe)

每次创建单元格时,此代码都会使用配方对象中的属性将可accessibility attributes应用于图像。

在设备上构建并运行,然后在主屏幕按钮上轻按三下即可启用VoiceOver。 测试食谱列表,以查看图像描述是否更有意义。

好多了! 现在,您不仅可以听到未提供具体细节的Image,还可以听到图像的完整说明。 用户现在可以可视化食物,而不必因不知道图像是什么而感到沮丧。

在应用程序仍在模拟器中运行的情况下,再次运行Accessibility Inspector并导航到配方列表。 确保清除检查器中的所有警告,然后点击Run Audit

WOOt - 没有更多的描述警告! 将说明成功添加到图像后,现在可以完全访问此视图的核心。

现在,该使食谱的难度级别变得可访问了。


Transforming the Difficulty Labels

Accessibility Inspector中,您会看到potentially inaccessible text警告,该警告告诉您视觉障碍用户看不到难度标签。 要解决这些问题,您需要使标签可访问并使用有意义的描述更新其属性。

对于下一步,请转到RecipeCell.swift并将以下内容添加到applyAccessibility(_ :)的末尾:

// 1
difficultyLabel.isAccessibilityElement = true
// 2
difficultyLabel.accessibilityTraits = .none
// 3
difficultyLabel.accessibilityLabel = "Difficulty Level"
// 4
switch recipe.difficulty {
case .unknown:
  difficultyLabel.accessibilityValue = "Unknown"
case .rating(let value):
  difficultyLabel.accessibilityValue = "\(value)"
}

以下是有关此代码功能的更多详细信息:

  • 1) isAccessibilityElement是一个标志,使该标志为true时对辅助功能可见。 对于大多数UIKit类,默认值为true,但对于UILabel,则为false
  • 2) accessibilityTraits帮助表征可访问性元素。 由于不需要任何交互,因此将其设置为没有特征。
  • 3) 接下来,让VoiceOver简洁地标识该标签的意图。 Difficulty Level可让用户确切地知道他们正在处理什么。
  • 4) VoiceOver将读取accessibilityValue作为标签说明的一部分。 在此处设置难度级别会使此元素更加有用。

在物理设备上构建并运行您的应用,请三按主屏幕按钮以启用VoiceOver并在配方列表中滑动。

滚动浏览不同的辅助功能元素时,VoiceOver会读取每个单元的完整说明,包括难度级别。


Checking for Warnings

每次您公开一个新的辅助功能元素时,就像在此处对难度级别所做的那样,您应该再次运行audit

如果Accessibility Inspector尚未运行,请启动它。 在您的设备或模拟器上运行该应用,并相应地设置检查器目标。 现在,选择audit切换按钮,然后点击Run audit

较少的警告出现! 其余的是关于标签不支持动态文本的。 接下来,您将对其进行修复。


Making the Text Dynamic

auditor警告您,您缺少使所有人都能使用您的应用程序的重要步骤:动态文本。 这是可访问性的一项重要功能,它允许具有部分视力障碍的用户增加字体大小以提高可读性。 您的应用当前使用的非动态字体不允许这样做。

单击Fix Suggestions图标以查看auditor的建议:

它告诉您使用UIfont首选字体,并将adjustsFontForContentSizeCategory设置为true。 您现在就要做。

RecipeCell.swift中,在最底部的applyAccessibility(_ :)内添加以下代码:

dishNameLabel.font = .preferredFont(forTextStyle: .body)
dishNameLabel.adjustsFontForContentSizeCategory = true

difficultyLabel.font = .preferredFont(forTextStyle: .body)
difficultyLabel.adjustsFontForContentSizeCategory = true

这会将preferredFont设置为body样式,这意味着iOS将像文档主体一样设置文本样式。 大小和字体的细节取决于辅助功能设置。 AdjustsFontForContentSizeCategory指示当用户更改文本内容大小时字体应自动更新。

借助Accessibility Inspector,测试应用程序如何处理字体大小调整变得非常容易。

Accessibility Inspector一起构建并运行配方应用程序。 再次运行audit,所有警告都将消失。


Testing Some Other Options

导航到检查器中的Settings开关,并尝试一些工具:

  • 1) 反转颜色可使用此辅助功能预览界面的外观。 这对有光敏感,视力不好以及某些情况下色盲的人有用。
  • 2) 您也可以为喜欢较大字体大小的用户实时测试动态字体大小变化。

在测试应用程序时,它可能看起来像这样:

inspector使测试可访问性案例变得容易。 由此,您可以说出食谱列表将对视力障碍的用户有效。


Transforming the Recipe Detail Screen

现在,您已经完成了食谱选项的列表,现在您想看看当用户单击其中一个食谱时会发生什么。 在您的设备上运行该应用,启用VoiceOver并查看详细视图。 听起来像这样:

详细视图中的VoiceOver交互存在一些问题:

  • 1) 左箭头按钮不是导航的理想说明。 用户如何知道按钮的作用?
  • 2) 表情符号的面孔状态为:心脏形状的眼睛和混杂的面孔。 这些解释会使任何用户感到困惑!
  • 3) 当用户选中一个复选框时,它的图标显示为icon empty

在每种情况下,重要的是要解释控制状态的含义,而不是其外观。 Back button按钮比Left Arrow button按钮清晰。 LikeDislike简要解释表情符号。 接下来,您将进行这两项更改。

要更改导航,请打开RecipeInstructionsViewController.swift并在assert(recipe!= nil)之后将以下内容添加到viewDidLoad中:

backButton.accessibilityLabel = "back"
backButton.accessibilityTraits = .button

VoiceOver现在会显示Back button按钮,而不是Left Arrow button按钮。

现在,进入表情符号。 在同一文件中,将isLikedFood(_ :)的内容替换为以下内容:

if liked {
  likeButton.setTitle("😍", for: .normal)
  likeButton.accessibilityLabel = "Like"
  likeButton.accessibilityTraits = .button
  didLikeFood = true
} else {
  likeButton.setTitle("😖", for: .normal)
  likeButton.accessibilityLabel = "Dislike"
  likeButton.accessibilityTraits = .button
  didLikeFood = false
}

对于LikeDislike模式,您都添加了一个accessibilityLabel,该按钮清楚说明了按钮的功能。 您还设置了accessibilityTraits以将其标识为按钮,以便用户知道如何与之交互。

在设备上构建并运行,然后启用VoiceOver。 使用VoiceOver导航到详细配方屏幕,以测试对视图顶部按钮的更改。

现在,每个功能都有清晰的简短说明,可帮助用户了解其意图。 好多了!


Improving the Checkboxes

最终问题是清单。 对于每个复选框,VoiceOver当前都将图标说明为空,后跟配方说明。 根本不清楚!

要更改此设置,请打开InstructionCell.swift并查找shouldStrikeThroughText(_ :)。 将整个if strikeThrough语句替换为以下内容:

// 1
checkmarkButton.isAccessibilityElement = false

if strikeThrough {
  // 2
  descriptionLabel.accessibilityLabel = "Completed: \(text)"
  attributeString.addAttribute(
    NSAttributedString.Key.strikethroughStyle, 
    value: 2, 
    range: NSRange(text.startIndex..., in: text))
} else {
  // 3
  descriptionLabel.accessibilityLabel = "Uncompleted: \(text)"
}

此代码的作用如下:

  • 1) 关闭对勾标记按钮的可访问性,因此VoiceOver会将其作为一个单元而不是两个不同的可访问性元素进行读取。
  • 2) 现在,用于描述的accessibilityLabel使用硬编码的字符串Completed,后跟文本。 只需访问标签即可提供所有必要的信息。
  • 3) 与完成的代码一样,如果用户将某项标记为未完成,则在标签描述之前添加“未完成”。

再次构建并运行该应用程序,并查看其声音。 它将成为用户耳中的音乐。

在此iOS accessibility教程中,您了解了VoiceOver。 您通过滚动浏览每个可访问元素并亲自测试用户体验来执行手动审核。 然后,您使用了Accessibility Inspector进行审核,查看可访问性元素值并进行实时动态更改以反转颜色或更改字体大小。

现在,您有了必要的工具,可以使您的应用程序更易于访问。 知道您将对某人的生活产生积极的影响是有益的。

后记

本篇主要讲述了Accessibility的使用,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 在iOS中框架是一个目录,包含了共享资源库,用于访问该资源库中储存的代码的头文件,以及图像、声音文件等其他资源。共...
    ch123阅读 1,764评论 0 1
  • 版本记录 前言 iOS中有关视图控件用户能看到的都在UIKit框架里面,用户交互也是通过UIKit进行的。感兴趣的...
    刀客传奇阅读 1,994评论 0 3
  • 介绍 1.开启voiceOver 设置->通用->辅助功能->VoiceOver 在voiceOver模式中 a....
    linatan阅读 6,036评论 0 8
  • 6转载-->>IOS框架和服务 在iOS中框架是一个目录,包含了共享资源库,用于访问该资源库中储存的代码的头文件,...
    李小六_阅读 3,598评论 2 24
  • 草长莺飞 柳琴呜咽 沈园白絮吹尽 陆游错错错 唐婉暪暪暪 落笔的休书 承载生生世世的相思 世间万般皆下品 唯有爱情...
    红秋池阅读 214评论 0 0