update
github

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

I’ve been working on iOS development for almost 4 years, and I’ve heard about Swift for over 2 years, but I’ve only been learning on the surface. I accidentally heard that Sam Lu launched an activity to make 40 Swift mini programs in 100 days on Twitter, and then I saw the Swift learning article written by Allen Chaohui in China, and I made a decision in my heart: Write 30 Swift mini programs in 30 days, hoping to promote my plan to learn Swift. These 30 mini-programs vary in difficulty, from being written in a single night to taking most of the weekend to study. Google can find most of the stuff that doesn’t, even if Swift doesn’t find the Objective-C version and just rewrite it in Swift, but luckily they have a pretty clear correspondence.

In terms of use cases, I have referred to Sam Lu’s 40 small projects, Allen Zhaohui’s projects, and some of the well-known apps I have copied myself.

In fact, I am not the only author who launched this 30 days Swift mini program in China and made it open source, but I may be the only author who wrote it in XCode 8 + Swift3 environment from start to finish. Also, to make the code more readable, all the code is written entirely by hand, not in Storyboard (except storyboard-only, like the Apple Watch app). In fact, we use storyboards as little as possible on collaborative projects because it’s easy to have conflict issues. And from a learning point of view, it’s hard to tell what the steps are in storyboard. I actually spent a lot of time on it, but I think it was worth it.

Hopefully, more developers interested in Swift will join the #30 Swift Applets in 30 days campaign. Here’s the Github link: github.com/nimomeng/30…

Project 30 – Google Now App

I learned a

  • This Project demonstrates how Present/Dismissd does Transition animation, which is the same basic principle that you use to do Push/Pop
  • This animation is based on the BubbleTransition animation and is modified to allow you to pass in custom UI properties for composite animations (for example, buttons that not only zoom in but also move up and down in this example).
  • The idea is to Scale the corresponding ViewController through a Bubble mask that looks like a Bubble
  • Other details are as follows:
    • To draw a circle button, the cornerRadius property must be 1/2 of the edge length:
        triggerButton.layer.cornerRadius = triggerButton.frame.width / 2
        triggerButton.layer.masksToBounds = true
Copy the code
  • UITextField sets the border style and must have its style set to None
  • Reference project :BubbleTransition

Project 29 – Beauty Contest

I learned a

  • This project is based on Koloda by Yalantis. Koloda is a very useful UIImage selector
  • Lazy loading in Swift:
    • Two ways:
lazy var firstWay = "first"
Copy the code

As well as

lazy var secondWay: String = {return "Second"} ()Copy the code

Note: The second way is to define the field type to facilitate type checking at compile time. And don’t forget the little brackets at the end

  • Lazy: You need to know the size of the KolodaView to determine the size of the Overlay. So there’s a dependency, so lazy loading works best.
  • Swift unowned/weak:
    • unowned is more like unsafe_unretained in OC; Weak is the same as weak.
    • If you are sure it will not be released, you can use unowned; Otherwise, you’d better use weak

Project 28 – SnapChat Like App

