IOS SDK framework 创建调试

.a静态库创建

直接创建Framework库

在已有工程中创建

创建Framework工程进行封装

创建Bundle资源库文件

含界面SDK如何进行依赖开发

使用脚本创建Framework库,解决合并的烦恼

Swift 如何创建Framework库

知识准备

终端命令

真机和模拟器上的库文件合并 Framework库合并的是Framework内包含的二进制文件,合并后替换库中的文件,没有.a后缀lipo -create xxx.a(真机)xxx.a(模拟器)-output 新名字.a查看SDK支持的架构lipo -info XXX.a  输出: i386 armv7 x86_64 arm64

arm7: 在最老的支持iOS7的设备上使用

arm7s: 在iPhone5和5C上使用

arm64: 运行于iPhone5S的64位 ARM 处理器 上

i386: 32位模拟器上使用

x86_64: 64为模拟器上使用

注意: 高位兼容地位(32位兼容16位),arm7版本可以在arm7s上运行

需要在对应架构设备上运行,才能生成对应架构的包

category的处理

category是项目开发中经常用到的,把category打包成静态库是没有问题的,但是在使用这个静态库时,

调用category中的方法时会发生找不到该方法的运行时错误(selector not recognized),

解决的办法是在使用静态库的工程中配置other linker flags的值为 -ObjC -all_load

对图片资源和UI界面xib或nib文件的处理

.a和.framework两种静态库,通常都是把需要用的到图片或者xib文件存放在一个bundle文件中,而该bundle文件的名字和.a或.framework的名字相同。

.a文件中无法存放图片或xib文件,很容易理解,但是.framework从本质上说也是一个bundle文件,为什么不把图片或者xib文件直接放在.framework中而单独再创建个bundle文件呢?

那是因为iOS系统不会去扫描.framework下的图片等资源文件,也不会在项目中显示,也就是说即使放在 .framework目录下,系统根本就不会去扫描,因此也无法发现使用

Debug和Release

Debug和Release,在我看来主要是针对其面向的目标不同的而进行区分的。

Debug通常称为调试版本,通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能力。

Release通常称为发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优。为用户的使用提供便利

开发指南

网上找了一个动画工程,作为我们开刀的对象

下载原始工程

如果你有耐性,可以和我一起走完整个流程。当然每个模块都是独立的,你可以进行针对性的阅读

一、.a静态库创建

创建静态库工程 >> 删除自动创建的.m文件 >> 清空头文件里的信息 >> 导入你要封装的系统库文件

创建静态库工程 libLoader(名字你高兴就好)

删除自动创建的.m文件,清空头文件里的信息

导入你要封装的系统库文件

点击目标工程 >> Build Phases >> Editor >> add build Phases(是否公开头文件选项) >> 设置公开访问的头文件(或在Target Membership中直接设置)

目标工程 > Build Phases > 点击左侧加号 > add build Phases(是否公开头文件选项) > 设置公开访问的头文件(或在Target Membership中直接设置)

添加头文件选项

设置私有和暴露头文件

设置私有和暴露头文件

选择sdk支持的系统版本

参数设置

Build Settings >> Dead Code Stripping设置为NO

Build Settings >> Strip Debug Symbol During Copy 全部设置为NO

Build Settings >> Strip Style设置为Non-Global Symbols

Build Settings >> Base SDK >> Latest iOS(iOS 选择最新的)

Dead Code Stripping设置为NO

Strip Debug Symbol During Copy 全部设置为NO

Strip Style设置为Non-Global Symbols

Base SDK >> Latest iOS(iOS 选择最新的)

在设备 和 模拟器 下分别按下command + B进行编译 >> 查看Product目录 >> Show in Finder 查看编译成功的静态库

debug模式下运行生成  Debug-iphoneos 和 Debug-iphonesimulator两个文件夹

release模式下运行生成 Release-iphoneos 和 Release-iphonesimulator文件夹

切换编译模式

分别查看.a库文件

合并Debug模式下的真机和模拟器下的静态库文件

