All Projects → nsoojin → Bookstore Ios

nsoojin / Bookstore Ios

Licence: mit
 Sample iOS App - A collection of examples and patterns for Unit Testing, UI Testing, handling Result/Optionals, writing documentation, and more. Details in README.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Bookstore Ios

Quiz App
A repository reflecting the progress made on the "How to Build iOS Apps with Swift, TDD & Clean Architecture" YouTube series, by Caio & Mike.
Stars: ✭ 230 (+56.46%)
Mutual labels:  swift-framework, unit-testing, ui-testing, xctest
XCTestHTMLReport
Xcode-like HTML report for Unit and UI Tests
Stars: ✭ 581 (+295.24%)
Mutual labels:  unit-testing, xctest, ui-testing
Xctesthtmlreport
Xcode-like HTML report for Unit and UI Tests
Stars: ✭ 489 (+232.65%)
Mutual labels:  unit-testing, ui-testing, xctest
Dagger2
Kotlin Dagger2 example project
Stars: ✭ 145 (-1.36%)
Mutual labels:  unit-testing, ui-testing
Mockingbird
A convenient mocking framework for Swift
Stars: ✭ 302 (+105.44%)
Mutual labels:  unit-testing, xctest
Hotels
酒店预订App
Stars: ✭ 323 (+119.73%)
Mutual labels:  ios-app, ios-demo
Iosproject
iOS project of collected some demos for iOS App, use Objective-C
Stars: ✭ 5,357 (+3544.22%)
Mutual labels:  ios-app, ios-demo
Example Ios Apps
 A curated list of Open Source example iOS apps developed in Swift. An amazing list for people who are beginners and learning ios development and for ios developers who need any example app or feature.
Stars: ✭ 461 (+213.61%)
Mutual labels:  ios-app, ios-demo
Avsqldebugger
A Simple Core Data Debugger that will look inside your apps DB
Stars: ✭ 30 (-79.59%)
Mutual labels:  ios-app, ios-demo
Swiftcocoadsl
An easy way to write iOS UI
Stars: ✭ 103 (-29.93%)
Mutual labels:  ios-app, ios-demo
Uitestingexample
Example code from my blog post about UI testing
Stars: ✭ 57 (-61.22%)
Mutual labels:  ui-testing, xctest
Fakery
👽 Swift fake data generator
Stars: ✭ 1,572 (+969.39%)
Mutual labels:  swift-framework, unit-testing
Iosproject
IOS综合项目,完善的框架,路由模块化设计,集成科大讯飞SDK方便iOS基本输入控件实现语音辅助输入,UI效果参照京东APP,JS与OC交互,ionic跨平台开发,MQTT 协议,即时通讯协议,视屏播放,跑马灯效果 仿美团地图定位,城市收索, 友盟分享,基础动画 增加FCUIID帮助类,引导页功能模块,照片上传 ,UIView自定义导航栏,文件下载,Masonry 案例,fmdb,数据库,sqlite,百度地图,二维码,照片上传,照片上传有进度,列表倒计时,H5和原生交互,自定义各种弹框,常见表单类型,人脸识别,列表加载图片,列表拖拽,日历操作,导航条渐变,核心动画,动画特效等等
Stars: ✭ 291 (+97.96%)
Mutual labels:  ios-app, ios-demo
Postdemo
BBCo - iOS开发入门教程 SwiftUI 微博App项目实战 零基础学习Swift编程
Stars: ✭ 269 (+82.99%)
Mutual labels:  ios-app, ios-demo
Autoinch
优雅的iPhone全尺寸/等比例精准适配工具
Stars: ✭ 395 (+168.71%)
Mutual labels:  ios-app, ios-demo
DailyNews
Daily News is a news app with good looking user interface ! Apps architecture is MVVM and used RxSwift for binding.
Stars: ✭ 31 (-78.91%)
Mutual labels:  unit-testing, ios-app
Swift project
原OC项目用swift实现,纯swift项目,可作为学习swift的demo,包含多个自定义控件,并且进行封装网络请求库,结构清晰。
Stars: ✭ 133 (-9.52%)
Mutual labels:  ios-app, ios-demo
OnboardingSample
Beginners - A demo of an onboarding screen in iOS using Swift
Stars: ✭ 95 (-35.37%)
Mutual labels:  ios-app, ios-demo
Leon
Leon is swift library to show and slid images with more gesture
Stars: ✭ 16 (-89.12%)
Mutual labels:  ios-app, swift-framework
Cocoaasyncsocket demo
基于AsyncSocket搭建即时通讯体系 . 包含TCP连接 , 消息发送 , 消息接收 , 心跳处理 ,断网重连 , 消息超时 , 消息分发 , 数据库结构设计 , 消息丢失等 . 以及UI设计, 文本表情消息/语音消息/图片消息/视频消息/文件消息/撤回消息/提示语消息的实现思路讲解
Stars: ✭ 981 (+567.35%)
Mutual labels:  ios-app, ios-demo

