diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3e8f379 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,74 @@ +name: Build + +on: + push: + paths-ignore: + - 'README.md' + - 'CHANGES.md' + - 'LICENSE' + schedule: + - cron: "0 0 * * *" + +jobs: + build: + runs-on: macOS-latest + env: + XCODE: /Applications/Xcode_12.4.app + XCODE_SDK: iphoneos14.4 + steps: + - uses: actions/checkout@v2 + - name: Select Xcode Version + run: sudo xcode-select -s '${{ env.XCODE }}/Contents/Developer' + - name: Show Xcode Version + run: xcodebuild -version + - name: Show CocoaPods Version + run: pod --version + - name: Restore Pods + uses: actions/cache@v2 + with: + path: Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: Install Dependences + run: | + pod repo update + pod install + - name: Create Environment.swift + run: cp SoraQuickStart/Environment.example.swift SoraQuickStart/Environment.swift + - name: Build Xcode Project + run: | + set -o pipefail && \ + xcodebuild \ + -workspace 'SoraQuickStart.xcworkspace' \ + -scheme 'SoraQuickStart' \ + -sdk ${{ env.XCODE_SDK }} \ + -arch arm64 \ + -configuration Release \ + -derivedDataPath build \ + clean build \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGNING_ALLOWED=NO \ + CODE_SIGN_IDENTITY= \ + PROVISIONING_PROFILE= + - name: Check uncommitted unformatted code + run: | + ./lint-format.sh + release: + if: contains(github.ref, 'tags/v') + needs: [build] + runs-on: macOS-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Create Release + id: create_release + uses: actions/create-release@v1.0.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + diff --git a/.gitignore b/.gitignore index 68b7148..5a9b36e 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ fastlane/screenshots *.swp doc *.xcworkspace +Environment.swift diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..7acd1cb --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +5.5.1 diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 0000000..2c72698 --- /dev/null +++ b/.swiftformat @@ -0,0 +1,8 @@ +--exclude Pods +--indent 4 +--semicolons inline +--trailingclosures +--wrapparameters after-first +--header strip + +--disable redundantInit,sortedSwitchCases,strongOutlets,unusedArguments,wrapSwitchCases diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..fd1e8a3 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,41 @@ +included: + - SoraQuickStart +excluded: + - Pods +disabled_rules: + - identifier_name + - force_cast + - force_try + - cyclomatic_complexity + - function_body_length + - file_length + - line_length + - type_body_length + - weak_delegate + - opening_brace + - closing_brace + - anonymous_argument_in_multiline_closure + - conditional_returns_on_newline + - multiline_arguments + - multiline_arguments_brackets + - multiline_literal_brackets + - multiline_parameters + - multiline_parameters_brackets + - vertical_parameter_alignment + - vertical_parameter_alignment_on_call + - vertical_whitespace + - vertical_whitespace_between_cases + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - colon + - comma + - comment_spacing + - trailing_comma + - trailing_newline + - trailing_whitespace + - closure_parameter_position + - closure_end_indentation + - closure_spacing + - for_where + - large_tuple + - todo \ No newline at end of file diff --git a/Podfile b/Podfile index 739e209..d35aa83 100644 --- a/Podfile +++ b/Podfile @@ -1,10 +1,13 @@ +source 'https://cdn.cocoapods.org/' source 'https://github.com/shiguredo/sora-ios-sdk-specs.git' -source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '12.1' +platform :ios, '13.0' target 'SoraQuickStart' do use_frameworks! - pod 'Sora', '2021.3.1' + pod 'Sora', '2022.1.0' + + pod 'SwiftLint' + pod 'SwiftFormat/CLI' end diff --git a/README.md b/README.md index 8939e88..98c7568 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ Please read https://github.com/shiguredo/oss before use. ## システム条件 -- iOS 12.1 以降 +- iOS 13 以降 - アーキテクチャ arm64, x86_64 (シミュレーターの動作は未保証) -- macOS 12.0 以降 -- Xcode 13.1 -- Swift 5.5 +- macOS 12.2 以降 +- Xcode 13.2 +- Swift 5.5.2 - CocoaPods 1.11.2 以降 -- WebRTC SFU Sora 2021.1 以降 +- WebRTC SFU Sora 2021.2 以降 Xcode と Swift のバージョンによっては、 Carthage と CocoaPods で取得できるバイナリに互換性がない可能性があります。詳しくは[ Sora iOS SDK ドキュメント](https://sora-ios-sdk.shiguredo.jp/) を参照してください。 @@ -34,4 +34,6 @@ Xcode と Swift のバージョンによっては、 Carthage と CocoaPods で $ pod install ``` -2. ``SoraQuickStart.xcworkspace`` を Xcode で開いてビルドします。 +2. ``SoraQuickStart/Environment.example.swift`` のファイル名を ``SoraQuickStart/Environment.swift`` に変更し、接続情報を設定します。 + +3. ``SoraQuickStart.xcworkspace`` を Xcode で開いてビルドします。 diff --git a/SoraQuickStart.xcodeproj/project.pbxproj b/SoraQuickStart.xcodeproj/project.pbxproj index cb3f9e5..1571d10 100644 --- a/SoraQuickStart.xcodeproj/project.pbxproj +++ b/SoraQuickStart.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 91169197273126A80098FBFF /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91169196273126A80098FBFF /* Environment.swift */; }; 91A4844226F9BB5100C18B76 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A4844126F9BB5100C18B76 /* AppDelegate.swift */; }; 91A4844426F9BB5100C18B76 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A4844326F9BB5100C18B76 /* SceneDelegate.swift */; }; 91A4844626F9BB5100C18B76 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91A4844526F9BB5100C18B76 /* ViewController.swift */; }; @@ -16,6 +17,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 91169196273126A80098FBFF /* Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; 91A4843E26F9BB5100C18B76 /* SoraQuickStart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SoraQuickStart.app; sourceTree = BUILT_PRODUCTS_DIR; }; 91A4844126F9BB5100C18B76 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 91A4844326F9BB5100C18B76 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -63,6 +65,7 @@ 91A4844A26F9BB5100C18B76 /* Assets.xcassets */, 91A4844C26F9BB5100C18B76 /* LaunchScreen.storyboard */, 91A4844F26F9BB5100C18B76 /* Info.plist */, + 91169196273126A80098FBFF /* Environment.swift */, ); path = SoraQuickStart; sourceTree = ""; @@ -74,6 +77,8 @@ isa = PBXNativeTarget; buildConfigurationList = 91A4845226F9BB5100C18B76 /* Build configuration list for PBXNativeTarget "SoraQuickStart" */; buildPhases = ( + 915772F6274E183500A17984 /* Run SwiftFormat */, + 915772F7274E184100A17984 /* Run SwiftLint */, 91A4843A26F9BB5100C18B76 /* Sources */, 91A4843B26F9BB5100C18B76 /* Frameworks */, 91A4843C26F9BB5100C18B76 /* Resources */, @@ -132,12 +137,52 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 915772F6274E183500A17984 /* Run SwiftFormat */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SwiftFormat"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which \"${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat\" >/dev/null; then\n \"${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat\" \"$SRCROOT\"\nelse\n echo \"warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat\"\nfi\n"; + }; + 915772F7274E184100A17984 /* Run SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SwiftLint"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which \"${PODS_ROOT}/SwiftLint/swiftlint\" >/dev/null; then\n ${PODS_ROOT}/SwiftLint/swiftlint --fix\n ${PODS_ROOT}/SwiftLint/swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 91A4843A26F9BB5100C18B76 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 91A4844626F9BB5100C18B76 /* ViewController.swift in Sources */, + 91169197273126A80098FBFF /* Environment.swift in Sources */, 91A4844226F9BB5100C18B76 /* AppDelegate.swift in Sources */, 91A4844426F9BB5100C18B76 /* SceneDelegate.swift in Sources */, ); diff --git a/SoraQuickStart/AppDelegate.swift b/SoraQuickStart/AppDelegate.swift index 34ca27d..0954a6f 100644 --- a/SoraQuickStart/AppDelegate.swift +++ b/SoraQuickStart/AppDelegate.swift @@ -2,12 +2,9 @@ import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. - return true + true } // MARK: UISceneSession Lifecycle @@ -15,7 +12,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { @@ -23,7 +20,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - - } - diff --git a/SoraQuickStart/Environment.example.swift b/SoraQuickStart/Environment.example.swift new file mode 100644 index 0000000..71f8a24 --- /dev/null +++ b/SoraQuickStart/Environment.example.swift @@ -0,0 +1,11 @@ +import Foundation + +enum Environment { + + // 接続するサーバーのシグナリング URL + static let url = URL(string: "wss://sora.example.com/signaling")! + + // チャネル ID + static let channelId = "sora" + +} diff --git a/SoraQuickStart/SceneDelegate.swift b/SoraQuickStart/SceneDelegate.swift index 8778aa8..44a4ad5 100644 --- a/SoraQuickStart/SceneDelegate.swift +++ b/SoraQuickStart/SceneDelegate.swift @@ -1,10 +1,8 @@ import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { - var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -39,7 +37,4 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // Use this method to save data, release shared resources, and store enough scene-specific state information // to restore the scene back to its current state. } - - } - diff --git a/SoraQuickStart/ViewController.swift b/SoraQuickStart/ViewController.swift index 30fe354..7259455 100644 --- a/SoraQuickStart/ViewController.swift +++ b/SoraQuickStart/ViewController.swift @@ -1,14 +1,7 @@ -import UIKit import Sora - -// 接続するサーバーのシグナリング URL -let soraURL = URL(string: "wss://sora.example.com/signaling")! - -// チャネル ID -let soraChannelId = "sora" +import UIKit class ViewController: UIViewController { - @IBOutlet weak var senderVideoView: VideoView! @IBOutlet weak var receiverVideoView: VideoView! @IBOutlet weak var connectImageView: UIImageView! @@ -27,8 +20,8 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() Logger.shared.level = .debug - - navigationItem.title = "\(soraChannelId)" + + navigationItem.title = "\(Environment.channelId)" } // 接続ボタンの UI を更新します。 @@ -66,11 +59,11 @@ class ViewController: UIViewController { func connect() { // 接続の設定を行います。 - let config = Configuration(url: soraURL, - channelId: soraChannelId, + let config = Configuration(url: Environment.url, + channelId: Environment.channelId, role: .sendrecv, multistreamEnabled: true) - + // ストリームが追加されたら受信用の VideoView をストリームにセットします。 // このアプリでは、複数のユーザーが接続した場合は最後のユーザーの映像のみ描画します。 let publisherStreamId = config.publisherStreamId @@ -113,6 +106,4 @@ class ViewController: UIViewController { } } } - } - diff --git a/lint-format.sh b/lint-format.sh new file mode 100755 index 0000000..834377c --- /dev/null +++ b/lint-format.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# ローカルで lint と formatter を実行するスクリプト +# 未フォーマットか lint でルール違反を検出したら終了ステータス 1 を返す +# GitHub Actions では未フォーマット箇所の有無の確認に使う + +PODS_ROOT=Pods +SRCROOT=. +FORMAT=${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat +LINT=${PODS_ROOT}/SwiftLint/swiftlint + +# フォーマットの必要性を確認する +$FORMAT --lint $SRCROOT +format=$? + +$FORMAT $SRCROOT +$LINT --fix $SRCROOT +$LINT $SRCROOT +lint=$? + +test $format -eq 0 -a $lint -eq 0 +exit $? \ No newline at end of file