I learned a

  • Basic usage and small details of UIScrollView, such as the Bounces property for preventing bounce, the isPagingEnabled property for full page switching, the start position contentOffset property, and so on

  • Load the addChildViewController method of the child Viewcontroller

  • “XXX class has no initializers” problem

      You have to use implicitly unwrapped optionals so that Swift can cope with 
      circular dependencies (parent <-> child of the UI components in this case) 
      during the initialization phase.
    
      @IBOutlet var imgBook: UIImageView!
      @IBOutlet var titleBook: UILabel!
      @IBOutlet var pageBook: UILabel!
    Copy the code
  • Permission problem, specific error description: “This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app Uses this data.” solution: iOS10 after the permission problem, add the corresponding permission and description in the info.plist. In this example, the permission is: NSCameraUsageDescription PhotoMe needs the camera to take photos. NSMicrophoneUsageDescription PhotoMe needs the microphone to record audio with Live Photos. NSPhotoLibraryUsageDescription PhotoMe will save photos in the Photo Library.

  • Use AVCaptureSession:

    • AVCaptureSession is the core class of AVFoundation for capturing video and audio and coordinating the input and output streams of video and audio.
    • createAVCaptureSessionInstance and set itsessionPresetValue, that is, set the quality of the picture.
    • Add Input to Session. AVCaptureSession input source AVCaptureDeviceInput The specific step is to obtain the correspondingdeviceInstance (decide whether to use Video or Audio at this point), and then the instance gets its Input Source. Finally add the input source to the session.
    • Add Output to Session, the AVCaptureSession Output source. General output sources are divided into audio and video sources, picture sources, file sources and so on. For example, the output source of a static image is AVCapturePhotoOutput. Finally, add it to the session as well.
    • Set the preview layer, namely AVCaptureVideoPreviewLayer. In the input, output and other important information is added to the session, the session can be used to create AVCaptureVideoPreviewLayer, this is the video camera preview layer. Don’t forget to add Layer to View here.
    • Start Session, that iscaptureSesssion.startRunning()
  • Capture method of Photo

    • AVCaptureSession set up successfully and started
    • createAVCapturePhotoSettingsObject, and configure the corresponding properties, such as whether to turn on Flash, whether to turn on anti-shake mode, and so on
    • Execute the Capture method of the output source and specify the specific AVCapturePhotoSettings object and delegate object
    • In the Capture delegate method:
func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer? , previewPhotoSampleBuffer: CMSampleBuffer? , resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings? , error: Error?)Copy the code

To perform the specific logic to obtain the image. In this example, buffer is first converted to data, then converted to UIImage, and finally written to the album folder.

  • Reference: iOS AVCaptureSession study notes

Project 27: Carousel Effect

I learned a

  • The use of UICollectionView

    • The difference with UItableView is that each corresponding Cell (be it the Content Cell, header, or footer) requires a register method beforehand
    • The Cell spacing is too narrow, can be solved by minimumLineSpacingForSection DataSource agent method
    • If the selected layout for UICollectionViewFlowLayout, you can change scrollDirection attribute to modify the rolling direction
  • Custom Layout implements the following methods in the corresponding subclass

      prepare()
      shouldInvalidateLayout(forBoundsChange newBounds: CGRect)
      targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) 
      layoutAttributesForElements(in rect: CGRect)
    Copy the code

Among them:

  • Prepare defines the initialization operation

  • ShouldInvalidateLayout to check whether the bounds of each Cell need to be updated. Set this to true if our layout is one that needs to change dynamically per cell. Otherwise, set this parameter to false for performance. The default is flase.

  • TargetContentOffset, if we need images to be stopped at a specific location during scrolling (similar to album images on iPhone), please give specific rules for stopping in this function

  • All the layout layoutAttributesForElements returns all elements at this time. This is where we define layout related attributes for all other elements during the scroll. In this example, the closer you are to the center of the screen, the larger the image is scaled; The smaller the screen, the smaller the image is zoomed in.

  • Reference:

    • UICollectionView Comprehensive view
    • [function of photo albums with UICollectionView] (www.jianshu.com/p/4f691ec73)…
  • Use of Visual Effect View

    • Try to add it after the layer you want to blur, it will automatically blur the overlaid layer

      let blurEffect: UIBlurEffect = UIBlurEffect(style: .light)
      let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect)
      blurView.frame = self.view.bounds
      bgView.addSubview(blurView)
      Copy the code
  • Use of UISegmentedControl

  • If func in #selector() takes parameters, include them as well, for example: #selector(action_segmentValueChanged(sender:) This rule is different from OC.

Project 26 – Twitter-like Splash