BookStore

👉 한글 버전

See new releases and search for programming books from IT Bookstore API

This is a sample app to practice using Result type, stubbing network request for unit tests, separating functionalities into frameworks, and writing Swift documentation.

How to run

> cd BookStore
> open BookStore.xcodeproj

Run!

Contents

App Features

What's New

A simple UITableView with cells and modal presentation for a detailed page.

Search

  1. As a user types in the keyword, the search text is "debounced" for a fraction of second for better performance and user experience. See Debouncer.

  2. Search results are paginated and provides infinite scroll.

Result type in Swift 5

Out of the box, you have to switch on the Result instance to access the underlying success instance or the error instance.

switch result {
case .success(let response):
  //do something with the response
case .failure(let error):
  //handle error
}

However, I think switch statements are too wordy. I added success and catch method to Result type. So it can be chained like this.

searchResult.success { response in
  //do something with the response
}.catch { error in
  //handle error
}

Even cleaner, like this.

result.success(handleSuccess)
      .catch(handleError)
      
func handleSuccess(_ result: SearchResult) { ... }
func handleError(_ error: Error) { ... }

Stubbing Network Requests for Unit Tests

Generally, it is not a good idea to rely on the actual network requests for unit tests because it adds too much dependency on tests. One way to stub networking is to subclass URLProtocol.

1. Subclass URLProtocol

See MockURLProtocol

2. Configure URLSession with your mock URLProtocol

let config = URLSessionConfiguration.ephemeral
config.protocolClasses = [MockURLProtocol.self]

//Use this URLSession instance to make requests.
let session = URLSession(configuration: config) 

4. Use the configured URLSession instance just as you would.

session.dataTask(with: urlRequest) { (data, response, error) in
  //Stubbed response
}.resume()

UI Testing with Stubbed Network Data

The above method(as well as the famous OHHTTPStubs) doesn't work for UI testing because the test bundle and the app bundle (XCUIApplication) are loaded in separate processes. By using Swifter, you can run a local http server on the simulator.

First, change the API endpoints during UI testing with launchArguments in your hosting app.

//In XCTestCase,
override func setUp() {
  app = XCUIApplication()
  app.launchArguments = ["-uitesting"]
}

//In AppDelegate's application(_:didFinishLaunchingWithOptions:)
if ProcessInfo.processInfo.arguments.contains("-uitesting") {
  BookStoreConfiguration.shared.setBaseURL(URL(string: "http://localhost:8080")!)
}

Then stub the network and test the UI with it.

let server = HttpServer()

func testNewBooksNormal() {
  do {
    let path = try TestUtil.path(for: normalResponseJSONFilename, in: type(of: self))
    server[newBooksPath] = shareFile(path)
    try server.start()
    app.launch()
  } catch {
    XCTAssert(false, "Swifter Server failed to start.")
  }
        
  XCTContext.runActivity(named: "Test Successful TableView Screen") { _ in
    XCTAssert(app.tables[tableViewIdentifier].waitForExistence(timeout: 3))
    XCTAssert(app.tables[tableViewIdentifier].cells.count > 0)
    XCTAssert(app.staticTexts["9781788476249"].exists)
    XCTAssert(app.staticTexts["$44.99"].exists)
  }
}

Using Frameworks for independent functionalities

Separating your app's functions into targets has several advantages. It forces you to care about dependencies, and it is good for unit tests since features are sandboxed. However, it may slow down the app launch (by little) due to framework loading.

BookStoreKit is responsible for fetching and searching books data from IT Bookstore API.

Networking is a wrapper around URLSession for making HTTP requests and parsing response.

Writing a documentation comment

Swift's API Design Guidelines suggest you write a documentation comment for every declaration. Writing one can have an impact on the design.

1. Write

Reference this document for markup formatting.

2. Check out the result

In Xcode's autocompletion

and Show Quick Help (option + click)

Getting Rid of IUOs

IMHO Implictly unwrapped optional is a potential threat to code safety and should be avoided as much as possible if not altogether. An example of two methods to get rid of them from where they are commonly used.

Make IBOutlets Optional

IBOutlets are IUOs by Apple's default. However, you can change that to Optional types. You may worry that making IBOutlets Optionals may cause too many if lets or guards, but that concern may just be overrated. IBOutlets are mostly used to set values on them, so optional chaining is sufficient. In just few cases where unwrapping is added, I will embrace them for additional safety of my code.

Using lazy instantiation

For the properties of UIViewController subclass, IUO can be useful but it's still dangerous. Instead, I use unspecified. It generates a crash upon class/struct usage so it can be spotted fast during development, and most importantly no more IUOs.

//Inside a viewcontroller
lazy var bookStore: BookStoreService = unspecified()
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].