游戏发行技术- iOS客户端-第二节:OC语言讲解

Objective-C 编程语言简介

Objective-C 关键特点

面向对象:支持类和对象的概念。

C语言的超集:与C语言兼容,任何有效的C程序也是有效的Objective-C程序。

动态运行时:具有动态运行时特性,可以在运行时动态地绑定方法调用。

消息传递:使用消息传递机制来实现对象之间的通信。

类别(Categories):允许向现有类添加新的方法,无需修改类的源代码。

协议(Protocols):类似于接口,定义了对象必须实现的方法。

内存管理

早期版本使用引用计数,需要手动管理内存。

较新版本支持自动引用计数(ARC),简化内存管理。

Foundation框架:提供基本的类和工具,用于数据类型、集合、文件处理等。

Cocoa/Cocoa Touch框架:为macOS和iOS开发提供丰富的用户界面组件和数据管理功能。

脚本支持:可以作为脚本语言使用,执行自动化任务。

编译器和工具链:通常使用苹果的Clang编译器进行编译,集成在Xcode中。

桥接头文件(Bridging Header):在Objective-C和Swift混合编程中,用于暴露Objective-C代码给Swift。

互操作性:与Swift代码无缝集成。

开源:许多实现随着OpenStep的源代码公开而开源。

历史:最初由Brad Cox和Tom Love在1980年代早期开发。

基本语法和数据类型

在 iOS 开发中,基本语法和数据类型是构建应用程序的基础。以下是一些重要的数据类型和相关概念:

基本数据类型

整型(Integers)

在 Objective-C 中,常用的整型包括 int、long、short 等。

为了与 32 位和 64 位架构兼容,iOS 开发通常使用 NSInteger 和 NSUInteger。NSInteger 通常作为有符号整数类型,而 NSUInteger 为无符号整数类型1011。

浮点型(Floating-point numbers)

用于表示有小数点的数字,包括 float 和 double。CGFloat 也是一种常用的浮点类型,特别是在图形和界面编程中11。

布尔型(Booleans)

表示逻辑值 true 或 false。在 Swift 中使用 Bool 类型,而在 Objective-C 中使用 BOOL 或 BOOL 的别名 true 和 false1213。

字符型(Characters)

用于表示单个字符,类型为 char。

枚举型(Enumerations)

一组命名的整数值,通常用于表示一组相关的常量。

空类型(Void)

表示没有值,通常用作没有返回值的函数的返回类型。

构造类型

数组(Arrays)

用于存储一系列相同类型的数据,如 NSArray 和 NSMutableArray11。

字典(Dictionaries)

存储键值对,其中键和值可以是任何对象类型,如 NSDictionary 和 NSMutableDictionary11。

结构体(Structures)

用于将多个不同或相同类型的数据组合成一个单一的复合类型。

联合体(Unions)

较少使用,允许存储多种不同类型的数据。

指针类型

用于存储内存地址,如 data_type *pointer_name。指针的大小取决于系统的架构,32位系统上占4个字节,64位系统上占8个字节10。

面向对象类型

Objective-C 是一种面向对象的语言,因此可以定义类(class)和对象。iOS 开发中大量使用了 Cocoa Touch 框架中的类,如 NSObject、UIView、NSString 等10。

Swift 数据类型

Swift 语言也用于 iOS 开发,它有自己的一套基本数据类型,包括整数(Int)、浮点数(Float、Double)、布尔型(Bool)、可选型(Optional)和元组(Tuple)12。

特殊类型

void *:用于存储任意类型的指针,常用于不确定类型的函数参数或返回值。

语法

在 Objective-C 中,语法类似于 C 语言,包括条件语句(if、switch)、循环(for、while、do-while)和函数定义。

在 Swift 中,语法更为现代化,包括结构化的错误处理、模式匹配和高级函数式编程特性。

了解这些基本语法和数据类型对于任何 iOS 开发者来说都是至关重要的,它们是编写高效、可读和可维护代码的基础。

// 定义整型变量int age = 25;// 定义浮点型变量float height = 1.75;// 定义字符型变量char initial = 'A';// 定义字符串NSString *name = @"John Doe";

基本算术运算符

加法运算符 +:用于加法运算。

int sum = 5 + 3;