I learned a

  • For this effect, it is difficult to use a simple UIView animation method, so use CAAnimation instead.
  • We need the effect to set keyPath to “bounds”. Jokingly, why doesn’t Apple do an enumeration… The complete keyPath list is shown below:
  • Since the animation customization of logo is quite demanding, we choose CAKeyFrameAnimation in CAAnimation to make the animation change. Focus on the keyTimes, values property, which is the property of the keyFrame. The timingFunctions attribute is the coun-1 of the keyframe, i.e. the animation transition functions from frame1 to frame2 and frame2 to frame3. I don’t need to talk more about this. It was mentioned in the previous Project.
  • During the process of logo enlargement, the alpha value in the middle of the logo should also have white become transparent, so a maskView should be added first, hidden in the top layer, below the logo layer, as the white base. The time and duration of the animation trigger keep pace with the animation of the logo and remember to remove it when the animation is complete. This is done using CABasicAnimation’s animationDidStop agent.
  • The transparency of the logo can be changed either by using a simple UIView animation or by using a Layer CABasicAnimation. Because I’m familiar with the former, I’ll use the latter here, and note keyPath isopacity. The code is relatively simple and won’t be repeated here.
  • The overall effect is still cool 🙂
  • CAKeyFrameAnimation refer to this document

Project 25 Custom Transition

I learned a

  • NavigationController animation can be customized to achieve UINavigationControllerDelegate method is good
  • If you only need to pay attention to the previous VC and the VC after the animation switch, do not need to pay attention to the middle process, directly implement the following method can be:
navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
Copy the code
  • The return value of the above methodUIViewControllerAnimatedTransitioningYou need custom animation, you need implementationUIViewControllerAnimatedTransitioningProxy, which implements two specific methods:
    • Transition animation time, directly return a time can be
transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
Copy the code
  • The transition animation process, as shown below, is more complicated:
animateTransition(using transitionContext: UIViewControllerContextTransitioning) 
Copy the code
  • The first step is to get fromVC, toVC, and container for the transition animation:
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! XXXController
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! YYYController
let container = transitionContext.containerView
Copy the code
  • Then comes the preparation work before animation, such as image assignment, such as coordinate calculation:
let snapshotView = fromVC.selectedCell.imageView.snapshotView(afterScreenUpdates: false) snapshotView? .frame = container.convert(fromVC.selectedCell.imageView.frame, from: fromVC.selectedCell) ....Copy the code
  • Finally, the Animation execution logic can be implemented through the ANIMATE method of UIView. Specific parameters and methods can be flexibly combined by referring to the previous Project.
    • Do not forget to add at the end of the incoming animationtransitionContext.completeTransition(true), showing navigationController to take control (in the Completion block)
    • Remember to bring the exit animationtransitionContext.completeTransition(! transitionContext.transitionWasCancelled)The animation is complete
  • If you need to focus on animation execution, you should implement the following methods on top of the above:
navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?
Copy the code

Among them, the transitional object UIViewControllerInteractiveTransitioning is animation

  • Gets the iOS hand swipe from left to right along the screen event, is passedUIScreenEdgePanGestureRecognizerMethod and sets its edges to left.
 let edgePanGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(edgePanGestrueAction(_:)))
edgePanGesture.edges = UIRectEdge.left
Copy the code
  • This tutorial focuses on creating custom animations for Push and Pop
  • Refer to document 1, document 2, and make changes based on them
  • This is an example that I love. This is Roscoe.

Project 24 – Vertical Menu Transition

I learned a

  • This article has the same idea as the Google Now App project, which is to customize the Transition for the Present/Dismiss operation
  • Since partial screenshots are required for animations, it is recommended to write the Present and Dismiss transitions together and use a variable to switch and control the different animations. Variables can be passed throughanimationController(forDismissed dismissed: UIViewController)withanimationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController)To set it up.
  • Target-action mode, which typically sets target to self. If set to the corresponding delegate, the Action field should be filled in#selector(CustomTransitionDelegate.functionName)
  • In the Present/Dismiss custom transition animation, remember to add the animation-ending block to the complete callback:
    transitionContext.completeTransition(true) fromViewController? .endAppearanceTransition() toViewController? .endAppearanceTransition()Copy the code

Project 23 – Side Navigation App

