Top iOS Interview Questions and Answers

author image Hirely
at 07 Jan, 2025

Question: What is the purpose of @objc in Swift?

Answer:

The @objc attribute in Swift is used to expose Swift code (such as methods, properties, or classes) to the Objective-C runtime. This allows Swift code to be used with Objective-C features, such as dynamic dispatch, selectors, KVO (Key-Value Observing), and targets for actions. The @objc attribute is essential for interoperability between Swift and Objective-C, especially when working with APIs that require Objective-C runtime features.

Here are the key purposes and use cases of @objc in Swift:


1. Interoperability with Objective-C

  • Swift is designed to work seamlessly with Objective-C, and @objc is used to expose Swift code to the Objective-C runtime. This is particularly important when you’re using Objective-C frameworks (such as UIKit or Foundation) in your Swift projects, as they often rely on features like selectors, dynamic dispatch, and KVO, which are part of the Objective-C runtime.

    Example:

    @objc class MyClass: NSObject {
        @objc func myMethod() {
            print("This method can be called from Objective-C")
        }
    }

    In this example, the class MyClass is marked with @objc, making it compatible with the Objective-C runtime. The myMethod() is also marked with @objc, making it accessible to Objective-C code.


2. Using Selectors

  • @objc allows methods to be referenced as selectors. In Objective-C, selectors are used to refer to methods by name, and you can use them to perform methods dynamically, such as in performSelector:, or with UI actions like buttons and targets.

    Example:

    class MyViewController: UIViewController {
        @objc func buttonTapped() {
            print("Button was tapped")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let button = UIButton(type: .system)
            button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
            // This makes the button tap trigger the 'buttonTapped' method
        }
    }

    Here, @objc is necessary for the method buttonTapped() to be used as a selector in the addTarget method.