使用终端进行合并cd 文件保存目录lipo -create 模拟器.a(路径)真机.a(路径)-output 重命名.a查看架构模式lipo -info XXX.a  查看是否满足运行要求

使用.a库文件

创建文件夹libAdvanced用于保存静态库信息 >> 替换刚刚合并的.a文件 >> 添加用到的图片等资源文件 >> 导入工程验证

静态库完成

创建新工程验证

如果架构报错  Build Settings >> BuildActiveArchitecture Only Debug改为NO

二、直接创建Framework库

<p id="jump"></p>

Framework是资源的集合,将静态库和其头文件包含到一个结构中,让Xcode可以方便地把它纳入到你的项目中。本质也是一个bundle文件

在已有工程中创建

创建Framework

点击目标工程 >> 点击下面左下角加号 >> 创建

创建Framework

参数配置

点击目标工程>>选择你创建的Framework>>点击工程设置>>做出如下修改      Build Settings>>Dead Code Stripping>>设置为NO      Build Settings>>Strip Debug Symbol During Copy>>全部设置为NO      Build Settings>>Strip Style>>设置为Non-Global Symbols      Build Settings>>Base SDK>>Latest iOS(iOS 选择最新的)Build Settings>>Link With Standard Libraries>>设置为 NO      Build Settings>>Mach-O Type>>Static Library      对于Mach-O Type有两种情况:(1)选择 Static Library 打出来的是静态库;(2)选择 Relocatable Object File 打出来是动态库。

其他参数修改类似

选择framework支持的系统版本

将需要打包的文件拖入到Framework中

将需要打包的文件拖入到Framework中

设置需要公开的文件

设置暴露头文件

选择运行模式(debug 或 Release)分别在真机和模拟器下common + B 编译生成对应的Framework库

合并二进制文件并替换

cd 到保存文件目录下lipo-create xxx/Debug-iphoneos/LibLoaderFramework.framework/LibLoaderFramework xxx/Debug-iphonesimulator/LibLoaderFramework.framework/LibLoaderFramework-output LibLoaderFrameworklipo-info LibLoaderFramework输出Architecturesinthe fat file:LibLoaderFramework are:i386 arm64 然后替换二进制文件

image.png

删除Framework

image.png

如果没有用到info.plist文件可以删除,避免在工程中发生冲突

验证

导入完整Framework到工程,移除打包前的代码,对库进行验证

建立Framework工程进行创建

使用xcode直接创建Framework工程

把需要编译的文件导入到工程中

设置需要公开的头文件

image.png

选择Framework支持的系统版本

配置参数

参数配置基本都一样点击目标工程>>选择你创建的Framework>>点击工程设置>>做出如下修改  Build Settings>>Dead Code Stripping>>设置为NO  Build Settings>>Strip Debug Symbol During Copy>>全部设置为NO  Build Settings>>Strip Style>>设置为Non-Global Symbols  Build Settings>>Base SDK>>Latest iOS(iOS 选择最新的)Build Settings>>Link With Standard Libraries>>设置为 NO  Build Settings>>Mach-O Type>>Static Library  对于Mach-O Type有两种情况:(1)选择 Static Library 打出来的是静态库;(2)选择 Relocatable Object File 打出来是动态库。

-  选择Debug(或Release)模式分别在模拟器和真机上 command + B 编译- 合并真机和模拟器下编译的二进制文件

cd到你想要保存合并后文件的目录下lipo -create xxx.framework/xxx ooo.framework/ooo -output ooo。查看文件支持的架构lipo -info LibLoaderFramework将合并成功的二进制文件替换为framework中的二进制文件,如果没有用到info.plist文件,可以删除,避免在工程中发生冲突

创建新的工程,导入Framework进行验证

如果工程无法联想出Framework头文件,导入路径形式如下:#import

三、创建Bundle资源库文件

创建Bundle工程

创建Bundle工程

配置几个编译设置