#### I learned it

  • Swift-oc mixed programming method
    • Create a new header file, for example named bridge.h
    • Click on the Project file, select Build Setting, locate the Objective-C Bridge Header, and enter the path to bridge.h
    • All OC file headers that need to be referenced in swift files are then imported into bridge.h

  • Sideslip effect borrowedSWRevealViewController, using the following steps (the original project only mentioned calling methods in OC)
    • There are at least several types of viewControllers in the project: the VC shown on the first page, such as FrontViewController; The MenuViewController that the tabeView is in
    • Create a custom Window in the AppDelegate according to the rules as follows:
      • Establish a UIWindow
      • Create two new UinavigationControllers, FrontViewController and MenuViewController as rootViewControllers respectively
      • Instantiate SWRevealViewController and set the values of rearViewController and frontViewController. Among them, RearViewController is tableView UINavigationController, frontViewController is frontViewController UINavigationController
      • Set the instantiated SWRevealViewController to the Window rootViewController
 window = UIWindow(frame: UIScreen.main.bounds)
 let rearNavigationController = UINavigationController(rootViewController: MenuViewController())
let frontNavigationController = UINavigationController(rootViewController: FrontViewController())
letrevealController = SWRevealViewController(rearViewController: rearNavigationController, frontViewController: frontNavigationController) revealController? .delegate = self window?.rootViewController = revealController window?.makeKeyAndVisible()Copy the code
  • You need to add left-swipe Menu logic to each ViewController, in a word:
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
Copy the code
  • It is best to hide the status bar and navigationBar:
self.navigationController? .isNavigationBarHidden =true
Copy the code
override var prefersStatusBarHidden: Bool {  return true  }
Copy the code

Project 22 – Basic Animations

I learned a

  • This time involves the most basic UIAnimation. Many complex animations are actually the superposition of various simple animations, so we should not overlook them
  • The Animation of Position can be modified either by directly modifying the Origin property of the frame or by directly modifying the Transform of the UIView
  • Animation-animation-alpha is also required
  • Scale is a transform that modifies UIView, passing in the relative Scale to Scale and creating the corresponding CGAffineTransform object. Such as:
Heartview. transform = CGAffineTransform(scaleX: 1.5, Y: 1.5)Copy the code
  • Color is directly modify backgroundColor can be
  • Rotation is done by modifying UIView’s transform, passing in the value to be rotated and creating the corresponding CGAffineTransform object. Where, the value is between 0 and 2*Pi, indicating that the value is between 0 and 360°. Note that the positive value rotates counterclockwise. Such as:
Self. RollingBallView. Transform = CGAffineTransform (6.28)Copy the code

Project 21 CoreData App

I learned a

  • Be sure to check UseCoreData so that part of the code is automatically generated in the Appdelegate
  • You don’t have to generate subclasses through the Editor
  • The Entity in this example is shown in the figure below:

  • In the class where CoreData is called, import CoreData
  • This example is relatively simple, and only getResult and Add operations are carried out. The ideas are as follows:
    • getResult:
      let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: EntityName)
        do {
            let searchResults = try getContext().fetch(fetchRequest)
            dataSource = searchResults as! [TodoList]
        } catch  {
           // todo error handler
        }
Copy the code

Note that the extracted searchResult can be directly instantiated as TodoList(TodoList is my Entity name) so that TodoList’s Content method can be used directly later.

  • saveContent:
        letContext = getContext() // Define an entity, which must be defined in xcDatamodeldlet entity = NSEntityDescription.entity(forEntityName: EntityName, in: context)
        lettodoList = NSManagedObject(entity: entity! , insertInto: context) todoList.setValue(content,forKey: "content"
        do {
            try context.save()
        }catch{}
Copy the code

Two lines of code for the getConent method:

 let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
Copy the code

This can be done directly by retrieving the TodoList object and calling its Content method. cell.textLabel? .text = (dataSource[indexPath.row]).content

  • UIAlertController adds input values:
alertController.addTextField { (textField) in
textField.placeholder = "Please input the todo Item"}
Copy the code
  • This method has passed the XCode8.3 + Swift3.2 test. CoreData has changed a lot in iOS10, and the previous version may be different from the above operation method
  • Refer to the article

Project 20 – Apple Watch OS App – Guess Game

I learned a

  • Watch program, you need to select the Section of Watch OS in create Project, and then select the following:

  • The UI in Watch can only be laid out through the Storyboard. The layout file is in the WatchKit App Interface. Storyboard

  • The example involves the interaction between the watch and the main app. The WCSession method is used here, and the steps are as follows:

    • Determine whether the device where the app resides supports WCSession
    • Generate a WCSession object and set its delegate
    • To activate this part of the WCSession object, the code reads:
      let wcsession = WCSession.default()
        if WCSession.isSupported() {
            wcsession.delegate = self
            wcsession.activate()
        }
Copy the code
  • Send communication (between the Watch and the main app) is via the updateApplicationContext method of the WCSession object, for exampletry wcsession.updateApplicationContext(["numberToBeGuessed": number])
  • The receiver receives and parses the sent message through the proxy method
    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) 