3. Key-Value Observing (KVO)

  • In Swift, @objc is required for a method to work with Key-Value Observing (KVO). KVO is a mechanism in Objective-C that allows objects to observe changes to properties in other objects. Swift does not natively support KVO, but you can still use it by marking methods and properties with @objc.

    Example:

    @objc class MyModel: NSObject {
        @objc dynamic var name: String = ""
    }
    
    let model = MyModel()
    model.addObserver(self, forKeyPath: #keyPath(MyModel.name), options: .new, context: nil)

    The @objc dynamic keyword combination is used to enable KVO for Swift properties, making them observable by Objective-C components.


4. Making Swift Methods Available for Objective-C Runtime

  • When using frameworks that rely on the Objective-C runtime (such as UIBarButtonItem or NSNotificationCenter), you often need to mark Swift methods with @objc so that they can be accessed by Objective-C code.

    Example:

    class MyClass: NSObject {
        @objc func handleNotification(notification: Notification) {
            print("Notification received: \(notification)")
        }
    }
    
    let myClass = MyClass()
    NotificationCenter.default.addObserver(myClass, selector: #selector(myClass.handleNotification(notification:)), name: .someNotification, object: nil)

    In this case, handleNotification(notification:) must be exposed to the Objective-C runtime to be used with NotificationCenter’s selector.


5. Support for Protocols with Objective-C Requirements

  • Some Objective-C protocols or APIs (e.g., UITableViewDelegate or UIActionSheetDelegate) require methods to be marked with @objc. When a Swift class conforms to such protocols, Swift automatically adds the @objc attribute to required methods.

    Example:

    @objc protocol MyDelegate: AnyObject {
        func didUpdateData()
    }
    
    class MyViewController: UIViewController, MyDelegate {
        @objc func didUpdateData() {
            print("Data has been updated.")
        }
    }

    Here, the didUpdateData method must be exposed to the Objective-C runtime so that the protocol can be used effectively in Objective-C code.


6. Dynamic Dispatch for Swift Methods

  • Swift uses static dispatch by default, which means methods are called directly based on their type at compile time. However, @objc enables dynamic dispatch, allowing the method to be looked up at runtime (i.e., through the Objective-C runtime). This is crucial for situations like method swizzling, where methods are dynamically replaced at runtime.

7. Using @objc with Properties and Initializers

  • @objc can also be used with properties and initializers to expose them to the Objective-C runtime.

    Example:

    class MyClass: NSObject {
        @objc var myProperty: String = ""
        
        @objc init(property: String) {
            self.myProperty = property
            super.init()
        }
    }

    In this case, both the property and the initializer are accessible from Objective-C code.


Conclusion

The @objc attribute serves to bridge Swift code with the Objective-C runtime, making it possible for Swift code to interact with Objective-C APIs and frameworks that depend on runtime features such as selectors, dynamic dispatch, KVO, and method swizzling. It’s also essential for interoperability between Swift and Objective-C, allowing you to use features like the target-action pattern and notifications in iOS development.

Question: What is the difference between frame and bounds in UIKit?

Answer:

In UIKit, frame and bounds are both properties used to describe the size and position of views, but they are used in different contexts and represent different coordinate systems. Here’s a detailed breakdown of the differences:


1. Frame

  • The frame property represents the view’s position and size relative to its superview’s coordinate system. It is a CGRect that contains both the origin (x, y) and size (width, height) of the view.

  • The origin of the frame is specified in the coordinate system of the view’s superview. The frame is affected by the position of the view in its superview.

  • The frame property includes:

    • Origin: The position of the view in its superview’s coordinate system (x, y).
    • Size: The width and height of the view.
  • When to use: The frame is often used to determine or set a view’s position and size within its superview, especially when positioning a view within a layout.

    Example:

    let myView = UIView()
    myView.frame = CGRect(x: 50, y: 100, width: 200, height: 300)
    // This means the view's top-left corner is at (50, 100) in the superview's coordinate system

2. Bounds

  • The bounds property represents the view’s own coordinate system. It is also a CGRect, but it contains the origin and size of the view in its own local coordinate space.

  • The origin of bounds is typically (0, 0), representing the top-left corner of the view in its own local coordinate system. However, it can be changed to adjust the view’s content position (e.g., in cases like scrolling).

  • The bounds property includes:

    • Origin: Usually (0, 0), but can be adjusted to change the view’s internal content position (e.g., for panning or scrolling).
    • Size: The width and height of the view, which determines its internal size.
  • When to use: The bounds is often used when you need to work with the view’s content size or position within its own local coordinate system, such as when implementing custom drawing or handling internal animations.

    Example:

    let myView = UIView()
    myView.bounds = CGRect(x: 0, y: 0, width: 200, height: 300)
    // This means the view's internal content size is 200x300

Key Differences:

Aspectframebounds
Coordinate SystemRelative to the superview’s coordinate systemRelative to the view’s own coordinate system
OriginAffects the position of the view within the superviewTypically (0, 0), but can be modified for internal content positioning
Use CaseUsed for positioning and sizing the view within its superviewUsed for the view’s internal layout or content (e.g., for drawing or transformations)
Affect on View’s PositionChanging the frame.origin moves the viewChanging the bounds.origin moves the content inside the view
Affect on View’s SizeChanging the frame.size changes the view’s sizeChanging the bounds.size changes the view’s internal content area (doesn’t affect positioning)

Examples to Clarify:

  • Frame Example:
    If you change the frame.origin of a view, you move the view within its superview.

    myView.frame.origin = CGPoint(x: 100, y: 200)
    // The view will now be positioned at (100, 200) within its superview
  • Bounds Example:
    If you change the bounds.origin, you affect the content inside the view, but it doesn’t move the view itself.

    myView.bounds.origin = CGPoint(x: 10, y: 10)
    // This shifts the content inside the view, but the view's position on the screen does not change

Summary:

  • frame is used for positioning and sizing a view in relation to its superview.
  • bounds describes the view’s internal coordinate system and size, often used for custom content layout or transformations.

By understanding the difference, you can effectively manage views and their content within your app’s layout and positioning.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as iOS interview questions, iOS interview experiences, and details about various iOS job positions. Click here to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now