减法运算符 -:用于减法运算。

int difference = 5 - 3;

乘法运算符 *:用于乘法运算。

int product = 5 * 3;

除法运算符 /:用于除法运算。需注意,除法运算结果可能是浮点数。

float quotient = 5.0 / 3; // 结果为 1.6666667

模运算符 %:用于求余运算,得到除法的余数。

int remainder = 5 % 3; // 结果为 2

指数运算符:Swift中使用 ** 表示指数运算。

let power = 2 ** 3; // 结果为 8

运算符是编程语言中表达式构建的基本元素,正确使用运算符对于编写正确、高效的代码至关重要。

控制结构

控制结构是编程中用于控制代码执行流程的语句。在iOS开发中,无论是使用Objective-C还是Swift,控制结构都是基本的语法元素。以下是控制结构的详细介绍:

条件语句

if 语句

用于基于特定条件执行不同的代码块。

if (condition) {    // 条件为真时执行的代码} else {    // 条件为假时执行的代码}

if...else if...else 语句

允许根据多个条件进行不同的操作。

if (condition1) {    // 第一个条件为真时执行的代码} else if (condition2) {    // 第二个条件为真时执行的代码} else {    // 所有条件都不为真时执行的代码}

switch 语句

用于基于多个可能的值执行不同的代码块。

switch (value) {    case value1:        // 当 value 等于 value1 时执行的代码        break;    case value2:        // 当 value 等于 value2 时执行的代码        break;    default:        // 如果没有匹配的 case,则执行的代码}

循环语句

for 循环

用于重复执行一段代码,直到给定的条件不再满足。

for (int i = 0; i < numberOfIterations; i++) {    // 每次迭代执行的代码}

while 循环

只要条件为真,就重复执行代码块。

while (condition) {    // 条件为真时重复执行的代码}

do...while 循环

至少执行一次代码块,然后只要条件为真就继续执行。

do {    // 至少执行一次的代码} while (condition);

循环控制语句

break 语句

立即终止循环或 switch 语句的执行。

for (int i = 0; i < 10; i++) {    if (i == 5) {        break; // 在 i 等于 5 时终止循环    }}

continue 语句

跳过当前循环的剩余代码,直接开始下一次迭代。

for (int i = 0; i < 10; i++) {    if (i % 2 == 0) {        continue; // 跳过偶数的迭代    }    // 执行奇数的迭代代码}

选择语句

switch-case 语句(Objective-C)

基于不同的情况执行不同的代码块。

switch (expression) {    case constantExpression:        // 执行的代码        break;    default:        // 如果没有匹配的 case,则执行的代码}

switch 语句(Swift)

Swift 的 switch 语句更加强大,可以匹配多种模式,包括范围、元组、类型等。

let value = 2switch value {    case 1:        print("One")    case 2:        print("Two")    case let x where x > 2:        print("Greater than two")    default:        print("Unknown")}

异常处理

try-catch 语句(Swift)

用于捕获和处理可能抛出的错误。

do {    try someFunctionThatThrows()} catch error {    print("An error occurred: \(error)")}

控制结构是编程中不可或缺的部分,它们允许开发者根据不同的条件和需求来控制程序的执行流程。正确使用控制结构可以使代码更加清晰、易于理解和维护。

函数和方法

函数和方法是编程中用于封装代码逻辑的基本构件。它们可以在满足特定条件时被调用,以执行一段特定的代码。以下是函数和方法的详细说明:

函数(Function)

定义:函数是执行一个或多个操作的一段代码,可以接收输入参数,并可选择性地返回一个值。

特点

可以有零个或多个输入参数。

可以有一个返回值,或者没有返回值(称为void函数)。

语法(C语言风格):

return_type function_name(parameter1_type parameter1_name, ..., parameterN_type parameterN_name) {    // 函数体    return return_value; // 如果函数有返回值}

示例(C语言风格):

int sum(int a, int b) {    return a + b;}

方法(Method)

定义:方法与函数类似,但它们是对象的一部分,与类或对象的属性相关联。

特点

可以访问和修改对象的状态(属性)。

可以是实例方法,也可以是类方法。

语法(Objective-C):

- (return_type)method_name:(parameter_type *)parameter {    // 实例方法体    return return_value;}+ (return_type)class_method_name:(parameter_type *)parameter {    // 类方法体    return return_value;}

示例(Objective-C):

- (NSString *)fullName {    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];}

Swift 中的函数和方法

定义:在Swift中,函数和方法统称为函数,它们使用相同的语法。

特点

支持外部参数名称和内部参数名称。

可以有默认参数值。

可以返回元组。

语法(Swift):

func function_name(parameters) -> return_type {    // 函数体    return return_value}

示例(Swift):

func sum(_ a: Int, _ b: Int) -> Int {    return a + b}

函数和方法的高级特性

参数:可以有默认值,使得函数调用更灵活。

可变参数:可以接受不定数量的参数。

返回值:可以返回多个值,通过元组或自定义类型。

递归:函数可以调用自身,用于实现递归算法。

作用域:函数内部定义的变量在函数外部不可见。

重载:可以定义多个同名函数,只要它们的参数列表不同。

闭包:在Swift中,闭包是自包含的函数结构,可以捕获和存储上下文中的任何常量和变量。

使用场景

封装逻辑:将重复使用的代码逻辑封装在函数或方法中。

代码复用:通过调用函数或方法,避免重复编写相同的代码。

提高可读性:清晰地表达代码的意图,使代码更易读。

函数和方法是编程中实现代码复用、逻辑封装和提高代码可维护性的关键工具。正确使用函数和方法可以使代码结构更清晰,更易于理解和维护。

// 定义一个函数void printGreeting(NSString *name) {    NSLog(@"Hello, %@", name);}// 调用函数printGreeting(@"John");

类和对象

// 定义一个类@interface Person : NSObject@property (strong, nonatomic) NSString *name;@property int age;- (void)introduce;@end// 实现类的方法@implementation Person- (void)introduce {    NSLog(@"My name is %@ and I am %d years old.", self.name, self.age);}@end// 创建对象并调用方法Person *person = [[Person alloc] init];person.name = @"Jane";person.age = 28;[person introduce];

内存管理

内存管理是编程中的一个重要概念,特别是在那些需要手动管理内存的编程语言中。iOS开发中,Objective-C 语言使用引用计数来管理内存,而 Swift 语言则采用了自动引用计数(ARC)。以下是内存管理的详细说明:

Objective-C 内存管理

引用计数(Reference Counting)

每个对象都有一个与之关联的整数计数器,表示当前有多少个强引用指向该对象。

当创建一个对象或将对象赋值给一个变量时,引用计数增加。

当一个引用被释放或赋值为其他对象时,引用计数减少。

内存管理规则

retain:手动增加对象的引用计数。

release:手动减少对象的引用计数,当引用计数为0时,对象被销毁。

autorelease:将对象加入自动释放池,在自动释放池被清空时,对象的引用计数减1。

内存泄漏

当一个对象的引用计数不再为0,但不再有有效的引用指向它时,就会发生内存泄漏。

自动释放池(Autorelease Pool)

一个管理对象自动释放的机制,用于优化内存使用。

循环引用

当两个对象互相强引用对方时,会造成循环引用,需要使用弱引用(weak)或无主引用(unowned)来解决。

Swift 内存管理

自动引用计数(ARC - Automatic Reference Counting)

Swift 语言自动管理内存,开发者不需要手动调用 retain 和 release。

所有权和生命周期

Swift 通过所有权和生命周期的概念来管理内存。

强引用(Strong Reference)

强引用增加对象的引用计数,当没有强引用时,对象被销毁。

弱引用(Weak Reference)

弱引用不增加对象的引用计数,用于避免循环引用。

无主引用(Unowned Reference)

无主引用假设其所指向的对象在生命周期上是稳定的,不增加引用计数。

闭包和内存捕获

闭包可以捕获并存储对外部常量和变量的引用,需要注意闭包造成的循环引用问题。

内存泄漏

在 Swift 中,内存泄漏较少见,但仍然可能发生,特别是在闭包和多线程编程中。

内存管理的最佳实践

避免循环引用:使用弱引用或无主引用来避免对象之间的循环强引用。

及时释放资源:在不需要对象时,确保释放对其的引用,以便内存可以被回收。

使用自动释放池:在 Objective-C 中,合理使用自动释放池来优化内存使用。

理解 ARC:在 Swift 中,理解 ARC 的工作原理,避免不必要的强引用和循环引用。

内存泄漏检测工具:使用 Xcode 的内存泄漏检测工具来识别和修复内存泄漏问题。

内存管理是确保应用程序性能和稳定性的关键。正确的内存管理策略可以避免内存泄漏、野指针和其他内存相关的问题。在 iOS 开发中,无论是使用 Objective-C 还是 Swift,都需要对内存管理有一定的了解和掌握。

// 强引用和弱引用__strong NSString *strongName = name;__weak NSString *weakName = name;

集合类型

集合类型是编程中用于存储多个元素的数据结构。iOS开发中,无论是使用Objective-C还是Swift,都提供了多种集合类型来满足不同的需求。以下是一些常用的集合类型及其详细说明:

数组(Array)

定义:数组是一个有序的元素集合,可以包含重复的元素。

特点

元素可以是任何类型。

通过索引访问元素。

Objective-C 示例

NSArray *array = @[@1, @2, @3];NSNumber *firstElement = array[0];

Swift 示例

var array = [1, 2, 3]let firstElement = array[0]

集合(Set)

定义:集合是一个无序的唯一元素集合。

特点

元素唯一,不会有重复的元素。

不保证元素的顺序。

Objective-C 示例

NSSet *set = [NSSet setWithObjects:@1, @2, @3, nil];

Swift 示例

var set = Set([1, 2, 3])

字典(Dictionary)

定义:字典是一个键值对集合,每个键映射到一个值。

特点

键必须是唯一的。

通过键访问对应的值。

Objective-C 示例

NSDictionary *dictionary = @{@"key1": @1, @"key2": @2};NSNumber *value = dictionary[@"key1"];

Swift 示例

var dictionary = ["key1": 1, "key2": 2]let value = dictionary["key1"]

可变数组(Mutable Array)

定义:可变数组是一个可以修改内容的数组。

特点

可以添加、删除或更改元素。

Objective-C 示例

NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@1, @2, @3, nil];[mutableArray addObject:@4];

Swift 示例

var mutableArray = [1, 2, 3]mutableArray.append(4)

可变集合(Mutable Set)

定义:可变集合是一个可以修改内容的集合。

特点

可以添加或删除元素。

Objective-C 示例

NSMutableSet *mutableSet = [NSMutableSet setWithObjects:@1, @2, @3, nil];[mutableSet addObject:@4];

Swift 示例

var mutableSet = Set([1, 2, 3])mutableSet.insert(4)

可变字典(Mutable Dictionary)

定义:可变字典是一个可以修改内容的字典。

特点

可以添加、删除或更改键值对。

Objective-C 示例

NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:@1, @"key1", @2, @"key2", nil];[mutableDictionary setObject:@3 forKey:@"key3"];

Swift 示例

var mutableDictionary = ["key1": 1, "key2": 2]mutableDictionary["key3"] = 3

高级特性

枚举:遍历集合时,可以同时获取索引和元素。

过滤:根据条件过滤集合中的元素。

映射:将集合中的每个元素应用一个函数,转换成另一个集合。

归约:将集合中的所有元素合并成一个单一的值。

最佳实践

选择合适的集合类型:根据需求选择数组、集合或字典。

注意性能:理解不同集合类型的性能特点,如插入、删除和查找的时间复杂度。

使用不可变集合:如果不需要修改集合,使用不可变集合以避免不必要的复制。

注意线程安全:在多线程环境中,需要特别注意集合类型的线程安全问题。

集合类型是编程中处理数据集合的强大工具。正确使用集合类型可以提高代码的效率、可读性和易用性。在iOS开发中,无论是使用Objective-C还是Swift,都需要熟练掌握各种集合类型的使用。

// 数组NSArray *fruits = @[@"Apple", @"Banana", @"Cherry"];// 字典NSDictionary *personInfo = @{@"Name": @"John", @"Age": @25};// 集合NSSet *uniqueFruits = [NSSet setWithObjects:@"Apple", @"Banana", @"Apple", nil];

协议和类别

在iOS开发中,协议(Protocols)和类别(Categories)是两个重要的语言特性,它们在Objective-C中得到了广泛应用,并且在Swift中也有所体现。

协议(Protocols)

定义:协议是定义方法、属性、和其他需要被实现的契约的蓝图。

目的

允许定义一种规范,任何遵循协议的类或结构体都必须实现协议中要求的方法和属性。

语法(Objective-C):

@protocol ProtocolName- (void)requiredMethod;@end

Swift 中的协议

Swift 使用协议来支持类似接口的功能,并且可以包含方法、属性、构造器、甚至协议和类型别名。

protocol ProtocolName {    func requiredMethod()    var propertyName: Int { get set }}

遵循协议

类或结构体通过在继承列表中添加协议名称来遵循协议。

@interface MyClass () <ProtocolName>@end

实现协议

遵循协议的类或结构体必须实现协议中定义的所有方法和属性。

@implementation MyClass- (void)requiredMethod {    // 实现方法}@end

可选方法

协议中的方法可以是可选的,使用 @optional 关键字。

@protocol ProtocolName@optional- (void)optionalMethod;@end

协议继承

协议可以继承其他协议,使用冒号(:)语法。

@protocol ProtocolA <NSObject>@end@protocol ProtocolB <ProtocolA>@end

类别(Categories)

定义:类别允许给已经存在的类添加新的方法,但是不能添加属性或成员变量。

目的

扩展类的功能,而不需要修改原始类的定义。

语法(Objective-C):

@interface ClassName (CategoryName)- (void)newMethod;@end

实现类别

类别的方法需要在另一个文件中实现。

@implementation ClassName (CategoryName)- (void)newMethod {    // 方法实现}@end

使用类别

类别可以用于组织代码,或者为第三方库添加功能。

限制

类别不能添加属性,因为属性需要存储空间,这需要修改原始类的结构。

类别不能声明新的存储类型为 static 或 global 的变量。

优点

提供了一种灵活的方式来扩展类的功能,而不需要继承。

注意

类别方法的实现必须在链接时出现在程序中,否则调用这些方法将会导致运行时错误。

扩展(Extensions)

在Swift中,扩展(Extensions)提供了类似于Objective-C中类别的功能,但更加强大和灵活。

定义:扩展用于给现有类型添加新功能。

语法(Swift):

extension ClassName {    func newMethod() {        // 方法实现    }}

功能

可以添加方法、计算属性、构造器、协议遵循等。

限制

不能添加存储属性或修改现有属性的访问级别。

优点

可以在不修改原始类型定义的情况下,增加新功能。

协议和类别是iOS开发中强大的工具,它们提供了代码复用、功能扩展和模块化设计的能力。正确使用这些特性可以提高代码的可维护性和灵活性。

异常处理

在iOS开发中,异常处理是一种错误管理机制,用于捕获和处理程序运行过程中出现的意外情况。以下是异常处理的详细说明:

Objective-C 中的异常处理

Objective-C 使用 NSException 类来处理异常。它是基于Cocoa框架的异常处理方式,并不是C++那样的传统异常处理机制。

抛出异常:使用 @throw 语句抛出一个 NSException 对象。

@throw [NSException exceptionWithName:@"MyException" reason:@"Something went wrong" userInfo:nil];

捕获异常:Objective-C 没有传统意义上的 try-catch 语句来捕获异常,但可以使用 @try、@catch、@finally 语句块来处理异常。

@try {    // 可能抛出异常的代码} @catch (NSException *exception) {    // 处理异常    NSLog(@"Exception: %@", [exception reason]);} @finally {    // 无论是否发生异常都会执行的代码}

异常类型:NSException 是所有异常类型的基类,可以创建自定义异常类型继承自 NSException。

Swift 中的异常处理

Swift 使用 do-catch-throw 语句进行异常处理,这是一种更现代的错误处理机制,类似于其他现代编程语言。

错误类型:在 Swift 中,使用 Error 协议定义错误类型。任何遵循 Error 协议的类型都可以被抛出和捕获。

enum MyError: Error {    case somethingWentWrong}

抛出错误:使用 throw 关键字抛出一个错误。

throw MyError.somethingWentWrong

捕获错误:使用 do 代码块来执行可能会抛出错误的代码,并使用 catch 来捕获错误。

do {    // 可能抛出错误的代码} catch MyError.somethingWentWrong {    // 处理特定的错误    print("Something went wrong")} catch {    // 处理其他所有错误    print("An unknown error occurred")}

传播错误:使用 throws 关键字声明函数、方法可能抛出错误,但不处理它,而是让调用者来处理。

func functionThatThrows() throws {    // 如果发生错误,使用 throw 抛出}

错误处理策略

使用 defer 代码块来执行无论是否抛出错误都需要执行的清理工作。

func someFunction() {    defer {        // 清理资源    }    // 其他代码}

断言:Swift 提供了 assert 和 assertionFailure 用于调试过程中的检查。

assert(condition, "Condition failed")

最佳实践

避免过度使用异常处理:异常处理应该用于处理真正的异常情况,而不是常规的控制流。

使用自定义错误类型:定义清晰、描述性的错误类型来提高代码的可读性和可维护性。

资源清理:使用 defer 来确保即使发生错误也能正确清理资源。

错误传播:当函数、方法不能处理某个错误时,应该使用 throws 将其传播到调用者。

异常处理是确保程序稳定性和健壮性的关键机制。正确使用异常处理可以避免程序在遇到错误时崩溃,并提供优雅地处理错误的机会。在iOS开发中,无论是使用Objective-C还是Swift,都需要对异常处理有一定的了解和掌握。

字符串和字符操作

字符串和字符操作是编程中的基础部分,尤其是在处理用户输入、输出和数据表示时。iOS开发中,Objective-C和Swift都提供了丰富的API来操作字符串和字符。

Objective-C 中的字符串和字符操作

NSString 类

Objective-C 中的字符串由 NSString 类表示,是一个不可变的字符串类。

创建字符串

NSString *string = @"Hello, World!";

连接字符串

NSString *concatenatedString = [string stringByAppendingString:@" This is iOS development."];

访问字符

char16_t charValue = [string characterAtIndex:0]; // 'H'

长度和子字符串

NSUInteger length = [string length];NSString *substring = [string substringFromIndex:7]; // "World!"

比较字符串

BOOL isEqual = [string isEqualToString:@"Hello, World!"];

搜索和替换

NSString *replacedString = [string stringByReplacingOccurrencesOfString:@"World" withString:@"iOS"];

格式化字符串

NSString *formattedString = [NSString stringWithFormat:@"Value: %d", 42];

Swift 中的字符串和字符操作

String 结构体

Swift 中的字符串由 String 结构体表示,与 Objective-C 类似,它也是不可变的。

创建字符串

let string = "Hello, World!"

连接字符串

let concatenatedString = string + " This is iOS development."

访问字符

let character = string[string.startIndex] // 'H'

长度和子字符串

let length = string.countlet substring = String(string.suffix(5)) // "World!"

比较字符串

let isEqual = string == "Hello, World!"

搜索和替换

let replacedString = string.replacingOccurrences(of: "World", with: "iOS")

字符串格式化

let formattedString = "Value: \(value)"

跨语言特性

不可变性:字符串在Objective-C和Swift中都是不可变的,任何修改都会返回一个新的字符串实例。

Unicode 支持:两种语言的字符串都支持Unicode字符。

字符串索引:可以通过索引访问字符串中的特定位置,Swift 中使用 String.Index 类型。

字符串迭代器:Swift 通过 String.CharacterView 来迭代字符串中的字符。

高级字符串操作

正则表达式:使用正则表达式进行复杂的搜索和替换操作。

编码和解码:处理字符串的编码格式,如 UTF-8、UTF-16 等。

本地化:根据用户的语言环境对字符串进行本地化处理。

图形和布局:在图形界面中使用字符串时,考虑字符串的布局、对齐和样式。

最佳实践

避免字符串字面量拼接:频繁的字符串拼接可能导致性能问题,特别是在循环中。

使用字符串插值:使用插值(如 Swift 中的 \(variable))来构建字符串。

处理空字符串:在操作字符串之前检查空字符串,避免运行时错误。

使用字符集:使用字符集来定义有效的字符范围,用于搜索和验证。

字符串和字符操作是编程中非常基础且频繁的操作。掌握这些操作可以提高开发效率,编写出更清晰、更健壮的代码。在iOS开发中,无论是使用Objective-C还是Swift,都需要熟练使用这些字符串操作。

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

推荐阅读更多精彩内容