Copy the code
  • The example references WatchKit Introduction: Building a Simple Guess Game

Project 19 – TodayWidget

I learned a

  • Create Today Widget: File > New > Target… And then select the Today Extension for Application Extension in iOS
  • To facilitate data sharing between widgets and apps, switch to App Group mode. To open the main target, select Capability, locate the App Group, and open:

  • Add a name for the app group under the main Target, then go to the Extension Target and do the same and check the group
  • We can use UserDefault as shared storage between the main app and widgets. Instead of using standardUserDefaults, you can only use suiteName to share the same name as the one you added to the app Group:
let userDefault = UserDefaults(suiteName: "group.nimoAndHisFriend.watchDemo")
Copy the code
  • Write the corresponding read logic code in the Widget’s ViewController:
 let userDefaults = UserDefaults(suiteName: "group.nimoAndHisFriend.watchDemo") var leftTimeWhenQuit = userDefaults? .double(forKey: "lefttime")
Copy the code

To synchronize the data in the widget, add a timer to the Extension code. This synchronizes widge with the main application’s widge

  • To learn more about the use of widgets, refer to the documentation

Project 18 – Spotlight Search

I learned a

  • Spotlight Search:
    • Introducing CoreSpotlight libraryimport CoreSpotlight
    • CSSearchableItem is used here to add objects that need to be indexed. First create a CSSearchableItemAttributeSet, i.e., the attribute of the Item class, to add specific properties, including the title, contentDescription, and thumbData Settings.
    • Just to be clear, ThumbData CSSearchableItemAttributeSet object can be obtained through the UIImage object after its UIImageJPEGRepresentation method to get or UIImagePNGRepresentation method to get the ( Depending on what type of file image corresponds to)
    • Create the CSSearchableItem object and further add the created CSSearchableItem to the index using the indexSearchableItems method:
let tmpItems = [searchItem]
CSSearchableIndex.default().indexSearchableItems(tmpItems) { (error) in
}
Copy the code
  • If the spotlight cache cannot be cleared during debugging, please replace it with a new one or reset it. Or simply switch to the real machine for debugging, real machine this situation is less 🙂

Project 17 – 3D Touch Quick Action

  • The specific functions of 3D Touch are divided into two types: the first is to hold down ICONS in SpringBoard for direct function jump, and the second is to hold down ICONS for Peek & Pop of specific view elements inside the APP
  • Before introducing any 3D Touch related features, make sure your device supports 3D Touch.self.window? .traitCollection.forceTouchCapability == .available
  • For the first function, buildUIApplicationShortcutItemThe shortcutItems attribute of the application is set to Item. Note that when setting the icon, only the built-in centralized icon of the system can be set. Custom ICONS are not supported
  • For the second function, you need to register and add events to the VC that you want to add 3D Touch support
  • addUIViewControllerPreviewingDelegate
  • Sign up for 3D Touch support in this VC category.self.registerForPreviewing(with: self, sourceView: self.view)
  • Implement two types of delegate:
    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) 
Copy the code
  • To implement the extra Action button in the example, override the corresponding previewActionItems property and return the Array of UIPreviewAction you want

Project 16 – LoginAnimation

I learned a

  • At first I thought it was very simple, just the Animation method of normal UIView. It turned out that the bouncing effect wasn’t possible with the normal methods I used
  • The bounce animation is neededusingSpringWithDampingTo do this, the attributes should be noted:
    • UsingSpringWithDamping: the smaller the value is, the more exaggerated the animation is. The difference can be illustrated by using the online picture:

    • InitialSpringVelocity: the larger the value is, the higher the initial velocity will be.

    • Options animation curves:

  • What is the difference between usingSpringWithDamping in uiview.animation and parameter animations without usingSpringWithDamping? You can see below:

  • What fun animations with Spring properties! 🙂
  • Refer to documents 1, 2 for this section

