Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Being a tvOS developer

Being a tvOS developer

Presenting what my daily development looks like as a tvOS dev.
The talk was took place at yidev meetup, in Yokohama, Japan.

toshi0383

March 05, 2016
Tweet

More Decks by toshi0383

Other Decks in Technology

Transcript

  1. Toshihiro Suzuki 4 ླ໦ ढ़༟ 4 @toshi0383 4 iOS/Mac/tvOS develper

    4 currently at NEXTSCAPE 4 try! Swift attendee © Toshihiro Suzuki 2016 2
  2. Toshihiro Suzuki 4 Drives go-kart so fast too farious 4

    Drummer/Trumpetter 4 Snowboarder 4 used to be a Pokemon Master © Toshihiro Suzuki 2016 3
  3. Will talk about what it means to be a tvOS

    developer © Toshihiro Suzuki 2016 4
  4. tvOS is a new platform We can use the newest

    APIs © Toshihiro Suzuki 2016 5
  5. has very sofistcated user interface. It's much easier than iOS

    to write great apps. © Toshihiro Suzuki 2016 9
  6. Today's topics will be 4 What my daily development look

    like 4 What my codebase look like © Toshihiro Suzuki 2016 13
  7. The App 4 is kind of like Netflix. 4 Already

    available on iOS/Android, AndroidTV, TVs 4 SI, not own app. 4 We're middle of development. © Toshihiro Suzuki 2016 15
  8. Development I will cover ... - Managing Libraries - Testing

    - Beta Distributing - Shipping © Toshihiro Suzuki 2016 17
  9. Carthage $ cat Cartfile github "ReactiveKit/ReactiveUIKit" "master" github "ReactiveKit/ReactiveKit" "master"

    github "ReactiveKit/ReactiveFoundation" "master" github "rs/SDWebImage" "master" github "ReactKit/SwiftState" ~> 4.0.0 github "cbpowell/MarqueeLabel-Swift" github "duemunk/Async" github "ikesyo/Himotoki" ~> 1.5 github "ishkawa/APIKit" ~> 1.1.2 github "realm/realm-cocoa" github "radex/SwiftyUserDefaults" "master" github "malcommac/SwiftDate" I checkin Carthage/Build/tvOS to repo. Update once in a while. ! git history data gets larger " CI build is fast © Toshihiro Suzuki 2016 19
  10. Plain XCTest and UITest 4 runs on Bitrise on every

    git-push 4 mostly tests for models 4 trying to write some for PlayerViewController © Toshihiro Suzuki 2016 23
  11. PlayerViewControllerTests.swift func test003DidAppear() { let root = UIViewController() let nav

    = UINavigationController(rootViewController: root) UIApplication.sharedApplication().keyWindow?.rootViewController = nav let ex = expectationWithDescription("PlayerViewController viewDidAppear") nav.presentViewController(vc, animated: true) {[unowned self] in XCTAssert(self.vc.machine.state == .Preparing) ex.fulfill() } waitForExpectationsWithTimeout(2.0, handler: nil) } © Toshihiro Suzuki 2016 24
  12. UITest fails a lot due to 4 Server introduced API

    bug 4 assertionFailure() or fatalError() 4 Unstable Simulator © Toshihiro Suzuki 2016 26
  13. Solution for force crashing /// Calls assertionFailure unless isRunningTests() is

    true /// This is useful in such case like when /// unstable API causes UITests failure. (which happens like always...) /// - parameter msg: func assertionError(msg: String = "") { if !isRunningTests() { assertionFailure(msg) } } © Toshihiro Suzuki 2016 27
  14. isRunningTests() /// Detects if app is running xctest /// -

    returns: true if running xctest func isRunningTests() -> Bool { let env = NSProcessInfo.processInfo().environment if let _ = env["UITest"] { return true } if let path = env["XCInjectBundle"] { return NSString(string: path).pathExtension == "xctest" } return false } © Toshihiro Suzuki 2016 28
  15. "UITest" env variable /// HogeUITests.swift func setup() { ... let

    app = XCUIApplication() app.launchEnvironment["UITest"] = "" © Toshihiro Suzuki 2016 29
  16. tvOS Simulator often hangs up Also, DerivedData causes weird compile

    errors sometimes © Toshihiro Suzuki 2016 30
  17. Solution # ~/.bashrc export DERIVED=~/Library/Developer/Xcode/DerivedData alias resetd='rm -rf $DERIVED/*' alias

    resetdd='resetd && snapshot reset_simulators' export SNAPSHOT_FORCE_DELETE=true I run this at least 10 times a day. © Toshihiro Suzuki 2016 31
  18. Makefile TEST_DESTINATION=-destination "platform=tvOS Simulator,name=Apple TV 1080p,OS=latest" TEST=xcodebuild $(XCODEFLAGS) -scheme $(SCHEME)

    clean test $(TEST_DESTINATION) .PHONY: test beta release archive clean ipa-beta ipa ship test: set -o pipefail $(TEST) © Toshihiro Suzuki 2016 36
  19. Makefile archive: ./script/check-xcode-version.sh if [ $? -ne 0 ];then exit

    1;fi ./script/prepare_for_release.sh if [ ! -d $(BUILD_DIR)/script ];then mkdir -p $(BUILD_DIR)/script;fi xcodebuild -project $(PROJECT).xcodeproj -scheme $(SCHEME) \ -destination "generic/platform=tvOS" \ -xcconfig ./config/App-tvOS.xcconfig \ -archivePath $(ARCHIVE_PATH) \ PROVISIONING_PROFILE=$(PROVISIONING_PROFILE) \ -verbose \ archive | xcpretty --color ipa: xcodebuild -exportArchive -archivePath $(ARCHIVE_PATH) -exportPath $(BUILD_DIR) \ -exportOptionsPlist $(EXPORT_OPTION_PLIST) \ PROVISIONING_PROFILE=$(PROVISIONING_PROFILE) \ -destination "generic/platform=tvOS" © Toshihiro Suzuki 2016 37
  20. cmake is actually useful Comparing to fastlane, - less dependencies

    (plain xcodebuild commands) - runs faster It gets the job done. © Toshihiro Suzuki 2016 38
  21. GitHub release page fastlane ios upload ipa:$(IPA_PATH) My boss will

    download this app and hand it to testers. © Toshihiro Suzuki 2016 41
  22. How to install a beta app to device You always

    need a Xcode © Toshihiro Suzuki 2016 42
  23. make ship (haven't shipped yet) 4 Create ipa. 4 Copy

    howtobuild.txt and Makefile. 4 Zip all of above and ship it to customer. 4 A Resign.sh is embedded. Looks like sigh resign works for tvOS, too. Detailed post in Japanese © Toshihiro Suzuki 2016 44
  24. Use typealias for important types typealias JSON = [String: AnyObject]

    typealias ProductId = String typealias GenreId = String struct Product: Decodable { let productId: ProductId? let productQualityType: ProductQuality? © Toshihiro Suzuki 2016 49
  25. Write comment, write tests You will forget everything in next

    week. I guarantee. © Toshihiro Suzuki 2016 50
  26. It's okay. enum RequestSortType: Int { case ৽ணॱ = 1,

    ̑̌Իॱ = 3, ਓؾॱ = 4 } switch sortType { case .৽ணॱ: break case .̑̌Իॱ: break case .ਓؾॱ: break } © Toshihiro Suzuki 2016 51
  27. Reactive // ReactiveKit (going to switch to RxSwift) func startLaunchSequence()

    { combineLatest(validateDeviceTime, agreement, updateDatabase()) .observe(on: ImmediateExecutionContext) {[weak self] e in switch e { case .Next(let value): LOG("next: \(value)") case .Failure(let error): LOG("error: \(error)") self?.launchCompletion(.Failure(error)) case .Success: LOG("success") self?.launchCompletion(.Success()) } }.disposeIn(rbag) } © Toshihiro Suzuki 2016 52
  28. Separate public APIs into small extensions // MARK: Public API

    extension APICacheBatch { static var CompletedNotification = "APICacheBatchCompletedNotification" static func updateAllImmediately() { sharedInsance.updateAll(force: true) } } © Toshihiro Suzuki 2016 53
  29. Wrap Up what it means to be a tvOS developer

    4 daily development 4 codebase © Toshihiro Suzuki 2016 54
  30. BTW, if you want a TVML and native hybrid tvOS

    app I've heard of TVMLKitchen. © Toshihiro Suzuki 2016 60