100 Days of Swift & Hacking with iOS UIKit 版關鍵字重點整理

Paul Hudson 大大在網路上撰寫許多適合初學者學習的 iOS App 開發教材,彼得潘平時也常跟 Paul 學習。

想學習 iOS UIKit App 開發,Paul 的 100 Days of Swift & Hacking with iOS UIKit 版十分值得一讀。100 Days of Swift 包含了 30 個不同主題的 project。

Hacking with iOS 則包含 39 個 project,前 30 個是 100 Days of Swift 的 project,然後再加碼 9 個額外的 project。

有興趣的朋友可參考以上連結仔細研讀 Paul 的文章和影片,如果已有一定基礎,也可從 GitHub 下載專案的程式快速研究。

  • Paul 大大官方版的範例程式

HackingWithSwift 下分成 UIKit & SwiftUI 兩個版本,UIKit 版在資料夾 Classic 下。

  • Khumar 的範例程式

Pual 網頁上的教學有更新,不過官方 GitHub 的程式有些仍是舊的版本,新版可參考 Khumar 的連結。

最近彼得潘也花了點時間研究這 39 個專案,以下一一列出它們的關鍵字重點整理 & App 畫面,歡迎有興趣的朋友參考。

ps:

  • 彼得潘在整理關鍵字時,主要將它列在第一次出現的 project。比方 IBOutlet 初次出現在 project 1,因此將它列在 project 1,之後的 project 即使有用到 IBOutlet 也不會列出。
  • 39 個專案裡有 10 個跟遊戲相關的主題,跟 SpriteKit 技術有關。以下特別將這 10 個 project 的名稱加上(Game),對遊戲開發沒興趣的朋友可先跳過。
  • 39 個專案裡有許多技術是工作一兩年的 iOS 工程師也不一定會接觸的,想轉職新手 iOS App 工程師的朋友可先目標研究以下專案:

1~10,12~13,15~16,18~19,21,24,27~28,31~32,38。

Project 1: Storm Viewer

關鍵技術:

Xcode,project,UIKit,Interface Builder,storyboard,swift,UIViewController,title,viewDidLoad,viewWillAppear,viewWillDisappear,FileManager,Bundle.main,resourcePath,contentsOfDirectory,UITableViewController,data source,UITableView,UITableViewCell,delegate,UITableViewDataSource,UITableViewDelegate,tableView(_:numberOfRowsInSection:),tableView(_:cellForRowAt:),cell reuse id,dequeueReusableCell(withIdentifier:for:),IndexPath,row,textLabel,tableView(_:didSelectRowAt:),IBOutlet,UIImageView,aspect fit,UIImage,UINavigationController,navigationController,navigationBar,hidesBarsOnTap,pushViewController,storyboard id,instantiateViewController(withIdentifier:),prefersLargeTitles,navigationItem,largeTitleDisplayMode,Auto Layout,constraint

Project 2: Guess the Flag

關鍵技術:

asset catalogs,UIButton,append,setImage(_:for:),UIControlState,normal,UIView,CALayer,layer,borderWidth,borderColor,UIColor,CGColor,IBAction,tag,shuffle,random,UIAlertController,alert,UIAlertAction,addAction,present(_:animated:completion:),uppercased,2x,3x

Project 3: Social Media

關鍵技術:

UIBarButtonItem,rightBarButtonItem,#selector,@objc,UIActivityViewController,share,jpegData(compressionQuality:),popoverPresentationController?.barButtonItem,Info,Privacy — Photo Library Additions Usage Description

ps: 網頁的教學有更新,官方範例裡的 shareTapped 請更新成以下版本,並在 App 的 Info 頁面加入 Privacy — Photo Library Additions Usage Description。

@objc func shareTapped() {
guard let image = imageView.image?.jpegData(compressionQuality: 0.8) else {
print("No image found")
return
}
let vc = UIActivityViewController(activityItems: [image], applicationActivities: [])
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true)
}

Project 4: Easy Browser

關鍵技術:

WebKit,WKWebView,WKNavigationDelegate,loadView,URL,URLRequest,load,allowsBackForwardNavigationGestures,actionSheet,UIProgressView,sizeToFit,flexibleSpace,UIToolbar,toolbarItems,isToolbarHidden,KVO,key value observing,addObserver(_:forKeyPath:options:context:),#keyPath(WKWebView.estimatedProgress),webView(_:didFinish:),webView(_:decidePolicyFor:decisionHandler:),observeValue(forKeyPath:of:change:context:),contains