Project 15 – Tumblr Menu

I learned a

  • This example is essentially for animation +BlurEffect
  • Three rows of animations have a sequence, which can be adjusted by the animation delay parameter
  • The image above of button needs to be set. Here we have a CustomButton that encapsulates the style. Refer to this article

Project 14 – Video Splash

I learned a

  • Create an AVPlayerViewController and place its view in the background
  • Then combine AVPlayerViewController for video playback and automatic loop
  • Video playback part draws on 10 cases in this article, it is said that is also refer to a call VideoSplashViewController library

Project 13: Animation In TableViewCell

I learned a

  • The initial idea was to perform animation operation in the delegate of willDisplay, and the effect was good. However, it was found that cell disorder occurred during cell scrolling, because cell redrawing during scrolling led to re-call of willDisplay and coordinate error. Rough look, solve a little trouble, then change ideas. This “approach animation” should not be performed in a delegate during rendering.
  • I’m going to put the animation in ViewWillAppear. You can use the visibleCells of the tableView to get the Array of all cells to be displayed and animate them one by one.
  • Change the animation of Cell and adopt usingSpringWithDamping as described in the previous chapter. UsingSpringWithDamping is set to 0.8 and initialSpringVelocity is set to 0.(otherwise, the animation will bounce too much, Cause successive exposure of white gap, very unattractive)
  • Change the specific mode of the Cell, which can be directly operatedcell.frame.origin.y, can also passcell.transform = CGAffineTransform(translationX: 0, y: tableHeight)The effect is the same. However, if you want to use zooming or rotating animations, you’ll probably have to use the latter.
  • Animation is really fun 🙂

Project 12 – Emoji Slot Machine

I learned a

  • At first glance, I was going to use three CollectionViews, but it turned out to be a bit complicated
  • Then switch to UIPickerView and set component to 3
  • Arc4random () is used to calculate the random number, and then the selectRow method of UIPickerView is used to set the value to achieve the effect of slot machines
  • For simulation purposes, you can’t have the pickerView go to the first or last one, or you’ll hit the edge, so when calculating random rows, use theInt(arc4random())%(emojiArray.count - 2) + 1To achieve
  • Three cases at the same time are too rare, so for the sake of simulation, I added a double click operation, double click forced 666…
  • This case is quite interesting, ha ha

Project 11 – Gradient in TableView

I learned a

  • This is a little bit easier, notice that the CAGradientLayer is applied to the UITableViewCell
  • It is recommended to use the CAGradientLayer as the backgroundView of the cell instead of adding it directly to the cell.layer
  • SeparatorStyle: table.separatorStyle =.None Cell.selectionStyle =.None

Project 10 – Stretchy Header

I learned a

  • By listening to the scrollViewDidScroll proxy of the ScrollView (and its subclasses), you can know the offset of the ScrollView being pulled.
  • The displacement and the limited zoom value can be used to determine the magnification rate of the image
  • This can be done by setting the ImageView’s Transform. The core code is
bannerImgView.transform = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)
Copy the code

Project 9 – Swipeable Cell

I learned a

For simplicity, I used the Project 13 code base and changed it to a crisp green 🙂

  • Implement the Delegate method editActionsForRowAt, which returns Array. Create a few new functions and return them
  • Each Action is created directly through the INIT method of UITableView Action. There’s a block in the new method, so just put the click logic in there.
  • The interaction is a simple one, with no requirements on the size and content of the interactive button; If you have special requirements, you need to customize the UITableViewCell, manually control the Cell and capture UIPanGesture to achieve. Note that this method should not be triggered by sliding the Cell up and down.

Project 8 – Color Gradient

I learned a

  • The color gradient effect uses the CAGradientLayer class
  • The concept of Color space can be implemented with the help of the Color array, noting that the member variables are of type CGColor, and then implemented by setting the Colors property of the CAGradientLayer
  • Changing colors while sliding up and down is done by adding the PanGestureRecognizer. The specific effect is referred to the applicationSolar

