diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..033e079 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +## Fastlane +*.mobileprovision +*.cer +*.ipa +*.certSigningRequest +*.dSYM.zip +fastlane/report.xml + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint +*.p12 +*.dropbox +rvm.env + +## Obj-C/Swift specific +*.hmap +*.ipa \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e26547a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# rdar Changelog + +All notable changes to this project will be documented in this file. +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] +### Added +- Project init +- Radar model, RadarURLParser, RadarURLBuilder protocols and implementation +- RadarOption and BrowserOption +- Basic UI architecture diff --git a/README.md b/README.md new file mode 100644 index 0000000..83837d9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# rdar diff --git a/rdar.xcodeproj/project.pbxproj b/rdar.xcodeproj/project.pbxproj index 81a9758..122fb33 100644 --- a/rdar.xcodeproj/project.pbxproj +++ b/rdar.xcodeproj/project.pbxproj @@ -8,12 +8,26 @@ /* Begin PBXBuildFile section */ 6C07270C20CDC70300603199 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07270B20CDC70300603199 /* AppDelegate.swift */; }; - 6C07270E20CDC70300603199 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07270D20CDC70300603199 /* ViewController.swift */; }; 6C07271120CDC70300603199 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C07270F20CDC70300603199 /* Main.storyboard */; }; 6C07271320CDC70600603199 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C07271220CDC70600603199 /* Assets.xcassets */; }; 6C07271620CDC70600603199 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C07271420CDC70600603199 /* LaunchScreen.storyboard */; }; - 6C07272120CDC70600603199 /* rdarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07272020CDC70600603199 /* rdarTests.swift */; }; 6C07272C20CDC70600603199 /* rdarUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07272B20CDC70600603199 /* rdarUITests.swift */; }; + 6C07273A20CDCA5300603199 /* RadarOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07273920CDCA5300603199 /* RadarOption.swift */; }; + 6C07273C20CF692800603199 /* UserDefaults+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07273B20CF692800603199 /* UserDefaults+Extension.swift */; }; + 6C07273E20CF6C0D00603199 /* BrowserOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07273D20CF6C0D00603199 /* BrowserOption.swift */; }; + 6C07274020CF6C7700603199 /* Radar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07273F20CF6C7700603199 /* Radar.swift */; }; + 6C07274220CF6CD000603199 /* AppleRadar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274120CF6CD000603199 /* AppleRadar.swift */; }; + 6C07274420CF6CDB00603199 /* OpenRadar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274320CF6CDB00603199 /* OpenRadar.swift */; }; + 6C07274620CF6CF000603199 /* RadarURLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274520CF6CF000603199 /* RadarURLBuilder.swift */; }; + 6C07274820CF73C900603199 /* RadarURLParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274720CF73C900603199 /* RadarURLParser.swift */; }; + 6C07274C20CF801100603199 /* AppleRadarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274B20CF801100603199 /* AppleRadarTests.swift */; }; + 6C07274E20CF803300603199 /* OpenRadarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07274D20CF803300603199 /* OpenRadarTests.swift */; }; + 6C07275D20CFA81100603199 /* Recent.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C07275C20CFA81100603199 /* Recent.storyboard */; }; + 6C07276120CFA86C00603199 /* Favorites.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C07276020CFA86C00603199 /* Favorites.storyboard */; }; + 6C07276320CFA8A200603199 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C07276220CFA8A200603199 /* Settings.storyboard */; }; + 6C07276B20CFA90400603199 /* RecentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07276A20CFA90400603199 /* RecentViewController.swift */; }; + 6C07276D20CFA90E00603199 /* FavoritesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07276C20CFA90E00603199 /* FavoritesViewController.swift */; }; + 6C07276F20CFA91800603199 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C07276E20CFA91800603199 /* SettingsViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -36,17 +50,33 @@ /* Begin PBXFileReference section */ 6C07270820CDC70300603199 /* rdar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = rdar.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6C07270B20CDC70300603199 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 6C07270D20CDC70300603199 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 6C07271020CDC70300603199 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 6C07271220CDC70600603199 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6C07271520CDC70600603199 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 6C07271720CDC70600603199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6C07271720CDC70600603199 /* rdar-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "rdar-Info.plist"; sourceTree = ""; }; 6C07271C20CDC70600603199 /* rdarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = rdarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6C07272020CDC70600603199 /* rdarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = rdarTests.swift; sourceTree = ""; }; - 6C07272220CDC70600603199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6C07272220CDC70600603199 /* rdarTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "rdarTests-Info.plist"; sourceTree = ""; }; 6C07272720CDC70600603199 /* rdarUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = rdarUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6C07272B20CDC70600603199 /* rdarUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = rdarUITests.swift; sourceTree = ""; }; - 6C07272D20CDC70600603199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6C07272D20CDC70600603199 /* rdarUITests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "rdarUITests-Info.plist"; sourceTree = ""; }; + 6C07273920CDCA5300603199 /* RadarOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarOption.swift; sourceTree = ""; }; + 6C07273B20CF692800603199 /* UserDefaults+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Extension.swift"; sourceTree = ""; }; + 6C07273D20CF6C0D00603199 /* BrowserOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserOption.swift; sourceTree = ""; }; + 6C07273F20CF6C7700603199 /* Radar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Radar.swift; sourceTree = ""; }; + 6C07274120CF6CD000603199 /* AppleRadar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleRadar.swift; sourceTree = ""; }; + 6C07274320CF6CDB00603199 /* OpenRadar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenRadar.swift; sourceTree = ""; }; + 6C07274520CF6CF000603199 /* RadarURLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarURLBuilder.swift; sourceTree = ""; }; + 6C07274720CF73C900603199 /* RadarURLParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadarURLParser.swift; sourceTree = ""; }; + 6C07274B20CF801100603199 /* AppleRadarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleRadarTests.swift; sourceTree = ""; }; + 6C07274D20CF803300603199 /* OpenRadarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenRadarTests.swift; sourceTree = ""; }; + 6C07275C20CFA81100603199 /* Recent.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Recent.storyboard; sourceTree = ""; }; + 6C07276020CFA86C00603199 /* Favorites.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Favorites.storyboard; sourceTree = ""; }; + 6C07276220CFA8A200603199 /* Settings.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; + 6C07276A20CFA90400603199 /* RecentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentViewController.swift; sourceTree = ""; }; + 6C07276C20CFA90E00603199 /* FavoritesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesViewController.swift; sourceTree = ""; }; + 6C07276E20CFA91800603199 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; + 6C273FE120D01DCB001FD2F0 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; + 6C273FE220D01DEA001FD2F0 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -77,6 +107,8 @@ 6C0726FF20CDC70300603199 = { isa = PBXGroup; children = ( + 6C273FE120D01DCB001FD2F0 /* CHANGELOG.md */, + 6C273FE220D01DEA001FD2F0 /* README.md */, 6C07270A20CDC70300603199 /* rdar */, 6C07271F20CDC70600603199 /* rdarTests */, 6C07272A20CDC70600603199 /* rdarUITests */, @@ -97,12 +129,12 @@ 6C07270A20CDC70300603199 /* rdar */ = { isa = PBXGroup; children = ( - 6C07270B20CDC70300603199 /* AppDelegate.swift */, - 6C07270D20CDC70300603199 /* ViewController.swift */, - 6C07270F20CDC70300603199 /* Main.storyboard */, - 6C07271220CDC70600603199 /* Assets.xcassets */, - 6C07271420CDC70600603199 /* LaunchScreen.storyboard */, - 6C07271720CDC70600603199 /* Info.plist */, + 6C07277120CFB3B200603199 /* App */, + 6C07275920CFA51B00603199 /* Model */, + 6C07275E20CFA82300603199 /* Recent */, + 6C07275F20CFA84900603199 /* Favorites */, + 6C07275A20CFA53400603199 /* Settings */, + 6C07277020CFB39800603199 /* Resources */, ); path = rdar; sourceTree = ""; @@ -110,8 +142,9 @@ 6C07271F20CDC70600603199 /* rdarTests */ = { isa = PBXGroup; children = ( - 6C07272020CDC70600603199 /* rdarTests.swift */, - 6C07272220CDC70600603199 /* Info.plist */, + 6C07274B20CF801100603199 /* AppleRadarTests.swift */, + 6C07274D20CF803300603199 /* OpenRadarTests.swift */, + 6C07272220CDC70600603199 /* rdarTests-Info.plist */, ); path = rdarTests; sourceTree = ""; @@ -120,11 +153,72 @@ isa = PBXGroup; children = ( 6C07272B20CDC70600603199 /* rdarUITests.swift */, - 6C07272D20CDC70600603199 /* Info.plist */, + 6C07272D20CDC70600603199 /* rdarUITests-Info.plist */, ); path = rdarUITests; sourceTree = ""; }; + 6C07275920CFA51B00603199 /* Model */ = { + isa = PBXGroup; + children = ( + 6C07273F20CF6C7700603199 /* Radar.swift */, + 6C07274720CF73C900603199 /* RadarURLParser.swift */, + 6C07274520CF6CF000603199 /* RadarURLBuilder.swift */, + 6C07274120CF6CD000603199 /* AppleRadar.swift */, + 6C07274320CF6CDB00603199 /* OpenRadar.swift */, + 6C07273D20CF6C0D00603199 /* BrowserOption.swift */, + 6C07273920CDCA5300603199 /* RadarOption.swift */, + 6C07273B20CF692800603199 /* UserDefaults+Extension.swift */, + ); + path = Model; + sourceTree = ""; + }; + 6C07275A20CFA53400603199 /* Settings */ = { + isa = PBXGroup; + children = ( + 6C07276220CFA8A200603199 /* Settings.storyboard */, + 6C07276E20CFA91800603199 /* SettingsViewController.swift */, + ); + path = Settings; + sourceTree = ""; + }; + 6C07275E20CFA82300603199 /* Recent */ = { + isa = PBXGroup; + children = ( + 6C07275C20CFA81100603199 /* Recent.storyboard */, + 6C07276A20CFA90400603199 /* RecentViewController.swift */, + ); + path = Recent; + sourceTree = ""; + }; + 6C07275F20CFA84900603199 /* Favorites */ = { + isa = PBXGroup; + children = ( + 6C07276020CFA86C00603199 /* Favorites.storyboard */, + 6C07276C20CFA90E00603199 /* FavoritesViewController.swift */, + ); + path = Favorites; + sourceTree = ""; + }; + 6C07277020CFB39800603199 /* Resources */ = { + isa = PBXGroup; + children = ( + 6C07271220CDC70600603199 /* Assets.xcassets */, + 6C07271420CDC70600603199 /* LaunchScreen.storyboard */, + 6C07270F20CDC70300603199 /* Main.storyboard */, + 6C07271720CDC70600603199 /* rdar-Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + 6C07277120CFB3B200603199 /* App */ = { + isa = PBXGroup; + children = ( + 6C07270B20CDC70300603199 /* AppDelegate.swift */, + ); + path = App; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -230,7 +324,10 @@ buildActionMask = 2147483647; files = ( 6C07271620CDC70600603199 /* LaunchScreen.storyboard in Resources */, + 6C07275D20CFA81100603199 /* Recent.storyboard in Resources */, 6C07271320CDC70600603199 /* Assets.xcassets in Resources */, + 6C07276320CFA8A200603199 /* Settings.storyboard in Resources */, + 6C07276120CFA86C00603199 /* Favorites.storyboard in Resources */, 6C07271120CDC70300603199 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -256,7 +353,17 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6C07270E20CDC70300603199 /* ViewController.swift in Sources */, + 6C07274220CF6CD000603199 /* AppleRadar.swift in Sources */, + 6C07274820CF73C900603199 /* RadarURLParser.swift in Sources */, + 6C07276B20CFA90400603199 /* RecentViewController.swift in Sources */, + 6C07274020CF6C7700603199 /* Radar.swift in Sources */, + 6C07273A20CDCA5300603199 /* RadarOption.swift in Sources */, + 6C07274620CF6CF000603199 /* RadarURLBuilder.swift in Sources */, + 6C07273C20CF692800603199 /* UserDefaults+Extension.swift in Sources */, + 6C07273E20CF6C0D00603199 /* BrowserOption.swift in Sources */, + 6C07274420CF6CDB00603199 /* OpenRadar.swift in Sources */, + 6C07276F20CFA91800603199 /* SettingsViewController.swift in Sources */, + 6C07276D20CFA90E00603199 /* FavoritesViewController.swift in Sources */, 6C07270C20CDC70300603199 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -265,7 +372,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6C07272120CDC70600603199 /* rdarTests.swift in Sources */, + 6C07274E20CF803300603199 /* OpenRadarTests.swift in Sources */, + 6C07274C20CF801100603199 /* AppleRadarTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -316,6 +424,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -363,7 +472,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -376,6 +485,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -417,7 +527,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -432,7 +542,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdar/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/rdar/Resources/rdar-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -450,7 +560,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdar/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/rdar/Resources/rdar-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -469,7 +579,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdarTests/Info.plist; + INFOPLIST_FILE = "rdarTests/rdarTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -490,7 +600,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdarTests/Info.plist; + INFOPLIST_FILE = "rdarTests/rdarTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -510,7 +620,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdarUITests/Info.plist; + INFOPLIST_FILE = "rdarUITests/rdarUITests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -530,7 +640,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = SE9N6X5V7C; - INFOPLIST_FILE = rdarUITests/Info.plist; + INFOPLIST_FILE = "rdarUITests/rdarUITests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/rdar.xcodeproj/xcuserdata/ethanhuang.xcuserdatad/xcschemes/xcschememanagement.plist b/rdar.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 57% rename from rdar.xcodeproj/xcuserdata/ethanhuang.xcuserdatad/xcschemes/xcschememanagement.plist rename to rdar.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index a39d756..3ddf867 100644 --- a/rdar.xcodeproj/xcuserdata/ethanhuang.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/rdar.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -2,13 +2,7 @@ - SchemeUserState - - rdar.xcscheme - - orderHint - 0 - - + BuildSystemType + Latest diff --git a/rdar.xcodeproj/xcshareddata/xcschemes/rdar.xcscheme b/rdar.xcodeproj/xcshareddata/xcschemes/rdar.xcscheme new file mode 100644 index 0000000..4bb72af --- /dev/null +++ b/rdar.xcodeproj/xcshareddata/xcschemes/rdar.xcscheme @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar.xcodeproj/xcshareddata/xcschemes/rdarTests.xcscheme b/rdar.xcodeproj/xcshareddata/xcschemes/rdarTests.xcscheme new file mode 100644 index 0000000..36114e5 --- /dev/null +++ b/rdar.xcodeproj/xcshareddata/xcschemes/rdarTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/AppDelegate.swift b/rdar/App/AppDelegate.swift similarity index 79% rename from rdar/AppDelegate.swift rename to rdar/App/AppDelegate.swift index 7fd02d4..fccbc4e 100644 --- a/rdar/AppDelegate.swift +++ b/rdar/App/AppDelegate.swift @@ -41,6 +41,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } + // MARK: - URL Scheme + + func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { + if let radar = Radar(url: url) { + switch UserDefaults.standard.browserOption { + case .safari: + app.open(radar.url(by: UserDefaults.standard.radarOption), options: [:]) { (success) in + + } + case .sfvc: + // TODO: + break + } + + return true + } else { + return false + } + } } diff --git a/rdar/Base.lproj/Main.storyboard b/rdar/Base.lproj/Main.storyboard deleted file mode 100644 index 03c13c2..0000000 --- a/rdar/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rdar/Favorites/Favorites.storyboard b/rdar/Favorites/Favorites.storyboard new file mode 100644 index 0000000..03e3b2b --- /dev/null +++ b/rdar/Favorites/Favorites.storyboard @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/Favorites/FavoritesViewController.swift b/rdar/Favorites/FavoritesViewController.swift new file mode 100644 index 0000000..a2d3800 --- /dev/null +++ b/rdar/Favorites/FavoritesViewController.swift @@ -0,0 +1,97 @@ +// +// FavoritesViewController.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import UIKit + +class FavoritesViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + navigationItem.title = "Favorites" + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/rdar/Favorites/Favorite~.storyboard b/rdar/Favorites/Favorite~.storyboard new file mode 100644 index 0000000..a2c5fb3 --- /dev/null +++ b/rdar/Favorites/Favorite~.storyboard @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/Model/AppleRadar.swift b/rdar/Model/AppleRadar.swift new file mode 100644 index 0000000..4f3b850 --- /dev/null +++ b/rdar/Model/AppleRadar.swift @@ -0,0 +1,27 @@ +// +// AppleRadar.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +struct AppleRadar: RadarURLParser & RadarURLBuilder { + static func parse(_ url: URL) -> Radar? { + if url.scheme?.hasPrefix("http") == true, + url.host == "bugreport.apple.com", + url.path.hasPrefix("/web"), + url.lastPathComponent.hasPrefix("problemID=") { + let id = url.lastPathComponent.replacingOccurrences(of: "problemID=", with: "") + return Radar(id: id) + } else { + return nil + } + } + + static func buildURL(from radar: Radar) -> URL { + return URL(string: "https://bugreport.apple.com/web/problemID=\(radar.id)")! + } +} diff --git a/rdar/Model/BrowserOption.swift b/rdar/Model/BrowserOption.swift new file mode 100644 index 0000000..5173254 --- /dev/null +++ b/rdar/Model/BrowserOption.swift @@ -0,0 +1,14 @@ +// +// BrowserOption.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +enum BrowserOption: Int { + case safari + case sfvc +} diff --git a/rdar/Model/OpenRadar.swift b/rdar/Model/OpenRadar.swift new file mode 100644 index 0000000..8d344b0 --- /dev/null +++ b/rdar/Model/OpenRadar.swift @@ -0,0 +1,33 @@ +// +// OpenRadar.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +struct OpenRadar: RadarURLParser & RadarURLBuilder { + static func parse(_ url: URL) -> Radar? { + if url.scheme == "rdar", + let id = url.host, + id == String(Int(id) ?? -1) { + return Radar(id: id) + } else if url.scheme?.hasPrefix("http") == true, + url.host == "openradar.appspot.com", + url.lastPathComponent == String(Int(url.lastPathComponent) ?? -1) { + return Radar(id: url.lastPathComponent) + } else if url.scheme?.hasPrefix("http") == true, + url.host?.hasSuffix("openradar.me") == true, + url.lastPathComponent == String(Int(url.lastPathComponent) ?? -1) { + return Radar(id: url.lastPathComponent) + } else { + return nil + } + } + + static func buildURL(from radar: Radar) -> URL { + return URL(string: "https://openradar.appspot.com/\(radar.id)")! + } +} diff --git a/rdar/Model/Radar.swift b/rdar/Model/Radar.swift new file mode 100644 index 0000000..17fc51b --- /dev/null +++ b/rdar/Model/Radar.swift @@ -0,0 +1,36 @@ +// +// Radar.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +struct Radar { + let id: String + + init?(url: URL) { + if let radar = OpenRadar.parse(url) { + self = radar + } else if let radar = AppleRadar.parse(url) { + self = radar + } else { + return nil + } + } + + init(id: String) { + self.id = id + } + + func url(by radarOption: RadarOption) -> URL { + switch radarOption { + case .appleRadar: + return AppleRadar.buildURL(from: self) + case .openRadar: + return OpenRadar.buildURL(from: self) + } + } +} diff --git a/rdar/Model/RadarOption.swift b/rdar/Model/RadarOption.swift new file mode 100644 index 0000000..faa77a1 --- /dev/null +++ b/rdar/Model/RadarOption.swift @@ -0,0 +1,14 @@ +// +// RadarOpener.swift +// rdar +// +// Created by Ethanhuang on 2018/6/10. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +enum RadarOption: Int { + case openRadar + case appleRadar +} diff --git a/rdar/Model/RadarURLBuilder.swift b/rdar/Model/RadarURLBuilder.swift new file mode 100644 index 0000000..eb1f667 --- /dev/null +++ b/rdar/Model/RadarURLBuilder.swift @@ -0,0 +1,13 @@ +// +// RadarURLBuilder.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +protocol RadarURLBuilder { + static func buildURL(from radar: Radar) -> URL +} diff --git a/rdar/Model/RadarURLParser.swift b/rdar/Model/RadarURLParser.swift new file mode 100644 index 0000000..6347568 --- /dev/null +++ b/rdar/Model/RadarURLParser.swift @@ -0,0 +1,13 @@ +// +// RadarURLParser.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +protocol RadarURLParser { + static func parse(_ url: URL) -> Radar? +} diff --git a/rdar/Model/UserDefaults+Extension.swift b/rdar/Model/UserDefaults+Extension.swift new file mode 100644 index 0000000..143e656 --- /dev/null +++ b/rdar/Model/UserDefaults+Extension.swift @@ -0,0 +1,32 @@ +// +// UserDefaults+Extension.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import Foundation + +extension UserDefaults { + private var browserKey: String { return "com.elaborapp.rdar.browserKey" } + private var radarKey: String { return "com.elaborapp.rdar.radarKey" } + + var browserOption: BrowserOption { + get { + return BrowserOption(rawValue: UserDefaults.standard.integer(forKey: browserKey)) ?? .safari + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: browserKey) + } + } + + var radarOption: RadarOption { + get { + return RadarOption(rawValue: UserDefaults.standard.integer(forKey: radarKey)) ?? .openRadar + } + set { + UserDefaults.standard.set(newValue.rawValue, forKey: radarKey) + } + } +} diff --git a/rdar/Recent/Recent.storyboard b/rdar/Recent/Recent.storyboard new file mode 100644 index 0000000..68bfe44 --- /dev/null +++ b/rdar/Recent/Recent.storyboard @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/Recent/RecentViewController.swift b/rdar/Recent/RecentViewController.swift new file mode 100644 index 0000000..94106ed --- /dev/null +++ b/rdar/Recent/RecentViewController.swift @@ -0,0 +1,97 @@ +// +// RecentViewController.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import UIKit + +class RecentViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + navigationItem.title = "Recent" + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/rdar/Assets.xcassets/AppIcon.appiconset/Contents.json b/rdar/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from rdar/Assets.xcassets/AppIcon.appiconset/Contents.json rename to rdar/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/rdar/Assets.xcassets/Contents.json b/rdar/Resources/Assets.xcassets/Contents.json similarity index 100% rename from rdar/Assets.xcassets/Contents.json rename to rdar/Resources/Assets.xcassets/Contents.json diff --git a/rdar/Base.lproj/LaunchScreen.storyboard b/rdar/Resources/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from rdar/Base.lproj/LaunchScreen.storyboard rename to rdar/Resources/Base.lproj/LaunchScreen.storyboard diff --git a/rdar/Resources/Base.lproj/Main.storyboard b/rdar/Resources/Base.lproj/Main.storyboard new file mode 100644 index 0000000..1f1aab2 --- /dev/null +++ b/rdar/Resources/Base.lproj/Main.storyboard @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/Info.plist b/rdar/Resources/rdar-Info.plist similarity index 82% rename from rdar/Info.plist rename to rdar/Resources/rdar-Info.plist index 16be3b6..6294b77 100644 --- a/rdar/Info.plist +++ b/rdar/Resources/rdar-Info.plist @@ -16,6 +16,21 @@ APPL CFBundleShortVersionString 1.0 + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLIconFile + + CFBundleURLName + rdar + CFBundleURLSchemes + + rdar + + + CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/rdar/Settings/Settings.storyboard b/rdar/Settings/Settings.storyboard new file mode 100644 index 0000000..3dd8754 --- /dev/null +++ b/rdar/Settings/Settings.storyboard @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rdar/Settings/SettingsViewController.swift b/rdar/Settings/SettingsViewController.swift new file mode 100644 index 0000000..02ada92 --- /dev/null +++ b/rdar/Settings/SettingsViewController.swift @@ -0,0 +1,97 @@ +// +// SettingsViewController.swift +// rdar +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import UIKit + +class SettingsViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + navigationItem.title = "Settings" + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destinationViewController. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/rdar/ViewController.swift b/rdar/ViewController.swift deleted file mode 100644 index cbb9821..0000000 --- a/rdar/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// rdar -// -// Created by Ethanhuang on 2018/6/10. -// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/rdar/zh-Hant.lproj/Main.strings b/rdar/zh-Hant.lproj/Main.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/rdar/zh-Hant.lproj/Main.strings @@ -0,0 +1 @@ + diff --git a/rdarTests/AppleRadarTests.swift b/rdarTests/AppleRadarTests.swift new file mode 100644 index 0000000..72e6a70 --- /dev/null +++ b/rdarTests/AppleRadarTests.swift @@ -0,0 +1,36 @@ +// +// AppleRadarTests.swift +// rdarTests +// +// Created by Ethanhuang on 2018/6/12. +// Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. +// + +import XCTest +@testable import rdar + +class AppleRadarTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testParseURL() { + let url = URL(string: "https://bugreport.apple.com/web/problemID=12345678")! + let radar = AppleRadar.parse(url) + XCTAssertNotNil(radar) + XCTAssert(radar?.id == "12345678") + } + + func testBuildURL() { + let radar = Radar(id: "12345678") + let url = AppleRadar.buildURL(from: radar) + XCTAssertEqual(url.absoluteString, "https://bugreport.apple.com/web/problemID=12345678") + } +} diff --git a/rdarTests/rdarTests.swift b/rdarTests/OpenRadarTests.swift similarity index 50% rename from rdarTests/rdarTests.swift rename to rdarTests/OpenRadarTests.swift index 7c4a10c..b39e2d0 100644 --- a/rdarTests/rdarTests.swift +++ b/rdarTests/OpenRadarTests.swift @@ -1,15 +1,15 @@ // -// rdarTests.swift +// OpenRadarTests.swift // rdarTests // -// Created by Ethanhuang on 2018/6/10. +// Created by Ethanhuang on 2018/6/12. // Copyright © 2018年 Elaborapp Co., Ltd. All rights reserved. // import XCTest @testable import rdar -class rdarTests: XCTestCase { +class OpenRadarTests: XCTestCase { override func setUp() { super.setUp() @@ -21,16 +21,16 @@ class rdarTests: XCTestCase { super.tearDown() } - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. + func testParseURL() { + let url = URL(string: "rdar://12345678")! + let radar = OpenRadar.parse(url) + XCTAssertNotNil(radar) + XCTAssert(radar?.id == "12345678") } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } + + func testBuildURL() { + let radar = Radar(id: "12345678") + let url = OpenRadar.buildURL(from: radar) + XCTAssertEqual(url.absoluteString, "https://openradar.appspot.com/12345678") } - } diff --git a/rdarTests/Info.plist b/rdarTests/rdarTests-Info.plist similarity index 100% rename from rdarTests/Info.plist rename to rdarTests/rdarTests-Info.plist diff --git a/rdarUITests/Info.plist b/rdarUITests/rdarUITests-Info.plist similarity index 100% rename from rdarUITests/Info.plist rename to rdarUITests/rdarUITests-Info.plist