Project 5: Word Scramble

關鍵技術:

capture list,strong,weak,unowned,strong reference cycle,retain cycle,path(forResource:ofType:),String(contentsOfFile:),components(separatedBy:),randomElement,reloadData,addTextField,textFields,range(of:),firstIndex(of:),UITextChecker,rangeOfMisspelledWord,insertRows,lowercased,NSRange,NSNotFound,utf16

ps: 網頁的教學有更新,官方範例裡的 isPossible & isReal 請更新成以下版本。

func isPossible(word: String) -> Bool {
guard var tempWord = title?.lowercased() else { return false }
for letter in word {
if let position = tempWord.firstIndex(of: letter) {
tempWord.remove(at: position)
} else {
return false
}
}
return true
}
func isReal(word: String) -> Bool {
let checker = UITextChecker()
let range = NSRange(location: 0, length: word.utf16.count)
let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")
return misspelledRange.location == NSNotFound
}

Project 6: Auto Layout

關鍵技術:

addSubview,aspect ratio,NSLayoutConstraint,translatesAutoresizingMaskIntoConstraints,visual format language,constraints(withVisualFormat:options:metrics:views:),addConstraints,NSLayoutAnchor,constraint(equalTo:constant:),isActive,prefersStatusBarHidden

Project 7: Whitehouse Petitions

關鍵技術:

UITabBarController,Data,Data(contentsOf:),network,JSON,Codable,JSONDecoder,decode(_:from:),loadHTMLString(_:baseURL:),AppDelegate,application(_:didFinishLaunchingWithOptions:),UIWindow,window,rootViewController,UIStoryboard,UIStoryboard(name:bundle:),UITabBarItem,UITabBarItem(tabBarSystemItem:tag:),SceneDelegate,scene(_:willConnectTo:options:)

ps:

  • ViewController 裡記得改成以下網址
if navigationController?.tabBarItem.tag == 0 {
urlString = "https://www.hackingwithswift.com/samples/petitions-1.json"
} else {
urlString = "https://www.hackingwithswift.com/samples/petitions-2.json"
}
  • 新版 Xcode 專案多了 SceneDelegate.swift,請在 SceneDelegate 的 scene(_:willConnectTo:options:) 加入以下程式。
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
if let tabBarController = window?.rootViewController as? UITabBarController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "NavController")
vc.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
tabBarController.viewControllers?.append(vc)
}
}

Project 8: 7 Swifty Words

關鍵技術:

iPad,layoutMarginsGuide,activate,addTarget(_:action:for:),touchUpInside,subviews,isHidden,enumerated,tuple,replacingOccurrences(of:with:),trimmingCharacters(in:),whitespacesAndNewlines,setTitle(_:for:),joined,UIFont,isUserInteractionEnabled,placeholder,setContentHuggingPriority(_:for:),UILayoutPriority,vertical,horizontal,CGRect,frame,didSet,property observer,removeAll

ps: 網頁的教學有更新,改成從程式製作畫面,新版的程式可參考 Khumar 的 GitHub。

Project 9: Grand Central Dispatch

關鍵技術:

GCD,grand central dispatch,async,DispatchQueue,main,global,qos,performSelector(inBackground:),performSelector(onMainThread:with:waitUntilDone:)

ps: ViewController 裡記得改成以下網址

if navigationController?.tabBarItem.tag == 0 {
urlString = "https://www.hackingwithswift.com/samples/petitions-1.json"
} else {
urlString = "https://www.hackingwithswift.com/samples/petitions-2.json"
}

Project 10: Names to Faces

關鍵技術:

UICollectionViewController,UICollectionView,UICollectionViewCell,UICollectionViewDataSource,UICollectionViewDelegate,custom cell,cell size,section inset,collectionView(_:didSelectItemAt:),collectionView(_:cellForItemAt:),UIImagePickerControllerDelegate,init,documentDirectory,appendingPathComponent,cornerRadius,UIImagePickerController,allowsEditing,imagePickerController(_:didFinishPickingMediaWithInfo:),originalImage,UUID,write(to:),dismiss,fatalError,NSObject

Project 11: Pachinko(Game)

關鍵技術:

game,SpriteKit,Set,first,SKView,scene,SKScene,anchor point,scaleMode,presentScene,didMove(to:),zPosition,blendMode,replace,SKSpriteNode,rectangleOf,circleOfRadius,edgeLoopFrom,CGPoint,addChild,position,touchesBegan(_:with:),UITouch,location(in:),nodes(at:),CGSize,name,SKAction,rotate,pi,radians,repeatForever,run,isDynamic,SKPhysicsBody,SKPhysicsContactDelegate,physicsWorld,contactDelegate,contactTestBitMask,collisionBitMask,restitution,SKNode,removeFromParent,didBegin(_:),SKPhysicsContact,bodyA,bodyB,node,SKLabelNode,horizontalAlignmentMode,SKEmitterNode,sks,SpriteKit Particle File

Project 12: UserDefaults

關鍵技術:

save,NSKeyedArchiver,archivedData(withRootObject:requiringSecureCoding:),UserDefaults,standard,set(_:forKey:),object(forKey:),data(forKey:),NSKeyedUnarchiver,unarchiveTopLevelObjectWithData,NSCoding,init(coder:),encode(with:),decodeObject(forKey:),encode(_:forKey:),JSONDecoder,JSONEncoder,encode,Codable

Project 13: Instafilter

關鍵技術:

UISlider,editedImage,CoreImage,CIFilter,CIContext,outputImage,UIImageWriteToSavedPhotosAlbum,CIImage,createCGImage(_:from:),CGImage,inputKeys,func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer),localizedDescription

Project 14: Whack-a-Penguin(Game)

關鍵技術:

SKCropNode,maskNode,moveBy(x:y:duration:),SKTexture,asyncAfter(deadline:qos:flags:execute:),now,wait(forDuration:),sequence,run(block:),parent,playSoundFileNamed(_:waitForCompletion:),scale

ps: GameViewController 裡的 scaleMode 請改成 fill。

scene.scaleMode = .fill

Project 15: Animation

關鍵技術:

Core Animation,center,animate(withDuration:animations:completion:),spring animation,animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:) ,transform,CGAffineTransform,identity,translation,scale,rotationAngle,alpha,clear

Project 16: Capital Cities

關鍵技術:

map,MapKit,MKMapView,CLLocationCoordinate2D,latitude,longitude,annotation,MKAnnotation,addAnnotation,MKMapViewDelegate,mapView(_:viewFor:),MKAnnotationView,dequeueReusableAnnotationView(withIdentifier:),MKMarkerAnnotationView,canShowCallout,rightCalloutAccessoryView,detailDisclosure,mapView(_:annotationView:calloutAccessoryControlTapped:)

ps:

請將程式裡的 MKPinAnnotationView 改成 MKMarkerAnnotationView

Project 17: Space Race(Game)

關鍵技術:

SKEmitterNode,advanceSimulationTime,gravity,CGVector,Timer,scheduledTimer(timeInterval:target:selector:userInfo:repeats:),invalidate,velocity,angularVelocity,linearDamping,angularDamping,update(_:),touchesMoved(_:with:),CADisplayLink

ps: GameViewController 裡的 scaleMode 請改成 fill。

scene.scaleMode = .fill

Project 18: Debugging

關鍵技術:

debug,print,assert,breakpoint,debug view hierarchy

Project 19: JavaScript Injection

關鍵技術:

Application Extension,Safari extension,JavaScript,JavaScript Injection,NSExtensionItem,extensionContext,inputItems,attachments,NSItemProvider,loadItem(forTypeIdentifier:options:completionHandler:),NSDictionary,NSExtension,NSExtensionAttributes,NSExtensionJavaScriptPreprocessingResultsKey,completeRequest(returningItems:),UITextView,NotificationCenter,default,addObserver(_:selector:name:object:),UIResponder,keyboardWillHideNotification,keyboardWillChangeFrameNotification,keyboardFrameEndUserInfoKey,convert(_:from:),cgRectValue,contentInset,UIEdgeInsets,safeAreaInsets,scrollIndicatorInsets,selectedRange,scrollRangeToVisible,NSExtensionJavaScriptFinalizeArgumentKey,completeRequest(returningItems:),Notification.Name,post(name:object:userInfo:)

ps: adjustForKeyboard 裡的 script.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0) 請改成以下寫法。

script.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)

App 操作:

打開 Safari App,從選單點選 Extension,輸入 JavaScript 程式 alert(document.title),點選 Done 關閉頁面時會跳出 alert。

Project 20: Fireworks Night(Game)

關鍵技術:

UIBezierPath,move(to:),addLine(to:),follow(_:asOffset:orientToPath:speed:),children,colorBlendFactor,reversed,for case let,motionBegan(_:with:),shake

ps: checkTouches 的寫法有更新,請改成以下寫法。

func checkTouches(_ touches: Set<UITouch>) {
guard let touch = touches.first else { return }

let location = touch.location(in: self)
let nodesAtPoint = nodes(at: location)

for case let node as SKSpriteNode in nodesAtPoint {
guard node.name == "firework" else { return }

for parent in fireworks {
guard let firework = parent.children.first as? SKSpriteNode else {
continue
}
if firework.name == "selected" && firework.color != node.color {
firework.name = "firework"
firework.colorBlendFactor = 1
}
}

node.name = "selected"
node.colorBlendFactor = 0
}

}

Project 21: Local Notifications

關鍵技術:

local notification,UserNotifications,UNUserNotificationCenter,current,requestAuthorization(options:completionHandler:),alert,badge,sound,UNMutableNotificationContent,title,body,userInfo,UNNotificationSound,categoryIdentifier,DateComponents,UNCalendarNotificationTrigger,UNTimeIntervalNotificationTrigger,UNNotificationRequest,removeAllPendingNotificationRequests,UNNotificationAction,UNNotificationAction(identifier:title:options:),UNNotificationCategory,setNotificationCategories,UNUserNotificationCenterDelegate,userNotificationCenter(_:didReceive:withCompletionHandler:),UNNotificationResponse,actionIdentifier

Project 22: Detect-a-Beacon

關鍵技術:

CoreLocation,CLLocationManager,CLLocationManagerDelegate,requestAlwaysAuthorization,requestWhenInUseAuthorization,locationManager(_:didChangeAuthorization:),locationManagerDidChangeAuthorization(_:),CLAuthorizationStatus,authorizedAlways,isMonitoringAvailable(for:),CLBeaconRegion,isRangingAvailable,iBeacon,CLBeaconRegion(uuid:major:minor:identifier:),startMonitoring(for:),startRangingBeacons(in:),CLBeacon,proximity,CLProximity,unknown,far,near,immediate,locationManager(_:didRangeBeacons:in:),requestLocation,locationManager(_:didUpdateLocations:),locationManager(_:didFailWithError:),startMonitoringVisits,locationManager(_:didVisit:)

ps:

  • locationManager(_:didChangeAuthorization:) 可改成以下新版寫法
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedAlways {
if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
if CLLocationManager.isRangingAvailable() {
startScanning()
}
}
}
}
  • let beaconRegion = CLBeaconRegion(proximityUUID: uuid, major: 123, minor: 456, identifier: "MyBeacon") 可改成以下新版寫法
let beaconRegion = CLBeaconRegion(uuid: uuid, major: 123, minor: 456, identifier: "MyBeacon")
  • locationManager.startRangingBeacons(in: beaconRegion) 可改成以下新版寫法
locationManager.startRangingBeacons(satisfying: CLBeaconIdentityConstraint(uuid: uuid, major: 123, minor: 456))

Project 23: Swifty Ninja(Game)

關鍵技術:

SKShapeNode,strokeColor,touchesEnded(_:with:),touchesCancelled(_:with:),fadeOut(withDuration:),CGPath,run(_:completion:),AVFoundation,AVAudioPlayer,play,stop,CaseIterable,allCases,scale(to:duration:),group,removeAllActions,index(of:),removeFirst

ps:

  • GameViewController 裡的 scaleMode 請改成 fill。
scene.scaleMode = .fill
  • redrawActiveSlice 裡的 while activeSlicePoints.count > 12 {
    activeSlicePoints.remove(at: 0) }
    請改成以下程式。
if activeSlicePoints.count > 12 {

activeSlicePoints.removeFirst(activeSlicePoints.count - 12)
}

Project 24: Swift Strings

關鍵技術:

playground,index(_:offsetBy:),hasPrefix,hasSuffix,dropFirst,dropLast,capitalized,Character,contains(where:),NSAttributedString,NSMutableAttributedString,addAttribute(_:value:range:),underlineStyle,attributedText

Project 25: Selfie Share