Project 7 – Simple Photo Browser

I learned a

  • How to scale images: Add imageView to ScrollView
  • Set the Max /minZoomScale of the scrollView
  • Set up the delegate object and at least implement the viewForZooming proxy method

Project 6 – Video Player

I learned a

  • AVPlayer: video player entity
  • AVPlayerViewController: a simple encapsulated video player with simple controls
  • AVPlayerLayer: The Layer Layer of the video, all functions need to write controls for control, suitable for in-depth development of the player
  • Plist setting mode for background playback
  • do… catch… Use of grammar
  • Background modes Settings.
  • How to make app run in the background for a long time: refer to jian Shu’s article
  • How to display screen lock information and how to respond to screen lock Settings (implementing the proxy method of remoteControlReceived)

Project 5 – Pull To Refresh

I learned a

  • Drop down refresh component: UIRefreshControl sets the prompt textattributedTitleAdd the target event (UIControlEvents.valueChangedEvent) and add it to tableView

Project 4 – Limited Input Text Field

I learned a

  • Create the left and right items of navigationBarItem by creating a new UIBarButtonItem
  • Limit the number of words entered by capturing the current input through the TextView’s textViewDidChange event
  • Through listening NSNotification. Name. UIKeyboardWillChangeFrame events to monitor the rid_device_info_keyboard pop up and pack up. In the corresponding callback, note. UserInfo? Got a keyboard endFrame [UIKeyboardFrameEndUserInfoKey] to get the height of the keyboard, to frame the counter operations
  • Similarly, note. UserInfo? Animation duration [UIKeyboardAnimationDurationUserInfoKey] get a keyboard, and then changes can be done through the UIView animation animation of the synchronous counter frame

Project 3 – Find My Position

I learned a

  • Anchor point configuration, the configuration is added in the plist: NSLocationAlwaysUsageDescription
  • Use CLLocationManager for location
  • In reverseGeocodeLocation call if a block occurs all the timeDomain=GEOErrorDomain Code=-8 "(null)"And so onCLGeocoderChange it to a global variable
  • Later, this simple function can be completed directly through apple’s built-in method, without the need to introduce The AUtonavi SDK (the size of the SDK is omitted).

Project 2: Watch Demo

I learned a

  • The Update cocoaPods to 1.2.0
  • Learn how to use SnapKit (Quite similar with Masonry)
  • Learn how to use Timer in Swift
  • I learned: guard statement, see guard details

Project 1: Change Custom Font

I learned a

  • How to modify font properties, familiar with font properties

  • The font name can be queried in a storyboard or by using the following code:

    func printAllSupportedFontNames() {
    let familyNames = UIFont.familyNames
    for familyName in familyNames {
        print("++++++ \(familyName)")
        let fontNames = UIFont.fontNames(forFamilyName: familyName)
        for fontName in fontNames {
            print("----- \(fontName)")
        }}}
    Copy the code

Write at the end:

If you can see here, I will manually double click 666 for you!

To be honest, the article is a bit of a headline, but the actual development time is about 40 days, because the development time is from work to bed, so sometimes I have to go out to dinner, sometimes I am lazy, and sometimes I need you to understand at night, so the completion of these 30 projects takes longer than the planned time…

After writing these projects, I feel that on the one hand, I have improved my proficiency in using Swift language, and on the other hand, I have reviewed the knowledge points of iOS development, because AFTER writing these projects, I have basically felt that there is no difference in thinking with OC development. This answers the question someone asked me, “If I study iOS development now, should I study OC or Swift?” :

I think from the perspective of familiarity with iOS SDK, there is no essential difference. If you are familiar with the corresponding syntax under OC, there is no big difference in using Swift to write. So instead of spending time obsessing, find two projects to practice on.

Next, I plan to sort out the Swift syntax again and conduct a small-scale reconstruction of these projects to see if I can dig into the features of Swift from a structural point of view and learn Swift from another (currently functional) perspective. So maybe there will be another one.