因为你正在创建一个在iOS上使用的bundle,这与默认的OSX不同。BuildSettings>>BaseSDK>>LatestiOS(iOS10.2选择最新)BuildSettings>>ProductName>>${TARGET_NAME}替换为你的工程名XXXX(直接写工程名就好)################注意事项######################默认情况下,有两种resolutions(分辨率)的图片可以产生一些有趣的现象。例如,当你导入一个retina@2x版本的图片时,普通版的和Retina版的将会合并成一个多resolution的TIFF(标签图像文件格式,TaggedImageFileFormat)。BuildSettings>COMBINE_HIDPI_IMAGES设置为NO

如何添加资源文件

直接拖入

选择图片或其他资源文件 > Target Membership > 选择bundle目标

编译工程并查看

编译工程并查看

Bundle文件使用时需要真实路径

NSBundle*bundle=[NSBundle bundleWithURL:[[NSBundle mainBundle]URLForResource:@"LoaderBundle"withExtension:@"bundle"]];NSString*resourceStr=[bundle pathForResource:@"IMG_0017"ofType:@"JPG"];我们可以创建NSBundle分类避免重复书写

创建工程验证

四、含界面SDK如何进行依赖开发

在无法看到真实效果的情况下为iOS开发一个UI控件库是极其困难的,所以我们需要掌握依赖开发的知识

创建Framework工程

参数设置:参考如上第二章节

创建验证工程

关闭Framework工程

添加Framework工程的xxxx.xcodeproj到验证工程并连接到静态库如图操作:若未找到库,对库进行编译

添加Framework工程的xxxx.xcodeproj到验证工程并连接到静态库

导入库的公开头文件,对验证工程进行编译

如果工程无法联想出Framework头文件,导入路径形式如下:#import

像这样使用嵌套工程的好处是你可以对库本身做出修改,而不用离开示例工程,即使你同时改变两个地方的代码也一样。每次你编译工程,你都要检查是否将头文件的public/project关系设置正确。如果实例工程中缺失了任何需要的头文件,它都不能被编译。

五、使用脚本创建Framework库

创建.a的静态库工程

(创建方式与参数配置参照第一节不再赘述)

使用脚本创建Framework目录结构,此时不包含二进制文件

添加 New Run Script Phases

双击面板标题栏Run Script,重命名为Build Framework。

这个面板允许你在构建时运行一个Bash脚本

你希望让脚本在build的过程中何时执行,就把这个面板拖动到列表中相对应的那一位置。

对于该framework工程来说,脚本最后执行,因此你可以让它保留在默认的位置即可。

使用脚本创建Framework目录结构

#set –e确保脚本的任何地方执行失败,则整个脚本都执行失败。set -e#导出framework路径export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"# 创建当前版本真实头文件夹mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"# 创建引用路径/bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"/bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"/bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \"${FRAMEWORK_LOCN}/${PRODUCT_NAME}"# 拷贝公共头文件到framework中/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \ "${FRAMEWORK_LOCN}/Versions/A/Headers"#######################简化目录也可用使用如下脚本########################set –e确保脚本的任何地方执行失败,则整个脚本都执行失败。set -e#导出的文件路径export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"# 创建真是文件路径mkdir -p "${FRAMEWORK_LOCN}/Headers"# 拷贝公共头文件到framework中/bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \"${FRAMEWORK_LOCN}/Headers"