關鍵技術:

MultipeerConnectivity,viewWithTag,MCPeerID,UIDevice,MCSession,MCSession(peer:securityIdentity:encryptionPreference:),MCAdvertiserAssistant,MCAdvertiserAssistant(serviceType:discoveryInfo:session:),start,MCBrowserViewController,MCBrowserViewController(serviceType:session:),MCSessionDelegate,MCBrowserViewControllerDelegate,session(_:didReceive:withName:fromPeer:),session(_:didStartReceivingResourceWithName:fromPeer:with:),session(_:didFinishReceivingResourceWithName:fromPeer:at:withError:),session(_:peer:didChange:),MCSessionState,connected,session(_:didReceive:fromPeer:),browserViewControllerDidFinish(_:),browserViewControllerWasCancelled(_:),connectedPeers,pngData,send(_:toPeers:with:),reliable

Project 26: Marble Maze(Game)

關鍵技術:

bitmask,UInt32,categoryBitMask,rawValue,allowsRotation,CoreMotion,CMMotionManager,startAccelerometerUpdates,accelerometerData,acceleration,#if targetEnvironment(simulator),#if swift(>=5.0),compiler directives

ps: GameViewController 裡的 scaleMode 請改成 fill。

scene.scaleMode = .fill

Project 27: Core Graphics

關鍵技術:

Core Graphics,draw 2D,UIGraphicsImageRenderer,image(actions:),UIGraphicsImageRendererContext,CGContext,setFillColor,setStrokeColor,setLineWidth,addRect,drawPath(using:),addEllipse(in:),insetBy(dx:dy:),fill,translateBy,rotate,strokePath,move(to:),addLine(to:),NSMutableParagraphStyle,draw(with:options:attributes:context:),draw(at:)

Project 28: Secret Swift

關鍵技術:

keychain,KeychainWrapper,resignFirstResponder,UIApplication.willResignActiveNotification,Touch ID,Face ID,LocalAuthentication,LAContext,canEvaluatePolicy(_:error:),deviceOwnerAuthenticationWithBiometrics,evaluatePolicy(_:localizedReason:reply:),Privacy — Face ID Usage Description

ps: adjustForKeyboard 裡的 script.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0) 請改成以下寫法。

script.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)

Project 29: Exploding Monkeys(Game)

關鍵技術:

SKPhysicsBody(texture:size:),stride(from:to:by:),setFill,texture atlases,usesPreciseCollisionDetection,setTexture,applyImpulse,SKTransition,crossFade(withDuration:),presentScene(_:transition:),doorway(withDuration:),setBlendMode,UIColor(hue:saturation:brightness:alpha:),clear,mix UIKit and SpriteKit

ps: 將 drawBuilding 裡的 ctx.cgContext.setFillColor(color.cgColor)ctx.cgContext.setFillColor(lightOnColor.cgColor)ctx.cgContext.setFillColor(lightOffColor.cgColor) 改成以下程式

color.setFill()
lightOnColor.setFill()
lightOffColor.setFill()

Project 30: Instruments

關鍵技術:

Instrument,profiling,shadow,image caching,Time Profiler,clip,shadowColor,shadowOpacity,shadowRadius,shadowOffset,setShadow(offset:blur:color:),shadowPath,Allocations,register(_:forCellReuseIdentifier:),UIImage(contentsOfFile:)

Project 31: Multibrowser

關鍵技術:

UIStackView,axis,vertical,horizontal,Distribution: (Fill,Fill Equally,Fill Proportionally,Equal Spacing,Equal Centering),arrangedSubviews,UITextFieldDelegate,UIGestureRecognizer,UITapGestureRecognizer,addGestureRecognizer,UIGestureRecognizerDelegate,gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:),textFieldShouldReturn(_:),iPad multitasking,traitCollectionDidChange(_:),UITraitCollection,horizontalSizeClass,verticalSizeClass,compact,regular,absoluteString

ps: 網頁的教學有更新,請移除 deleteWebView 裡的 stackView.removeArrangedSubview(webView)

Project 32: SwiftSearcher

關鍵技術:

