iOS纯Swift代码构建一个功能完善的APP
Posted yofer张耀琦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS纯Swift代码构建一个功能完善的APP相关的知识,希望对你有一定的参考价值。
纯Swift代码构建一个功能完善的APP
源代码地址:https://github.com/yoferzhang/FoodPin
效果演示
ios11之后,导航栏可以设置这样变大的效果。
在 ViewController 的 viewDidLoad() 方法中添加下面这行代码可以实现:
// iOS11之后这个属性可以让导航栏往下滑动的时候title变大
navigationController?.navigationBar.prefersLargeTitles = true
向右滑动菜单:
向左滑动菜单:
tableView,actionSheet
详情页面
导航栏透明,并修改大字体状态的title颜色, viewDidLoad()
中
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
// 设置导航栏title的大字体状态的颜色
if let customFont = UIFont(name: "PingFangSC-Medium", size: 40.0)
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor(red: 231.0/255.0, green: 76.0/255.0, blue: 60.0/255.0, alpha: 1.0), NSAttributedString.Key.font: customFont]
详情页面的导航栏变透明,返回按钮变色
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.tintColor = UIColor.white
调整tableView的顶部位置
detailTableView.contentInsetAdjustmentBehavior = .never
全局修改导航栏的返回按钮 application(_:didFinishLaunchingWithOptions:)
中添加
let backButtonImage = UIImage(named: "back")
UINavigationBar.appearance().backIndicatorImage = backButtonImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backButtonImage
修改详情页状态栏,
/// 状态栏颜色
override var preferredStatusBarStyle: UIStatusBarStyle
return .lightContent
可以没有生效,因为会用导航栏controller的颜色,为了让可以针对性修改页面,加一个Extension文件,UINavigationController+Ext.swift
import UIKit
extension UINavigationController
open override var childForStatusBarStyle: UIViewController?
return topViewController
添加地图信息
自定义 annotationView
,实现 MKMapViewDelegate
//MARK: - MKMapViewDelegate
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
let identifier = "MyMarker"
if annotation.isKind(of: MKUserLocation.self)
return nil
// Reuse the annotation if possible
var annotationView: MKMarkerAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView
if annotationView == nil
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.glyphText = "?"
annotationView?.markerTintColor = UIColor.orange
return annotationView
mapView.showsTraffic = true
mapView.showsScale = true
mapView.showsCompass = true
测试一些动画
代理回调,将选择的表情回调给详情页,展示在 headerView
的右下角
静态列表,textField
使用
图片选择器
改用 CoreData
存储数据,并用 NSFetchedResultsController
监听;新建局部刷新首页 tableview
删除后,局部刷新首页 tableview
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") (action, soureView, comletionHandler) in
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
let context = appDelegate.persistentContainer.viewContext
if let currentVC = self.currentViewController() as? YQRestaurantTableViewController
let restaurantToDelete = currentVC.fetchResultController.object(at: indexPath)
context.delete(restaurantToDelete)
appDelegate.saveContext()
comletionHandler(true)
更新rating 表情,同样是数据库级别的更新,加 appDelegate.saveContext()
就可以
//MARK: - YQRestaurantReviewViewControllerDelegate
func onClickRateButtonInReviewVC(rate: RateModel)
restaurant.rating = rate.image
refreshRatingImageView(rateImage: rate.image)
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
appDelegate.saveContext()
添加搜索栏,支持name搜索,搜索状态时禁止左右滑动的编辑态
tabBarController
About页面;使用元组;分别用 WKWebView
和 SFSafariViewController
打开web页面
使用iCloud,在 CloudKit Dashboard 中创建数据;原本是想上传图片,但 Dashboard 一上传那图片就 停止响应了,苹果这个做的有点坑==
然后用 Convenience API:
func fetchRecordsFromCloud()
let cloudContainer = CKContainer.default()
let publicDatabase = cloudContainer.publicCloudDatabase
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Restaurant", predicate: predicate)
publicDatabase.perform(query, inZoneWith: nil) (results, error) in
if let error = error
print(error)
return
if let results = results
print("Completed the download of Restaurant data")
self.restaurants = results
DispatchQueue.main.async(execute:
self.discoverTableView.reloadData()
)
代码中拉取到的数据结构:
改用 Operational API。因为 Convenience API 不能只请求携带某些字段,它会把所有数据都完整拉下来
func fetchRecordsFromCloud()
let cloudContainer = CKContainer.default()
let publicDatabase = cloudContainer.publicCloudDatabase
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Restaurant", predicate: predicate)
let queryOperation = CKQueryOperation(query: query)
queryOperation.desiredKeys = ["name", "iamge"]
queryOperation.queuePriority = .veryHigh
queryOperation.resultsLimit = 50
queryOperation.recordFetchedBlock = (record) -> Void in
self.restaurants.append(record)
queryOperation.queryCompletionBlock = [unowned self] (cursor, error) -> Void in
if let error = error
print("Failed to get data from iCloud -\\(error.localizedDescription)")
return
print("Successfully retrieve the data from iCloud")
DispatchQueue.main.async(execute:
self.discoverTableView.reloadData()
)
publicDatabase.add(queryOperation)
使用 UIActivityIndicatorView
和 UIRefreshControl
将数据存储到iCloud
func saveRecordToCloud(restaurant: RestaurantMO!) -> Void
// Prepare the record to save
let record = CKRecord(recordType: "Restaurant")
record.setValue(restaurant.name, forKey: "name")
record.setValue(restaurant.type, forKey: "type")
record.setValue(restaurant.location, forKey: "location")
record.setValue(restaurant.phone, forKey: "phone")
record.setValue(restaurant.summary, forKey: "description")
let imageData = restaurant.image! as Data
// Resize the image
let originalImage = UIImage(data: imageData)!
let scalingFactor = (originalImage.size.width > 1024) ? 1024 / originalImage.size.width : 1.0
let scaledImage = UIImage(data: imageData, scale: scalingFactor)
// Write the image to local file for temporary use
let imageFilePath = NSTemporaryDirectory() + restaurant.name!
let imageFileURL = URL(fileURLWithPath: imageFilePath)
try? scaledImage?.jpegData(compressionQuality: 0.8)?.write(to: imageFileURL)
// Create image asset for upload
let imageAsset = CKAsset(fileURL: imageFileURL)
record.setValue(imageAsset, forKey: "image")
// Get the Public iCloud Database
let publicDatabase = CKContainer.default().publicCloudDatabase
// Save the record to iCloud
publicDatabase.save(record, completionHandler: (record, error) -> Void in
// Remove temp file
try? FileManager.default.removeItem(at: imageFileURL)
)
以上是关于iOS纯Swift代码构建一个功能完善的APP的主要内容,如果未能解决你的问题,请参考以下文章