Take notes on your iOS learning process
IOS Development – Fragmentary notes
Create a project directory structure
- Appdelegate.swift: Definition of the life cycle and variables
- ViewController. Swift: MVC C
- Assets. Xcasset: Store resource files, such as pictures
- Info. plist: configuration file
- XxxTest: unit test
- Products: generated file
- Main. Storyboard: view
Add comments quickly
option + command + /
Copy the code
Close the soft keyboard
Close the code
textField.resignFirstResponder()
Copy the code
Closing method 1: Override the touchesEnded() method in Controller, and then close the software disk inside it, meaning close by clicking on the blank
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
name.resignFirstResponder()
}
Copy the code
Close method 2: Close the soft keyboard when you click Next. Controller implements UITextFieldDelegate protocol; Implement textFieldShouldReturn method in UITextFieldDelegate protocol;
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Copy the code
UIDatePicker calculates the age after selecting the time
func calAge(by datePicker: UIDatePicker) -> Int? {
let gregorian = NSCalendar(calendarIdentifier: .gregorian)
let now = Date(a)letcomponents = gregorian? .components(NSCalendar.Unit.year, from: datePicker.date, to: now, options: NSCalendar.Options.init(rawValue: 0))
returncomponents? .year }Copy the code
Page jump, data transfer
There are two controllers: ViewController and GalleryViewController. Jump from ViewController to GalleryViewController. The ViewController overwrite method prepare, which is called when the page jumps and we need to determine which page to jump to.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// You need to name the Segue
if segue.identifier == "GoToGallery" {
let index = beautyPicker.selectedRow(inComponent: 0)
var imageName: String?
switch index {
case 0:
imageName = "fangbingbing"
case 1:
imageName = "libingbing"
case 2:
imageName = "wangfei"
case 3:
imageName = "yangmi"
case 4:
imageName = "zhouxu"
default:
imageName = nil
}
// Get the Controller for the next page
let vc = segue.destination as! GalleryViewController
vc.imageName = imageName
}
}
Copy the code
Set the image by the image file name
beautyImage.image = UIImage(named: imageName)
Copy the code
Unwind segue closes the page
After the page is closed, the Controller can get the value from the previous page that was written on the previous page
@IBAction func closedPrePage(segue: UIStoryboardSegue) {
print("closed")}Copy the code
Move the TableView down by one status bar height
- Methods a
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
}
Copy the code
- In method two, the content is partially offset by the height of the status bar
collectionView? .contentInset.top = -UIApplication.shared.statusBarFrame.height
Copy the code
TableView add refresh
let refreshControl = UIRefreshControl(a)// Initialize the refresh
refreshControl.backgroundColor = UIColor.blue // Set the background color for the refresh
refreshControl.attributedTitle = NSAttributedString(string: "Refresh:\(Data())", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white]) // Set the font color
refreshControl.tintColor = UIColor.green // Load the chrysanthemum color
refreshControl.tintAdjustmentMode = .dimmed // Color adjustment mode
refreshControl.addTarget(self, action: #selector(addcount), for: .valueChanged) // Add a method target
// Add the refresh
tableView.refreshControl = refreshControl
Copy the code
The refresh method
@objc func addcount(a) {
dataArrary.append(contentsOf: dataArrary)
tableView.reloadData()
refreshControl.endRefreshing()
}
Copy the code
Add a font to the project
Developer.apple.com/documentati…
Because the font name used in iOS is not the file name, but the name of the font itself. The following code searches for all fonts, and then we find the extra names in the console.
for family: String in UIFont.familyNames
{
print("\(family)")
for names: String in UIFont.fontNames(forFamilyName: family)
{
print(= = ""\(names)")}}Copy the code
Set tabbar font and font size
override func viewDidLoad(a) {
super.viewDidLoad()
let appearance = UITabBarItem.appearance()
appearance.setTitleTextAttributes([NSAttributedStringKey.font: UIFont(name: "Ubuntu-Light", size: 9)! ] .for: .normal)
}
Copy the code
UIButton related
UIButton.isEnabled = false
The background image of the rear image button has been changed
UIButton.adjustsImageWhenDisabled = false
Copy the code
The extension adds rounded corners, borders, and border colors
@IBDesignable extension UIButton {
@IBInspectable var borderWidth: CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
@IBInspectable var cornerRadius: CGFloat {
set {
layer.cornerRadius = newValue
}
get {
return layer.cornerRadius
}
}
@IBInspectable var borderColor: UIColor? {
set {
guard let uiColor = newValue else { return }
layer.borderColor = uiColor.cgColor
}
get {
guard let color = layer.borderColor else { return nil }
return UIColor(cgColor: color)
}
}
}
Copy the code
Expand picture on top, text on bottom
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0, imageBottom: CGFloat = 0.0) {
guard let imageSize = self.imageView? .image? .size,let text = self.titleLabel? .text,let font = self.titleLabel? .fontelse { return }
self.titleEdgeInsets = UIEdgeInsets(top: 0.0.left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
let labelString = NSString(string: text)
let titleSize = labelString.size(withAttributes: [NSAttributedStringKey.font: font])
self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: imageBottom, right: -titleSize.width)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)}}Copy the code
UITableView or UICollectionView is covered by TabBar
UITableView callreloadData
Causes moving to the top of the list to fail
UIView.animate(withDuration: 0, animations: {
self.tableView.contentOffset = CGPoint.zero
}, completion: { _ in
self.tableView.reloadData()
})
Copy the code
NavigationBar causes the CollectionViewCell or TableViewCell to be offset
self.collectionView? .contentInsetAdjustmentBehavior = .automaticCopy the code
Get the APP version
/// get the version name
let appVersion = Bundle.main.infoDictionary! ["CFBundleShortVersionString"] as? String
/// get the version number
let versionNumber = Bundle.main.infoDictionary! ["CFBundleVersion"] as? String
Copy the code
Clear the cache
func clearCache(a) {
// Retrieve the cache folder where the cache files are stored
let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
// Fetch the array of all files under the folder
let fileArr = FileManager.default.subpaths(atPath: cachePath!)
// Iterate over the delete
for file in fileArr! {
letpath = cachePath? .appendingFormat("/\(file)")
if FileManager.default.fileExists(atPath: path!) {
do {
try FileManager.default.removeItem(atPath: path!)
} catch{}}}}Copy the code
Open the Appstore of this software
// App Store URL.
let appStoreLink = "https://itunes.apple.com/cn/app/id1144351773?mt=8"
/* First create a URL, then check whether there is an installed app that can open it on the device. */
if let url = URL(string: appStoreLink), UIApplication.shared.canOpenURL(url) {
// Attempt to open the URL.
UIApplication.shared.open(url, options: [:], completionHandler: {(success: Bool) in
if success {
print("Launching \(url) was successful")}}}Copy the code
Set the circular display image
- Set up the
UIImageView
Width and height, if set to 60 x 60 - Set the runtime properties and set the arc to 30 (half the square edge length)
- Check the
Clip to Bounds
.
UIScrollView fills the top (remove the status bar to the spacing)
Content Insets
chooseNever
- unselected
Safe Area Relative Margins
UIImage Gaussian blur extension
extension UIImage {
func blurred(radius: CGFloat) -> UIImage {
let ciContext = CIContext(options: nil)
guard let cgImage = cgImage else { return self }
let inputImage = CIImage(cgImage: cgImage)
guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
ciFilter.setValue(radius, forKey: "inputRadius")
guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
return UIImage(cgImage: cgImage2)
}
}
Copy the code
Two UIImage merge extensions
extension UIImage {
func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
let newSize = CGSize(width: newWidth, height: newHeight)
UIGraphicsBeginImageContextWithOptions(newSize, false.0.0)
draw(in: CGRect(origin: CGPoint.zero, size: size))
image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext(a)return newImage
}
}
Copy the code
SDWebImageView downloads images
- Methods a
img.sd_setImage(with: URL(string: "http://url"),
placeholderImage: #imageLiteral(resourceName: "default_square")) { image, error, cacheType, url in
}
Copy the code
- Way 2
SDWebImageDownloader
.shared()
.downloadImage(with: URL(string: "http://url"),
options: SDWebImageDownloaderOptions.init(rawValue: 0),
progress: nil,
completed: { image, data, error, finished in
if finished {
}
})
Copy the code
AVPlayerViewController video playback
import AVKit
func playVideoByUrl(string: String) {
let videoURL = URL(string: string)
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) { playerViewController.player! .play() } }Copy the code
The click gesture added to UIImageView is invalid
- Check on
User Interaction Enabled
- Set in code
uiimageview.userInteractionEnabled = true
PHAsset Gets the file path
extension PHAsset {
func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)) {if self.mediaType == .image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) - >Bool in
return true
}
self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput? , info: [AnyHashable : Any]) -> Void incompletionHandler(contentEditingInput! .fullSizeImageURLas URL?)
})
} else if self.mediaType == .video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .original
PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset? , audioMix:AVAudioMix? , info: [AnyHashable : Any]? ->Void in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl: URL = urlAsset.url as URL
completionHandler(localVideoUrl)
} else {
completionHandler(nil)}})}}}Copy the code
UIView associated
Get the parent UIViewController from UIView
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
whileparentResponder ! =nil{ parentResponder = parentResponder! .nextif let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil}}Copy the code
String related
HTML string, the code into the corresponding effect
extension String {
var htmlToAttributedString: NSAttributedString? {
guard let data = data(using: .utf8) else { return NSAttributedString()}do {
return try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding:String.Encoding.utf8.rawValue], documentAttributes: nil)}catch {
return NSAttributedString()}}var htmlToString: String {
returnhtmlToAttributedString? .string ??""}}Copy the code
Regular expression matching
/// The regular expression matches
extension String {
func matchingStrings(regex: String)- > [String] {
do {
let regex = try NSRegularExpression(pattern: regex)
let results = regex.matches(in: self,
range: NSRange(self.startIndex... .in: self))
return results.map {
String(self[Range($0.range, in: self)!])
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return[]}}}Copy the code
Data Splicing Data
extension Data {
mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
if let data = string.data(using: encoding) {
append(data)
}
}
}
Copy the code
Scrambling an array
extension Array{
mutating func randamArray(a) {
var list = self
for index in 0..<list.count {
let newIndex = Int(arc4random_uniform(UInt32(list.count-index))) + index
ifindex ! = newIndex { list.swapAt(index, newIndex) } }self = list
}
}
Copy the code
UIImage related
Gaussian blur picture
extension UIImage {
func blurred(radius: CGFloat) -> UIImage {
let ciContext = CIContext(options: nil)
guard let cgImage = cgImage else { return self }
let inputImage = CIImage(cgImage: cgImage)
guard let ciFilter = CIFilter(name: "CIGaussianBlur") else { return self }
ciFilter.setValue(inputImage, forKey: kCIInputImageKey)
ciFilter.setValue(radius, forKey: "inputRadius")
guard let resultImage = ciFilter.value(forKey: kCIOutputImageKey) as? CIImage else { return self }
guard let cgImage2 = ciContext.createCGImage(resultImage, from: inputImage.extent) else { return self }
return UIImage(cgImage: cgImage2)
}
}
Copy the code
Two pictures are superimposed to make one picture
extension UIImage {
func overlayWith(image: UIImage, posX: CGFloat, posY: CGFloat) -> UIImage {
let newWidth = size.width < posX + image.size.width ? posX + image.size.width : size.width
let newHeight = size.height < posY + image.size.height ? posY + image.size.height : size.height
let newSize = CGSize(width: newWidth, height: newHeight)
UIGraphicsBeginImageContextWithOptions(newSize, false.0.0)
draw(in: CGRect(origin: CGPoint.zero, size: size))
image.draw(in: CGRect(origin: CGPoint(x: posX, y: posY), size: image.size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext(a)return newImage
}
}
Copy the code
Zoom pictures
extension UIImage {
func scaled(withSize size: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false.0.0)
defer { UIGraphicsEndImageContext() }
draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
return UIGraphicsGetImageFromCurrentImageContext()! }}Copy the code
Json related
Json encoding
extension JSONEncoder {
/// Convert the entity class to Json data
func toJson<T: Encodable>(_ entity: T) -> String? {
guard let encodedData = try? encode(entity) else {
return nil
}
return String(data: encodedData, encoding: .utf8)
}
}
Copy the code
Json decode
extension JSONDecoder {
func from<T: Decodable>(_ type: T.Type, json: String) -> T? {
do {
return try decode(type, from: json.data(using: .utf8)!)
}
catch {
return nil}}}Copy the code
The request field is encoded as a string, for example, key= Value&key = Value&key =value
extension Dictionary {
func percentEscaped(a) -> String {
return map { (key, value) in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")}}extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = : # @ "[]" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = ! "" * + $& '(),; ="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
Copy the code
UIViewController related
Add a sub UIViewController
extension UIViewController {
// add child ViewController
func addSubController(child: UIViewController, to: UIView? = nil) {
addChildViewController(child)
if let to = to {
child.view.frame = to.frame
to.addSubview(child.view)
}
else {
child.view.frame = view.frame
view.addSubview(child.view)
}
child.didMove(toParentViewController: self)}}Copy the code
Remove the sub UIViewController
extension UIViewController {
// remove the child ViewController
func removeSubController(child: UIViewController) {
child.willMove(toParentViewController: nil)
child.removeFromParentViewController()
child.view.removeFromSuperview()
}
}
Copy the code
Close the page
Close the current page
extension UIViewController {
// close the current page
func closePage(a) {
self.dismiss(animated: true, completion: nil)}}Copy the code
Close all pages except the one at the lowest level
extension UIViewController {
func closeAllPage(a) {
// Get root VC
var rootVC = self.presentingViewController
while letparent = rootVC? .presentingViewController { rootVC = parent }// Release all subordinate viewsrootVC? .dismiss(animated:true, completion: nil)}}Copy the code
Show and close chrysanthemums waiting to load
extension UIViewController {
class func displaySpinner(onView : UIView) - >UIView {
let spinnerView = UIView.init(frame: onView.bounds)
spinnerView.backgroundColor = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5)
let ai = UIActivityIndicatorView.init(activityIndicatorStyle: .whiteLarge)
ai.startAnimating()
ai.center = spinnerView.center
DispatchQueue.main.async {
spinnerView.addSubview(ai)
onView.addSubview(spinnerView)
}
return spinnerView
}
class func removeSpinner(spinner :UIView) {
DispatchQueue.main.async {
spinner.removeFromSuperview()
}
}
}
Copy the code
According to
let sp = UIViewController.displaySpinner(onView: self.view)
Copy the code
Shut down
UIViewController.removeSpinner(spinner: sp)
Copy the code
Within the IAP purchase
use
- The internal purchase preparation process except the code has been OK
- Obtaining product data: Pass
IAPHelper.shared.fetchAvailableProducts
Gets the product information from the Apple server for all product ids passed in as an array of product ID strings - Payment:
IAPHelper.shared.purchase(id: id)
Id is the product ID
IAPHelper.shared.purchase(id: selectItem! .product_id) {alert, product, transactionin
if alert == .purchased { // Successful purchase
if let receiptUrl = Bundle.main.appStoreReceiptURL, let receiptData = NSData(contentsOf: receiptUrl) {
let receiptString = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
// Validate the receiptString encrypted string}}else if alert == .restored {
}
else if alert == .purchasing {
}
else{}}Copy the code
IAPHelper code
import StoreKit
enum IAPHelperAlertType{
case disabled
case restored
case purchased
case purchasing
case setProductIds
func message(a) -> String{
switch self {
case .setProductIds: return "No product ID set, please call fetchAvailableProducts()"
case .disabled: return "Purchase cancelled"
case .restored: return "You have successfully resumed purchase."
case .purchased: return "You have successfully purchased this product."
case .purchasing: return "Buying..."}}}class IAPHelper: NSObject {
static let shared = IAPHelper(a)private override init() { }
fileprivate var productID = ""
fileprivate var productsRequest = SKProductsRequest()
fileprivate var productDict = [String:SKProduct]()
fileprivate var fetchProductCompletion: (([SKProduct] - >Void)?
fileprivate var productToPurchase: SKProduct?
var purchaseProductCompletion: ((IAPHelperAlertType.SKProduct? .SKPaymentTransaction?). ->Void)?
// MARK: - Buy the product
func canMakePurchases(a) -> Bool { return SKPaymentQueue.canMakePayments() }
func purchase(id: String, completion: @escaping ((IAPHelperAlertType, SKProduct? , SKPaymentTransaction?)->Void)) {
self.purchaseProductCompletion = completion
self.productToPurchase = productDict[id]
guard let product = self.productToPurchase else {
print(IAPHelperAlertType.setProductIds.message())
fatalError(IAPHelperAlertType.setProductIds.message())
}
if self.canMakePurchases() {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
print("Buy Products:\(product.productIdentifier)")
productID = product.productIdentifier
}
else {
completion(.disabled, nil.nil)}}// MARK: - Resume purchases
func restorePurchase(a){
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
// MARK: - Get available IAP products
func fetchAvailableProducts(by ids: [String], completion: @escaping (([SKProduct])->Void)) {self.fetchProductCompletion = completion
// Put your IAP product ID in here
guard! ids.isEmptyelse {
print("No product ID set")
fatalError(IAPHelperAlertType.setProductIds.message())
}
productsRequest = SKProductsRequest(productIdentifiers: Set(ids))
productsRequest.delegate = self
productsRequest.start()
}
}
extension IAPHelper: SKProductsRequestDelegate.SKPaymentTransactionObserver{
// MARK: - Request IAP products
func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
if (response.products.count > 0) {
for product in response.products {
print("product.productIdentifier = \(product.productIdentifier)")
self.productDict[product.productIdentifier] = product
}
self.fetchProductCompletion? (response.products) } }func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
self.purchaseProductCompletion? (.restored,nil.nil)}// MARK:- IAP payment queue
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
print("Called several times!!")
for transaction:AnyObject in transactions {
if let trans = transaction as? SKPaymentTransaction {
switch trans.transactionState {
case .purchased:
print("Product Purchased")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
self.purchaseProductCompletion? (.purchased,self.productToPurchase, trans)
break
case .failed:
print("Product purchase failed\(trans.error.debugDescription)")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
self.purchaseProductCompletion? (.disabled,self.productToPurchase, trans)
break
case .purchasing:
print("Buying...")
self.purchaseProductCompletion? (.purchasing,self.productToPurchase, trans)
break
case .restored:
print("Product purchase has resumed")
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
self.purchaseProductCompletion? (.restored,self.productToPurchase, trans)
break
default: break
}
}
}
}
}
Copy the code