automatic UITableViewCell sizing, Dynamic Type,preferredFont(forTextStyle:),SafariServices,SFSafariViewController,entersReaderIfAvailable,SFSafariViewController.Configuration,allowsSelectionDuringEditing,isEditing,editingAccessoryType,checkmark,tableView(_:editingStyleForRowAt:),UITableViewCell.EditingStyle,delete,insert,tableView(_:commit:forRowAt:),reloadRows(at:with:),CoreSpotlight,MobileCoreServices,CSSearchableItemAttributeSet,kUTTypeText,CSSearchableItem,CSSearchableIndex,indexSearchableItems(_:completionHandler:),deleteSearchableItems(withIdentifiers:completionHandler:),application(_:continue:restorationHandler:),NSUserActivity,activityType,CSSearchableItemActionType

Project 33: What’s that Whistle?

關鍵技術:

AVAudioSession,AVAudioRecorder,sharedInstance,setCategory(_:mode:options:),playAndRecord,setActive,requestRecordPermission(_:),numberOfLines,AVFormatIDKey,record,stop,AVAudioRecorderDelegate,audioRecorderDidFinishRecording(_:successfully:),accessoryType,disclosureIndicator,iCloud,CloudKit,hidesBackButton,popToRootViewController(animated:),CKRecord,CKRecord(recordType:),CKRecordValue,CKAsset,CKAsset(fileURL:),fileURL,CKContainer,publicCloudDatabase,save(_:completionHandler:),CloudKit dashboard,deselectRow(at:animated:),NSPredicate,NSPredicate(value:),NSSortDescriptor,NSSortDescriptor(key:ascending:),CKQuery,CKQuery(recordType:predicate:),sortDescriptors,CKQueryOperation,CKQueryOperation(query:),desiredKeys,resultsLimit,recordFetchedBlock,queryCompletionBlock,selectionStyle,CKRecord.Reference,CKRecord.Reference(recordID: action:),perform(_:inZoneWith:completionHandler:),startAnimating,fetch(withRecordID:completionHandler:),push notification,fetchAllSubscriptions(completionHandler:),delete(withSubscriptionID:completionHandler:),CKQuerySubscription,CKQuerySubscription(recordType:predicate:options:),CKSubscription.NotificationInfo,alertBody,registerForRemoteNotifications,userNotificationCenter(_:willPresent:withCompletionHandler:)

project 34 ~ 37 大部分是跟遊戲相關的技術,彼得潘先偷懶跳過,之後有空再研究。

Project 34: Four in a Row(Game)

Project 35: Generating random numbers

Project 36: Crashy Plane(Game)

Project 37: Psychic Tester(Game)

Project 38: GitHub Commits

關鍵技術:

CoreData,Data Model,xcdatamodeld,entity,attribute,NSPersistentContainer,loadPersistentStores(completionHandler:),NSManagedObjectContext,viewContext,NSManagedObject, @NSManaged@nonobjc,NSFetchRequest,fetch,SwiftyJSON,ISO8601DateFormatter,NSMergeByPropertyObjectTrumpMergePolicy,mergePolicy,NSPredicate(format:),Core Data entity relationship,delete,deleteRows(at:with:),fetchLimit,NSFetchedResultsController,NSFetchedResultsController(fetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:),fetchRequest,performFetch,NSFetchedResultsControllerDelegate,sections,NSFetchedResultsSectionInfo,object(at:)

https://api.github.com/repos/apple/swift/commits?per_page=100

Project 39: Unit testing with XCTest

關鍵技術:

unit test,XCTest,XCTestCase,@testable,setUp,tearDown,XCTAssertEqual,filter,measure(_:),keys,NSCountedSet,sorted(by:),UI test,XCUIApplication

--

--

--

學習 Swift iOS App 開發的學生作品集

Recommended from Medium

Push and Pop Navigation in SwiftUI

Journal of a senior iOS developer part 1

Higher — Order Functions in Swift

SwiftUI Parallax Motion Effect

SwiftUI: Will It Be Ready With Only a Month to Go?

What are The Top 8 Must-Have Skills For a Swift Developer In 2020

Creating iOS Simulators for End-to-End Automation Tests

Best way to dismiss Keyboard in a View Controller iOS (Swift)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
彼得潘的 iOS App Neverland

彼得潘的 iOS App Neverland

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com

More from Medium

適合新手學習參考的 Swift iOS UIKit App 專案

[Server-Side Swift] Summarize information/articles for iOS with Vapor

Capture Videos on a Custom Screen | Swift | Xcode

SectionedFetchRequest, sweet, sweet automagic goodness!