这个脚本做了如下三个操作:1.创建了libLoader.framework/Versions/A/Headers目录2.创建了一个framework所需要的三个连接符号([symbolic links](http://en.wikipedia.org/wiki/Symbolic_link))当前版本文件夹Versions/Current=>A头文件夹Headers=>Versions/Current/Headers二进制文件libLoader=>Versions/Current/libLoader3.将公共头文件从你之前定义的公共头文件路径拷贝到Versions/A/Headers目录下,-a参数确保修饰次数作为拷贝的一部分不会改变,防止不必要的重新编译。

构建成功后的Framework目录

多架构(Multi-Architecture)编译

解决Framework或.a库合并的烦恼,此处用的是.a工程,使用Framework工程类似

iOS app需要在许多不同的CPU架构下运行:

arm7: 在最老的支持iOS7的设备上使用 arm7s: 在iPhone5和5C上使用  arm64: 运行于iPhone5S的64位 ARM 处理器 上 i386: 32位模拟器上使用 x86_64: 64为模拟器上使用

每个CPU架构都需要不同的二进制数据,当你编译一个应用时,无论你目前正在使用那种架构,Xcode都会正确地依照对应的架构编译。例如,如果你想跑在虚拟机上,Xcode只会编译i386版本(或者是64位机的x86_64版本)。

这意味着编译会尽可能快地进行,当你归档一款app或者构建app的发布版本(release mode)时,Xcode会构建上述三个用于真机的ARM架构。因此这样app就可以跑在所有设备上了。不过,其他的编译架构又如何呢?让我们一起往下走

创建 Aggregate 集合

点击目标工程 > 添加新目标 > Cross-Platform > Aggregate > next > 命名为Framework

命名为Framework

为什么使用集合(Aggregate)目标来创建一个framework呢?为什么这么不直接?因为OS X对库的支持更好一些,事实上,Xcode直接为每一个OS X工程提供一个Cocoa Framework编译目标。基于此,你将使用集合编译目标,作为Bash脚本的连接串来创建神奇的framework目录结构。

你是不是开始觉得这个方法有些懵逼了?

添加依赖库

为了确保每当这个新的framework目标被创建时,静态链接库都会被编译,你需要往静态库目标中添加依赖(Dependency)。在库工程中选择Framework目标,在Build Phases中添加一个依赖。展开Target Dependencies面板,添加

添加依赖库

添加多平台编译脚本

这个目标的主要编译部分是多平台编译,你将使用一个脚本来做到这一点。和你之前做的一样

选择Framework目标 >> Build Phases >> 左侧 “+” 按钮 >> New Run Script Phases >> 命名MultiPlatform Build

![MultiPlatform Build

写入编译framewo编译脚本

#set –e确保脚本的任何地方执行失败,则整个脚本都执行失败。    set -e    #标示 如果已经插入脚本 退出    if [ -n "$IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then    exit 0    fi    export IYQ_MULTIPLATFORM_BUILD_IN_PROGRESS=1    # 自定义变量    IYQ_FRAMEWORK_NAME=${PROJECT_NAME}    IYQ_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"    IYQ_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework"    #构建静态库 传参 "${1}"    function build_static_library {    # 重新构建库        xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \        -target "${TARGET_NAME}" \        -configuration "${CONFIGURATION}" \        -sdk "${1}" \        ONLY_ACTIVE_ARCH=NO \        BUILD_DIR="${BUILD_DIR}" \        OBJROOT="${OBJROOT}" \        BUILD_ROOT="${BUILD_ROOT}" \        SYMROOT="${SYMROOT}" $ACTION    }    #合并    function make_fat_library {        xcrun lipo -create "${1}" "${2}" -output "${3}"    }    # 1 正则判断 真机还是模拟器 (iphoneos/iphonesimulator)    if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then    IYQ_SDK_PLATFORM=${BASH_REMATCH[1]}    else    echo "Could not find platform name from SDK_NAME: $SDK_NAME"    exit 1    fi    # 2 SDK版本    if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then    IYQ_SDK_VERSION=${BASH_REMATCH[1]}    else    echo "Could not find sdk version from SDK_NAME: $SDK_NAME"    exit 1    fi    # 3 其他平台判断 如果 则 否则    if [ "$IYQ_SDK_PLATFORM" == "iphoneos" ]; then    IYQ_OTHER_PLATFORM=iphonesimulator    else    IYQ_OTHER_PLATFORM=iphoneos    fi    # 4 其他平台路径    if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$IYQ_SDK_PLATFORM$ ]]; then    IYQ_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${IYQ_OTHER_PLATFORM}"    else    echo "Could not find other platform build directory."    exit 1    fi    #调用上面构建函数 如果当前运行的是真机则构建模拟器    build_static_library "${IYQ_OTHER_PLATFORM}${IYQ_SDK_VERSION}"    # 如果你现在正在为模拟器编译,那么Xcode会默认只在该系统对应的结构下编译,例如i386 或 x86_64。为了在这两个结构下都进行编译,这里调用了build_static_library,基于iphonesimulator SDK重新编译,确保这两个结构都进行了编译。    if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then    build_static_library "${SDK_NAME}"    fi    # 合并库    make_fat_library "${BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_INPUT_STATIC_LIB}" \    "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}"    # 确保文件存在 相当于-dpR,保持文件的连接(d),保持原文件的属性(p)并作递归处理(R)    cp -a "${IYQ_FRAMEWORK_LOCATION}/${IYQ_FRAMEWORK_NAME}" \    "${IYQ_OTHER_BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.framework/${IYQ_FRAMEWORK_NAME}"    # 拷贝到指定目录下    ditto "${IYQ_FRAMEWORK_LOCATION}" "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.framework"

在工程目录下的BuildFramework文件下查看,并导入工程验证

#import <libLoader/LoaderProgressView.h>

BuildFramework在工程目标下

SDK存在图片,xib等资源文件的情况

添加bundle目标工程

bundle创建详细操作参考第三节内容

bundle目标工程进行编译

添加bundle资源库依赖

添加bundle资源库依赖

如果想把你的编译包copy到指定位置,在脚本后面加入如下代码

# 拷贝bundle到指定目录下  ditto "${BUILT_PRODUCTS_DIR}/${IYQ_FRAMEWORK_NAME}.bundle" \  "${SRCROOT}/BuildFramework/${IYQ_FRAMEWORK_NAME}.bundle"

六、swift 工程如何创建Framework库

swift支持静态库吗?

iOS 8已经开放了动态库的权限。

Swift 不在支持静态库,这也就间接放弃了 iOS 7。

项目中如果使用了自制的动态库,能否上传到AppStore?

创建的动态库需要在 General >> Embedded Binaries 中添加才能使用

苹果把这种 Framework 称为 Embedded Framework。

我们创建的这个动态库其实也不能给其他程序使用,只能是在我们的 App Extension 和 APP 之间共用。所有这种情况对 AppStore 上架没有影响,可以正常发布。

创建swift语言的Framework项目

对外公开的方法和类需要添加public前缀

对外公开的方法需要添加 `public` 前缀

注意:如果还允许 **override **和继承的话,可以使用 **open **关键字。(关于访问控制的详细说明,可以参考我之前的这篇文章:Swift - 访问控制(fileprivate,private,internal,public,open)

分别在真机和模拟器上编译

为客户提供使用的正式包请选择release模式下编译

合并Framework二进制文件

终端命令cd 到Products目录真机和模拟器上的库文件合并 lipo -create xx/aa.framework/aa oo/aa.framework/aa -output aa查看SDK支持的架构lipo -info LibLoaderFramework

合并Mudules目录下的内容

最后Framework的目录结果

image.png

导入工程进行验证

因为是动态库,此处也需要导入,否则工程会崩溃

转载:https://www.jianshu.com/p/cbb1f54b89d2 保留学习

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

推荐阅读更多精彩内容

  • 11月22日,正是冬日里小雪的节气,这一天洛阳城迎来了第一场雪,这一天是女儿20岁的生日,而我也选择这一天在简书写...
    鹰鹰儿阅读 482评论 18 14
  • 今天算是正式在简书安家开篇了。 突然从微信的碎片阅读和短句写作切换到这个模式,说实话有些忐忑,虽然今天中午...
    遇见恺and瑞阅读 168评论 2 0
  • 今天是值得我纪念和庆祝的日子!因为今天我在简书安家啦! 10月27日注册了简书和#博,然后开始在#博里发原创,忙忙...
    阳光满屋哦阅读 733评论 26 23
  • 今天看到一篇文章里说到“简书”这个写作软件,我在百度上搜到了这个,然后注册成会员。我想以后这里将会是我写作练习的主...
    水境阅读 127评论 0 1
  • 亲爱的邹小北小姐, 你好,初次见面,内心忐忑 ,久候多时,终尝所愿! 现在是公历2016年2月20日,东二区时间下...
    野雾啦吠放阅读 1,737评论 4 15