Rectangle 27 397

2. Interacting with an Objective-C API

Before I can describe the use cases for Implicitly Unwrapped Optionals, you should already understand what Optionals and Implicitly Unwrapped Optionals are in Swift. If you do not, I recommend you first read my article on optionals

There are four main reasons that one would create an Implicitly Unwrapped Optional. All have to do with defining a variable that will never be accessed when nil because otherwise, the Swift compiler will always force you to explicitly unwrap an Optional.

Every member constant must have a value by the time initialization is complete. Sometimes, a constant cannot be initialized with its correct value during initialization, but it can still be guaranteed to have a value before being accessed.

Using an Optional variable gets around this issue because an Optional is automatically initialized with nil and the value it will eventually contain will still be immutable. However, it can be a pain to be constantly unwrapping a variable that you know for sure is not nil. Implicitly Unwrapped Optionals achieve the same benefits as an Optional with the added benefit that one does not have to explicitly unwrap it everywhere.

A great example of this is when a member variable cannot be initialized in a UIView subclass until the view is loaded:

class MyView : UIView {
    @IBOutlet var button : UIButton!
    var buttonOriginalWidth : CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

Here, you cannot calculate the original width of the button until the view loads, but you know that awakeFromNib will be called before any other method on the view (other than initialization). Instead of forcing the value to be explicitly unwrapped pointlessly all over your class, you can declare it as an Implicitly Unwrapped Optional.

Every reference to an object in Objective-C is a pointer, which means that it can be nil. That means, that every interaction with an Objective-C API from Swift must use an optional where there is a reference to an object. You could use a normal Optional in every one of these cases, but if you know for sure that the reference will not be nil, you can save yourself unwrapping code by declaring it as an Implicitly Unwrapped Optional.

UITableViewDataSource
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? { return nil }

Here, you know that the method will never be called without a tableView or indexPath. It would be a waste of time to check it for nil. If this were a purely Swift API, one would not declare it as an Optional at all.

This should be extremely rare, but if your app could literally not continue to run if a variable is nil when accessed, it would be a waste of time to bother testing it for nil. Normally if you have a condition that must absolutely be true for your app to continue running, you would use an assert. An Implicitly Unwrapped Optional has an assert for nil built right into it.

Apple does have at least one strange case of Implicitly Unwrapped Optionals. Technically, all initializers from classes that inherit from NSObject return Implicitly Unwrapped Optionals. This is because initialization in Objective-C can return nil. That means, in some cases, that you will still want to be able to test the result of initialization for nil. A perfect example of this is with UIImage if the image does not exist:

var image : UIImage? = UIImage(named: "NonExistentImage")
if image != nil {
    println("image exists")
}
else {
    println("image does not exist")
}

If you think there is a chance that your image does not exist and you can gracefully handle that scenario, you can declare the variable capturing the initialization explicitly as an Optional so that you can check it for nil. You could also use an Implicitly Unwrapped Optional here, but since you are planning to check it anyway, it is better to use a normal Optional.

Sometimes you have a member variable that should never be nil, but it cannot be set to the correct value during initialization. One solution is to use an Implicitly Unwrapped Optional, but a better way is to use a lazy variable:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

Now, the member variable contents is not initialized until the first time it is accessed. This gives the class a chance to get into the correct state before calculating the initial value.

Note: This may seem to contradict #1 from above. However, there is an important distinction to be made. The buttonOriginalWidth above must be set during viewDidLoad to prevent anyone changing the buttons width before the property is accessed.

For the most part, Implicitly Unwrapped Optionals should be avoided because if used mistakenly, your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn't hurt very much.

if someOptional

@SantaClaus hasValue is defined right on Optional. I prefer the semantics of hasValue to those of != nil. I feel it is much more understandable for new programers who have not used nil in other languages. hasValue is much more logical than nil.

Looks like hasValue was pulled from beta 6. Ash put it back though... github.com/AshFurrow/hasValue

@newacct Regarding the return type of Objc initializers, it is more of an implicit Implicitly Unwrapped Optional. The behavior you described for using a "non-optional" is exactly what an Implicitly Unwrapped Optional would do (not fail until being accessed). Regarding letting the program fail earlier by forcibly unwrapping, I agree that using a non-optional is preferred, but this is not always possible.

@confile no. No matter what, it is going to appear in Objective-C as a pointer (if it were optional, implicitly unwrapped, or non-optional).

swift - Why create "Implicitly Unwrapped Optionals"? - Stack Overflow

swift
Rectangle 27 397

2. Interacting with an Objective-C API

Before I can describe the use cases for Implicitly Unwrapped Optionals, you should already understand what Optionals and Implicitly Unwrapped Optionals are in Swift. If you do not, I recommend you first read my article on optionals

There are four main reasons that one would create an Implicitly Unwrapped Optional. All have to do with defining a variable that will never be accessed when nil because otherwise, the Swift compiler will always force you to explicitly unwrap an Optional.

Every member constant must have a value by the time initialization is complete. Sometimes, a constant cannot be initialized with its correct value during initialization, but it can still be guaranteed to have a value before being accessed.

Using an Optional variable gets around this issue because an Optional is automatically initialized with nil and the value it will eventually contain will still be immutable. However, it can be a pain to be constantly unwrapping a variable that you know for sure is not nil. Implicitly Unwrapped Optionals achieve the same benefits as an Optional with the added benefit that one does not have to explicitly unwrap it everywhere.

A great example of this is when a member variable cannot be initialized in a UIView subclass until the view is loaded:

class MyView : UIView {
    @IBOutlet var button : UIButton!
    var buttonOriginalWidth : CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

Here, you cannot calculate the original width of the button until the view loads, but you know that awakeFromNib will be called before any other method on the view (other than initialization). Instead of forcing the value to be explicitly unwrapped pointlessly all over your class, you can declare it as an Implicitly Unwrapped Optional.

Every reference to an object in Objective-C is a pointer, which means that it can be nil. That means, that every interaction with an Objective-C API from Swift must use an optional where there is a reference to an object. You could use a normal Optional in every one of these cases, but if you know for sure that the reference will not be nil, you can save yourself unwrapping code by declaring it as an Implicitly Unwrapped Optional.

UITableViewDataSource
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? { return nil }

Here, you know that the method will never be called without a tableView or indexPath. It would be a waste of time to check it for nil. If this were a purely Swift API, one would not declare it as an Optional at all.

This should be extremely rare, but if your app could literally not continue to run if a variable is nil when accessed, it would be a waste of time to bother testing it for nil. Normally if you have a condition that must absolutely be true for your app to continue running, you would use an assert. An Implicitly Unwrapped Optional has an assert for nil built right into it.

Apple does have at least one strange case of Implicitly Unwrapped Optionals. Technically, all initializers from classes that inherit from NSObject return Implicitly Unwrapped Optionals. This is because initialization in Objective-C can return nil. That means, in some cases, that you will still want to be able to test the result of initialization for nil. A perfect example of this is with UIImage if the image does not exist:

var image : UIImage? = UIImage(named: "NonExistentImage")
if image != nil {
    println("image exists")
}
else {
    println("image does not exist")
}

If you think there is a chance that your image does not exist and you can gracefully handle that scenario, you can declare the variable capturing the initialization explicitly as an Optional so that you can check it for nil. You could also use an Implicitly Unwrapped Optional here, but since you are planning to check it anyway, it is better to use a normal Optional.

Sometimes you have a member variable that should never be nil, but it cannot be set to the correct value during initialization. One solution is to use an Implicitly Unwrapped Optional, but a better way is to use a lazy variable:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

Now, the member variable contents is not initialized until the first time it is accessed. This gives the class a chance to get into the correct state before calculating the initial value.

Note: This may seem to contradict #1 from above. However, there is an important distinction to be made. The buttonOriginalWidth above must be set during viewDidLoad to prevent anyone changing the buttons width before the property is accessed.

For the most part, Implicitly Unwrapped Optionals should be avoided because if used mistakenly, your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn't hurt very much.

if someOptional

@SantaClaus hasValue is defined right on Optional. I prefer the semantics of hasValue to those of != nil. I feel it is much more understandable for new programers who have not used nil in other languages. hasValue is much more logical than nil.

Looks like hasValue was pulled from beta 6. Ash put it back though... github.com/AshFurrow/hasValue

@newacct Regarding the return type of Objc initializers, it is more of an implicit Implicitly Unwrapped Optional. The behavior you described for using a "non-optional" is exactly what an Implicitly Unwrapped Optional would do (not fail until being accessed). Regarding letting the program fail earlier by forcibly unwrapping, I agree that using a non-optional is preferred, but this is not always possible.

@confile no. No matter what, it is going to appear in Objective-C as a pointer (if it were optional, implicitly unwrapped, or non-optional).

swift - Why create "Implicitly Unwrapped Optionals"? - Stack Overflow

swift
Rectangle 27 395

2. Interacting with an Objective-C API

Before I can describe the use cases for Implicitly Unwrapped Optionals, you should already understand what Optionals and Implicitly Unwrapped Optionals are in Swift. If you do not, I recommend you first read my article on optionals

There are four main reasons that one would create an Implicitly Unwrapped Optional. All have to do with defining a variable that will never be accessed when nil because otherwise, the Swift compiler will always force you to explicitly unwrap an Optional.

Every member constant must have a value by the time initialization is complete. Sometimes, a constant cannot be initialized with its correct value during initialization, but it can still be guaranteed to have a value before being accessed.

Using an Optional variable gets around this issue because an Optional is automatically initialized with nil and the value it will eventually contain will still be immutable. However, it can be a pain to be constantly unwrapping a variable that you know for sure is not nil. Implicitly Unwrapped Optionals achieve the same benefits as an Optional with the added benefit that one does not have to explicitly unwrap it everywhere.

A great example of this is when a member variable cannot be initialized in a UIView subclass until the view is loaded:

class MyView : UIView {
    @IBOutlet var button : UIButton!
    var buttonOriginalWidth : CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

Here, you cannot calculate the original width of the button until the view loads, but you know that awakeFromNib will be called before any other method on the view (other than initialization). Instead of forcing the value to be explicitly unwrapped pointlessly all over your class, you can declare it as an Implicitly Unwrapped Optional.

Every reference to an object in Objective-C is a pointer, which means that it can be nil. That means, that every interaction with an Objective-C API from Swift must use an optional where there is a reference to an object. You could use a normal Optional in every one of these cases, but if you know for sure that the reference will not be nil, you can save yourself unwrapping code by declaring it as an Implicitly Unwrapped Optional.

UITableViewDataSource
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? { return nil }

Here, you know that the method will never be called without a tableView or indexPath. It would be a waste of time to check it for nil. If this were a purely Swift API, one would not declare it as an Optional at all.

This should be extremely rare, but if your app could literally not continue to run if a variable is nil when accessed, it would be a waste of time to bother testing it for nil. Normally if you have a condition that must absolutely be true for your app to continue running, you would use an assert. An Implicitly Unwrapped Optional has an assert for nil built right into it.

Apple does have at least one strange case of Implicitly Unwrapped Optionals. Technically, all initializers from classes that inherit from NSObject return Implicitly Unwrapped Optionals. This is because initialization in Objective-C can return nil. That means, in some cases, that you will still want to be able to test the result of initialization for nil. A perfect example of this is with UIImage if the image does not exist:

var image : UIImage? = UIImage(named: "NonExistentImage")
if image != nil {
    println("image exists")
}
else {
    println("image does not exist")
}

If you think there is a chance that your image does not exist and you can gracefully handle that scenario, you can declare the variable capturing the initialization explicitly as an Optional so that you can check it for nil. You could also use an Implicitly Unwrapped Optional here, but since you are planning to check it anyway, it is better to use a normal Optional.

Sometimes you have a member variable that should never be nil, but it cannot be set to the correct value during initialization. One solution is to use an Implicitly Unwrapped Optional, but a better way is to use a lazy variable:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

Now, the member variable contents is not initialized until the first time it is accessed. This gives the class a chance to get into the correct state before calculating the initial value.

Note: This may seem to contradict #1 from above. However, there is an important distinction to be made. The buttonOriginalWidth above must be set during viewDidLoad to prevent anyone changing the buttons width before the property is accessed.

For the most part, Implicitly Unwrapped Optionals should be avoided because if used mistakenly, your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn't hurt very much.

if someOptional

@SantaClaus hasValue is defined right on Optional. I prefer the semantics of hasValue to those of != nil. I feel it is much more understandable for new programers who have not used nil in other languages. hasValue is much more logical than nil.

Looks like hasValue was pulled from beta 6. Ash put it back though... github.com/AshFurrow/hasValue

@newacct Regarding the return type of Objc initializers, it is more of an implicit Implicitly Unwrapped Optional. The behavior you described for using a "non-optional" is exactly what an Implicitly Unwrapped Optional would do (not fail until being accessed). Regarding letting the program fail earlier by forcibly unwrapping, I agree that using a non-optional is preferred, but this is not always possible.

@confile no. No matter what, it is going to appear in Objective-C as a pointer (if it were optional, implicitly unwrapped, or non-optional).

swift - Why create "Implicitly Unwrapped Optionals"? - Stack Overflow

swift
Rectangle 27 398

2. Interacting with an Objective-C API

Before I can describe the use cases for Implicitly Unwrapped Optionals, you should already understand what Optionals and Implicitly Unwrapped Optionals are in Swift. If you do not, I recommend you first read my article on optionals

There are four main reasons that one would create an Implicitly Unwrapped Optional. All have to do with defining a variable that will never be accessed when nil because otherwise, the Swift compiler will always force you to explicitly unwrap an Optional.

Every member constant must have a value by the time initialization is complete. Sometimes, a constant cannot be initialized with its correct value during initialization, but it can still be guaranteed to have a value before being accessed.

Using an Optional variable gets around this issue because an Optional is automatically initialized with nil and the value it will eventually contain will still be immutable. However, it can be a pain to be constantly unwrapping a variable that you know for sure is not nil. Implicitly Unwrapped Optionals achieve the same benefits as an Optional with the added benefit that one does not have to explicitly unwrap it everywhere.

A great example of this is when a member variable cannot be initialized in a UIView subclass until the view is loaded:

class MyView : UIView {
    @IBOutlet var button : UIButton!
    var buttonOriginalWidth : CGFloat!

    override func awakeFromNib() {
        self.buttonOriginalWidth = self.button.frame.size.width
    }
}

Here, you cannot calculate the original width of the button until the view loads, but you know that awakeFromNib will be called before any other method on the view (other than initialization). Instead of forcing the value to be explicitly unwrapped pointlessly all over your class, you can declare it as an Implicitly Unwrapped Optional.

Every reference to an object in Objective-C is a pointer, which means that it can be nil. That means, that every interaction with an Objective-C API from Swift must use an optional where there is a reference to an object. You could use a normal Optional in every one of these cases, but if you know for sure that the reference will not be nil, you can save yourself unwrapping code by declaring it as an Implicitly Unwrapped Optional.

UITableViewDataSource
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? { return nil }

Here, you know that the method will never be called without a tableView or indexPath. It would be a waste of time to check it for nil. If this were a purely Swift API, one would not declare it as an Optional at all.

This should be extremely rare, but if your app could literally not continue to run if a variable is nil when accessed, it would be a waste of time to bother testing it for nil. Normally if you have a condition that must absolutely be true for your app to continue running, you would use an assert. An Implicitly Unwrapped Optional has an assert for nil built right into it.

Apple does have at least one strange case of Implicitly Unwrapped Optionals. Technically, all initializers from classes that inherit from NSObject return Implicitly Unwrapped Optionals. This is because initialization in Objective-C can return nil. That means, in some cases, that you will still want to be able to test the result of initialization for nil. A perfect example of this is with UIImage if the image does not exist:

var image : UIImage? = UIImage(named: "NonExistentImage")
if image != nil {
    println("image exists")
}
else {
    println("image does not exist")
}

If you think there is a chance that your image does not exist and you can gracefully handle that scenario, you can declare the variable capturing the initialization explicitly as an Optional so that you can check it for nil. You could also use an Implicitly Unwrapped Optional here, but since you are planning to check it anyway, it is better to use a normal Optional.

Sometimes you have a member variable that should never be nil, but it cannot be set to the correct value during initialization. One solution is to use an Implicitly Unwrapped Optional, but a better way is to use a lazy variable:

class FileSystemItem {
}

class Directory : FileSystemItem {
    lazy var contents : [FileSystemItem] = {
        var loadedContents = [FileSystemItem]()
        // load contents and append to loadedContents
        return loadedContents
    }()
}

Now, the member variable contents is not initialized until the first time it is accessed. This gives the class a chance to get into the correct state before calculating the initial value.

Note: This may seem to contradict #1 from above. However, there is an important distinction to be made. The buttonOriginalWidth above must be set during viewDidLoad to prevent anyone changing the buttons width before the property is accessed.

For the most part, Implicitly Unwrapped Optionals should be avoided because if used mistakenly, your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn't hurt very much.

if someOptional

@SantaClaus hasValue is defined right on Optional. I prefer the semantics of hasValue to those of != nil. I feel it is much more understandable for new programers who have not used nil in other languages. hasValue is much more logical than nil.

Looks like hasValue was pulled from beta 6. Ash put it back though... github.com/AshFurrow/hasValue

@newacct Regarding the return type of Objc initializers, it is more of an implicit Implicitly Unwrapped Optional. The behavior you described for using a "non-optional" is exactly what an Implicitly Unwrapped Optional would do (not fail until being accessed). Regarding letting the program fail earlier by forcibly unwrapping, I agree that using a non-optional is preferred, but this is not always possible.

@confile no. No matter what, it is going to appear in Objective-C as a pointer (if it were optional, implicitly unwrapped, or non-optional).

swift - Why create "Implicitly Unwrapped Optionals", since that implie...

swift design optional
Rectangle 27 7

3. Call Swift class from Objective-c code

Details: Objective-C project with Swift 3 code in Xcode 8.1

  • Use swift enum in objective-c class
  • Use objective-c enum in swift class
#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end
#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

In my sample I use SwiftCode.h to detect Swift code in Objective-C. This file generate automatically (I did not create a physical copy of this header file in a project), and you can only set name of this file:

If the compiler can not find your header file Swift code, try to compile the project.

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

You need to create bridging header file. When you add Swift file in Objective-C project, or Objective-C file in swift project Xcode will suggest you to create bridging header.

You can change bridging header file name here:

#import "ObjcClass.h"
#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

Full integration steps Objective-c and Swift described above

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}
SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";
#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end
#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end
if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}
extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}
[UIView swiftExtensionFunc];
#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end
@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end
UIView.objcExtensionFunc()

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 7

3. Call Swift class from Objective-c code

Details: Objective-C project with Swift 3 code in Xcode 8.1

  • Use swift enum in objective-c class
  • Use objective-c enum in swift class
#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end
#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

In my sample I use SwiftCode.h to detect Swift code in Objective-C. This file generate automatically (I did not create a physical copy of this header file in a project), and you can only set name of this file:

If the compiler can not find your header file Swift code, try to compile the project.

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

You need to create bridging header file. When you add Swift file in Objective-C project, or Objective-C file in swift project Xcode will suggest you to create bridging header.

You can change bridging header file name here:

#import "ObjcClass.h"
#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

Full integration steps Objective-c and Swift described above

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}
SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";
#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end
#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end
if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}
extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}
[UIView swiftExtensionFunc];
#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end
@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end
UIView.objcExtensionFunc()

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 7

3. Call Swift class from Objective-c code

Details: Objective-C project with Swift 3 code in Xcode 8.1

  • Use swift enum in objective-c class
  • Use objective-c enum in swift class
#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end
#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

In my sample I use SwiftCode.h to detect Swift code in Objective-C. This file generate automatically (I did not create a physical copy of this header file in a project), and you can only set name of this file:

If the compiler can not find your header file Swift code, try to compile the project.

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

You need to create bridging header file. When you add Swift file in Objective-C project, or Objective-C file in swift project Xcode will suggest you to create bridging header.

You can change bridging header file name here:

#import "ObjcClass.h"
#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

Full integration steps Objective-c and Swift described above

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}
SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";
#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end
#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end
if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}
extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}
[UIView swiftExtensionFunc];
#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end
@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end
UIView.objcExtensionFunc()

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 5

Use your swift file in objective c file.

  • Use your swift file in objective c file.
  • Use your objective c file in swift file.
  • Add your swift file in an objective-c project or vice-versa.

Go to Build Settings and perform below steps with search,

  • search for this text "brid" and set a path of your header file.
  • "Always Embed Swift Standard Libraries" : YES.
  • "Install Objective-C Compatibility Header" : YES.

In that case,First write "@objc" before your class in swift file.

After that ,In your objective c file, write this,

#import "YourProjectName-Swift.h"

In that case, In your header file, write this,

#import "YourObjective-c_FileName.h"

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 5

Use your swift file in objective c file.

  • Use your swift file in objective c file.
  • Use your objective c file in swift file.
  • Add your swift file in an objective-c project or vice-versa.

Go to Build Settings and perform below steps with search,

  • search for this text "brid" and set a path of your header file.
  • "Always Embed Swift Standard Libraries" : YES.
  • "Install Objective-C Compatibility Header" : YES.

In that case,First write "@objc" before your class in swift file.

After that ,In your objective c file, write this,

#import "YourProjectName-Swift.h"

In that case, In your header file, write this,

#import "YourObjective-c_FileName.h"

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 5

Use your swift file in objective c file.

  • Use your swift file in objective c file.
  • Use your objective c file in swift file.
  • Add your swift file in an objective-c project or vice-versa.

Go to Build Settings and perform below steps with search,

  • search for this text "brid" and set a path of your header file.
  • "Always Embed Swift Standard Libraries" : YES.
  • "Install Objective-C Compatibility Header" : YES.

In that case,First write "@objc" before your class in swift file.

After that ,In your objective c file, write this,

#import "YourProjectName-Swift.h"

In that case, In your header file, write this,

#import "YourObjective-c_FileName.h"

ios - Can't use Swift classes inside Objective-C - Stack Overflow

ios objective-c swift
Rectangle 27 8

Linking and the Objective-C runtime

So, your problems are pretty unrelated to the principal class. You should leave the principal class as NSApplication.

The major problem, as I alluded to before, is that you don't register an appropriate application delegate with NSApplication. Changing the principal class will not fix this. A NIB file can set the application delegate, but that's really overkill for this problem.

However, there are actually several problems:

OSX application delegates derive from NSObject, not from UIResponder, so the line:

AppDelClass = objc_allocateClassPair((Class) objc_getClass("NSObject"), "AppDelegate", 0);

Also, OSX application delegates respond to different messages than iOS application delegates. In particular, they need to respond to the applicationDidFinishLaunching: selector (which takes an NSNotifier object of type id).

class_addMethod(AppDelClass, sel_getUid("application:didFinishLaunchingWithOptions:"), (IMP) AppDel_didFinishLaunching, "i@:@@");
class_addMethod(AppDelClass, sel_getUid("applicationDidFinishLaunching:"), (IMP) AppDel_didFinishLaunching, "i@:@");

Notice that the parameters ("i@:@@" and "i@:@") are different.

There are two choices for registering AppDelegate with the Objective-C runtime:

I generally don't trust __attribute__ labels. They'll probably stay the same, but Apple might change them. I've chosen to call initAppDel from main.

Once you register your AppDelegate class with the system, it basically works like an Objective-C class. You instantiate it like an Objective-C class, and you can pass it around like an id. It actually is an id.

To make sure that AppDelegate is run as the application delegate, you have to set up NSAppliction. Because you're rolling your own application delegate, you really cannot use NSApplicationMain to do this. It actually turned out to not be that hard:

void init_app(void)
{
  objc_msgSend(
      objc_getClass("NSApplication"), 
      sel_getUid("sharedApplication"));

  if (NSApp == NULL)
  {
    fprintf(stderr,"Failed to initialized NSApplication... terminating...\n");
    return;
  }

  id appDelObj = objc_msgSend(
      objc_getClass("AppDelegate"), 
      sel_getUid("alloc"));
  appDelObj = objc_msgSend(appDelObj, sel_getUid("init"));

  objc_msgSend(NSApp, sel_getUid("setDelegate:"), appDelObj);
  objc_msgSend(NSApp, sel_getUid("run"));
}

So, here's the real meat of the problem, at least for me. All of the above will fail, utterly and completely, unless you actually have NSObject and NSApplication registered in the Objective-C runtime.

Usually, if you're working in Objective-C, the compiler tells the linker that it needs that. It does this by putting a bunch of special unresolved symbols in the .o file. If I compile the file SomeObj.m:

#import <Foundation/NSObject.h>

@interface SomeObject : NSObject
@end

@implementation SomeObject
@end
clang -c SomeObj.m
nm SomeObj.o
0000000000000000 s L_OBJC_CLASS_NAME_
                 U _OBJC_CLASS_$_NSObject
00000000000000c8 S _OBJC_CLASS_$_SomeObject
                 U _OBJC_METACLASS_$_NSObject
00000000000000a0 S _OBJC_METACLASS_$_SomeObject
                 U __objc_empty_cache
                 U __objc_empty_vtable
0000000000000058 s l_OBJC_CLASS_RO_$_SomeObject
0000000000000010 s l_OBJC_METACLASS_RO_$_SomeObject

You'll see all those nice _OBJC_CLASS_$_ symbols with a U to the left, indicating that the symbols are unresolved. When you link this file, the linker takes this and then realizes that it has to load the Foundation framework to resolve the references. This forces the Foundation framework to register all of its classes with the Objective-C runtime. Something similar is required if your code needs the AppKit framework.

If I compile your AppDelegate code, which I've renamed 'AppDelegate_orig.c' with clang -c AppDelegate_orig.c and then run nm on it:

00000000000001b8 s EH_frame0
000000000000013c s L_.str
0000000000000145 s L_.str1
000000000000014b s L_.str2
0000000000000150 s L_.str3
0000000000000166 s L_.str4
0000000000000172 s L_.str5
000000000000017e s L_.str6
00000000000001a9 s L_.str7
0000000000000008 C _AppDelClass
0000000000000000 T _AppDel_didFinishLaunching
00000000000001d0 S _AppDel_didFinishLaunching.eh
                 U _class_addMethod
00000000000000c0 t _initAppDel
00000000000001f8 s _initAppDel.eh
                 U _objc_allocateClassPair
                 U _objc_getClass
                 U _objc_msgSend
                 U _objc_registerClassPair
                 U _sel_getUid

You'll see that there are no unresolved symbols that would force the Foundation or AppKit frameworks to link. This means that all my calls to objc_getClass would return NULL, which means that the whole thing comes crashing down.

I don't know what the rest of your code looks like, so this may not be an issue for you, but solving this problem let me compile a modified AppDelegate.c file by itself into a (not very functional) OSX application.

The secret here is to find an external symbol that requires the linker to bring in Foundation and AppKit. That turned out to be relatively easy. The AppKit provides a global variable NSApp which hold the application's instance of NSApplication. The AppKit framework relies on the Foundation framework, so we get that for free. Simply declaring an external reference to this was enough:

extern id NSApp;

(NB: You have to actually use the variable somewhere, or the compiler may optimize it away, and you'll lose the frameworks that you need.)

Here is my version of AppDelegate.c. It includes main and should set everything up. The result isn't all that exciting, but it does open a tiny window on the screen.

#include <stdio.h>
#include <stdlib.h>

#include <objc/runtime.h>
#include <objc/message.h>

extern id NSApp;

struct AppDel
{
    Class isa;
    id window;
};


// This is a strong reference to the class of the AppDelegate
// (same as [AppDelegate class])
Class AppDelClass;

BOOL AppDel_didFinishLaunching(struct AppDel *self, SEL _cmd, id notification) {
    self->window = objc_msgSend(objc_getClass("NSWindow"),
      sel_getUid("alloc"));

    self->window = objc_msgSend(self->window, 
      sel_getUid("init"));

    objc_msgSend(self->window, 
      sel_getUid("makeKeyAndOrderFront:"),
      self);

    return YES;
}

static void initAppDel() 
{
  AppDelClass = objc_allocateClassPair((Class)
    objc_getClass("NSObject"), "AppDelegate", 0);

  class_addMethod(AppDelClass, 
      sel_getUid("applicationDidFinishLaunching:"), 
      (IMP) AppDel_didFinishLaunching, "i@:@");

  objc_registerClassPair(AppDelClass);
}

void init_app(void)
{
  objc_msgSend(
      objc_getClass("NSApplication"), 
      sel_getUid("sharedApplication"));

  if (NSApp == NULL)
  {
    fprintf(stderr,"Failed to initialized NSApplication...  terminating...\n");
    return;
  }

  id appDelObj = objc_msgSend(
      objc_getClass("AppDelegate"), 
      sel_getUid("alloc"));
  appDelObj = objc_msgSend(appDelObj, sel_getUid("init"));

  objc_msgSend(NSApp, sel_getUid("setDelegate:"), appDelObj);
  objc_msgSend(NSApp, sel_getUid("run"));
}


int main(int argc, char** argv)
{
  initAppDel();
  init_app();
  return EXIT_SUCCESS;
}

Compile, install, and run like this:

clang -g -o AppInC AppDelegate.c -lobjc -framework Foundation -framework AppKit
mkdir -p AppInC.app/Contents/MacOS
cp AppInC AppInC.app/Contents/MacOS/
cp Info.plist AppInC.app/Contents/
open ./AppInC.app
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
        <string>AppInC</string>
        <key>CFBundleIconFile</key>
        <string></string>
        <key>CFBundleIdentifier</key>
        <string>com.foo.AppInC</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <string>AppInC</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
        <string>1.0</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
        <string>1</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.games</string>
        <key>LSMinimumSystemVersion</key>
        <string></string>
        <key>NSPrincipalClass</key>
        <string>NSApplication</string>
</dict>
</plist>

With a screenshot:

Again, the code isn't the issue,

The problem you stated was that your AppDelegate class couldn't be found. The difference between OSX and iOS is that UIApplicationMain will take the name of the app delegate. On OSX, you can set it programmatically by not using NSApplicationMain, and rolling your own. If you programmatically initialize the app delegate, why can't you use NSApplication as your principal class?

Because I can't conform to an ObjC delegate with a struct (class) in C. I also can't receive selectors.

It seems like you can tell the objc runtime that a class does conform to the protocol with class_addProtocol. Why would this not work?

Yes, and I have tried that. Again, another problem that comes up is that I can't cast a struct to id, I'd have to use an NSValue pointer, which makes my life infinitely harder... I'll try it again.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

objective c - C As Principal Class Or; A Cocoa App Without ObjC - Stac...

objective-c c osx cocoa objective-c-runtime
Rectangle 27 76

There's an Objective-C wrapper around raw memory which I like to use a lot for similar tasks: NSMutableData. It has the benefit of giving you retain/release ownership plus it can grow the array easily (without having you to do the realloc yourself).

NSMutableData* data = [NSMutableData dataWithLength:sizeof(int) * 100];
int* array = [data mutableBytes];
// memory is already zeroed

// use the array

// decide later that we need more space:
[data setLength:sizeof(int) * 200];
array = [data mutableBytes]; // re-fetch pointer in case memory needed to be copied

// no need to free
// (it's done when the autoreleased object is deallocated)

I like this answer @Nikolai Ruhe. I was using a "malloc"ed array as a property. I had 3 objects of this class, and I "free"ed the array in dealloc. However after releasing the first object, I got a "malloc: *** error for object 0x70a60: pointer being freed was not allocated" error when releasing the second!? Looks like the malloc was done at "class level", rather than "object level". Switching to your solution made this go away, but the "behaviour" of the objects also changed. Not yet sure why.

OK, I tried this and, to my horror, eventually found that my "array" filled-up with random bits. I guess the underlying "data" was autoreleased before I had finished with the array. Putting a "retain" on the data fixed that problem, but now I have to keep a reference to the "data" object, making this solution less attractive.

@iPadDeveloper2011: You need to brush up on your memory management. In this particular case, the data is being autoreleased. So long as the autorelease pool isn't drained, this code is fine, but once you reach a scope where there might be an autorelease pool that could drain, you can no longer use the data. If you need it to last longer, then you must retain it, and then release it when you're done.

I for one love this answer. I've always been bothered when I need to use arrays of ints and lose the reference-counting, and being able to easily extend them. Thanks for the very good explanation and examples!

Is it ok to use "classic" malloc()/free() in Objective-C/iPhone apps? ...

c objective-c memory-management
Rectangle 27 248

A word of caution here. In Objective-C, unlike many similar languages, you generally should try to avoid using exceptions for common error situations that may occur in normal operation.

A word of caution here. In Objective-C, unlike many similar languages, you generally should try to avoid using exceptions for common error situations that may occur in normal operation.

Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)"

Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)"

Apple's conceptual Exception handling documentation explains the same, but with more words: "Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime. [.....] Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications."

Apple's conceptual Exception handling documentation explains the same, but with more words: "Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime. [.....] Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications."

The reasons for this is partly to adhere to programming idioms in Objective-C (using return values in simple cases and by-reference parameters (often the NSError class) in more complex cases), partly that throwing and catching exceptions is much more expensive and finally (and perpaps most importantly) that Objective-C exceptions are a thin wrapper around C's setjmp() and longjmp() functions, essentially messing up your careful memory handling, see this explanation.

The reasons for this is partly to adhere to programming idioms in Objective-C (using return values in simple cases and by-reference parameters (often the NSError class) in more complex cases), partly that throwing and catching exceptions is much more expensive and finally (and perpaps most importantly) that Objective-C exceptions are a thin wrapper around C's setjmp() and longjmp() functions, essentially messing up your careful memory handling, see this explanation.

I think this applies to most programming languages: "try to avoid using exceptions for common error situations". The same applies in Java; it's bad practice to handle user input errors (for example) with exceptions. Not just because of resource usage, but also for code clarity.

I think this applies to most programming languages: "try to avoid using exceptions for common error situations". The same applies in Java; it's bad practice to handle user input errors (for example) with exceptions. Not just because of resource usage, but also for code clarity.

More importantly, Exceptions in Cocoa are designed to indicate non-recoverable program errors. Doing otherwise is running against the framework and can lead to undefined behaviour. See stackoverflow.com/questions/3378696/iphone-try-end-try/… for details.

More importantly, Exceptions in Cocoa are designed to indicate non-recoverable program errors. Doing otherwise is running against the framework and can lead to undefined behaviour. See stackoverflow.com/questions/3378696/iphone-try-end-try/ for details.

"The same applies in Java;" Disagree. You can use checked exceptions in Java just fine for normal error conditions. Of course you wouldn't use Runtime exceptions.

"The same applies in Java;" Disagree. You can use checked exceptions in Java just fine for normal error conditions. Of course you wouldn't use Runtime exceptions.

I prefer the Cocoa way (exceptions are for programmer errors only) so I'd prefer to do it in Java as well, but the reality is that you should go with typical practices in an environment, and exceptions for error handling sticks out like a bad smell in Objective-C, but are used a lot for that purpose in Java.

I prefer the Cocoa way (exceptions are for programmer errors only) so I'd prefer to do it in Java as well, but the reality is that you should go with typical practices in an environment, and exceptions for error handling sticks out like a bad smell in Objective-C, but are used a lot for that purpose in Java.

This comment does not reply the question. Maybe the OP just wants to crash the app to test whether the crash report framework is working as expected.

This comment does not reply the question. Maybe the OP just wants to crash the app to test whether the crash report framework is working as expected.

throwing an exception in objective-c/cocoa - Stack Overflow

objective-c cocoa
Rectangle 27 248

A word of caution here. In Objective-C, unlike many similar languages, you generally should try to avoid using exceptions for common error situations that may occur in normal operation.

Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)"

Apple's conceptual Exception handling documentation explains the same, but with more words: "Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime. [.....] Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the recommended way to communicate expected errors in Cocoa applications."

The reasons for this is partly to adhere to programming idioms in Objective-C (using return values in simple cases and by-reference parameters (often the NSError class) in more complex cases), partly that throwing and catching exceptions is much more expensive and finally (and perpaps most importantly) that Objective-C exceptions are a thin wrapper around C's setjmp() and longjmp() functions, essentially messing up your careful memory handling, see this explanation.

I think this applies to most programming languages: "try to avoid using exceptions for common error situations". The same applies in Java; it's bad practice to handle user input errors (for example) with exceptions. Not just because of resource usage, but also for code clarity.

More importantly, Exceptions in Cocoa are designed to indicate non-recoverable program errors. Doing otherwise is running against the framework and can lead to undefined behaviour. See stackoverflow.com/questions/3378696/iphone-try-end-try/ for details.

"The same applies in Java;" Disagree. You can use checked exceptions in Java just fine for normal error conditions. Of course you wouldn't use Runtime exceptions.

I prefer the Cocoa way (exceptions are for programmer errors only) so I'd prefer to do it in Java as well, but the reality is that you should go with typical practices in an environment, and exceptions for error handling sticks out like a bad smell in Objective-C, but are used a lot for that purpose in Java.

This comment does not reply the question. Maybe the OP just wants to crash the app to test whether the crash report framework is working as expected.

throwing an exception in objective-c/cocoa - Stack Overflow

objective-c cocoa
Rectangle 27 45

It's perfectly fine -- Objective-C is a strict superset of C, so if you want to write plain C, there's nothing preventing you from doing so. In many cases, it's advantageous to use malloc and free to avoid the overhead of the Objective-C runtime.

For example, if you need to dynamically allocate an array of an unknown number of integers, it's often simpler and easier:

int *array = malloc(N * sizeof(int));  // check for NULL return value!
// use array[0]..array[N-1]
...
free(array);
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:N];
// use NSMutableArray methods to do stuff with array; must use NSNumbers instead
// of plain ints, which adds more overhead
...
[array release];

I was working on a word game for the iPhone, and we had to load a multi-megabyte dictionary of valid words. The word list was loaded into one giant char array allocated with malloc(), with some clever optimizations to reduce the memory size even more. Obviously for something like this, the overhead of using an NSArray is completely impractical on the limited iPhone. I don't know exactly what the overhead is, but it's certainly more than one byte per character.

RE: 'strict superset'. While I personally (strongly) agree with you, since we're discussing Apple/iPhone development, this statement is not technically true. Apple defines it thusly: Objective-C syntax is a superset of GNU C/C++ syntax. Strict superset has a very specific meaning, with the unqualified use of superset being the lesser of the two (think "behaves like" vs. "exactly like"). The qualifier of syntax further restricts it to the point where it is almost useless, effectively limiting Apples obligation to Annex A of the C99 spec- a scant 16 pages out of 552 in the standard.

I've had a number of problems using malloc/free in Objective C. See my comment to Nikolai's answer. Apart from that, I've had problems with assigning (copying) pointers to malloced arrays to share the malloced array between objects.

While it's true that you can use malloc() and free(), you can avoid most of the runtime's overhead by using a NSMutableData of appropriate length instead.

Is it ok to use "classic" malloc()/free() in Objective-C/iPhone apps? ...

c objective-c memory-management
Rectangle 27 134

Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:

Thank you but I already know that. I just wonder that my case is legal or not. My case is a little bit difference from documents. :)

Why it is different ? The doc says that it is legal IF the original method is not in a category, but strongly discouraged. Then you can do it...

Is it correct to override in Category method declared and implemented in Category of super class?

Overriding methods using categories in Objective-C - Stack Overflow

objective-c categories
Rectangle 27 971

You should use the arc4random_uniform() function. It uses a superior algorithm to rand. You don't even need to set a seed.

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

Use arc4random_uniform(x) as described below by @yood. It is also in stdlib.h (after OS X 10.7 and iOS 4.3) and gives a more uniform distribution of the random numbers. Usage int r = arc4random_uniform(74);

NB: the distribution from arc4random can be very poor, if you happen to choose a poor range. I hadn't realised the powers-of-two expectation. +1 for use @yood's version - made a noticeable difference for larger numbers (e.g. range of 400)

how does arc4random() 'know' to limit its return values to below the integer on the other side of the modulo operator if it is not being passed into the function?

@codecowboy It doesn't. It always returns an integer in the range [0, (2^32)-1]. It's the modulo that limits the upper-bound of the range to the number you specify.

Generating random numbers in Objective-C - Stack Overflow

objective-c random
Rectangle 27 970

You should use the arc4random_uniform() function. It uses a superior algorithm to rand. You don't even need to set a seed.

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

Use arc4random_uniform(x) as described below by @yood. It is also in stdlib.h (after OS X 10.7 and iOS 4.3) and gives a more uniform distribution of the random numbers. Usage int r = arc4random_uniform(74);

NB: the distribution from arc4random can be very poor, if you happen to choose a poor range. I hadn't realised the powers-of-two expectation. +1 for use @yood's version - made a noticeable difference for larger numbers (e.g. range of 400)

how does arc4random() 'know' to limit its return values to below the integer on the other side of the modulo operator if it is not being passed into the function?

@codecowboy It doesn't. It always returns an integer in the range [0, (2^32)-1]. It's the modulo that limits the upper-bound of the range to the number you specify.

Generating random numbers in Objective-C - Stack Overflow

objective-c random
Rectangle 27 970

You should use the arc4random_uniform() function. It uses a superior algorithm to rand. You don't even need to set a seed.

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

Use arc4random_uniform(x) as described below by @yood. It is also in stdlib.h (after OS X 10.7 and iOS 4.3) and gives a more uniform distribution of the random numbers. Usage int r = arc4random_uniform(74);

NB: the distribution from arc4random can be very poor, if you happen to choose a poor range. I hadn't realised the powers-of-two expectation. +1 for use @yood's version - made a noticeable difference for larger numbers (e.g. range of 400)

how does arc4random() 'know' to limit its return values to below the integer on the other side of the modulo operator if it is not being passed into the function?

@codecowboy It doesn't. It always returns an integer in the range [0, (2^32)-1]. It's the modulo that limits the upper-bound of the range to the number you specify.

Generating random numbers in Objective-C - Stack Overflow

objective-c random
Rectangle 27 970

You should use the arc4random_uniform() function. It uses a superior algorithm to rand. You don't even need to set a seed.

#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
NAME
     arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdlib.h>

     u_int32_t
     arc4random(void);

     void
     arc4random_stir(void);

     void
     arc4random_addrandom(unsigned char *dat, int datlen);

DESCRIPTION
     The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
     bit S-Boxes.  The S-Boxes can be in about (2**1700) states.  The arc4random() function returns pseudo-
     random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
     random(3).

     The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
     arc4random_addrandom().

     There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
     initializes itself.

EXAMPLES
     The following produces a drop-in replacement for the traditional rand() and random() functions using
     arc4random():

           #define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))

Use arc4random_uniform(x) as described below by @yood. It is also in stdlib.h (after OS X 10.7 and iOS 4.3) and gives a more uniform distribution of the random numbers. Usage int r = arc4random_uniform(74);

NB: the distribution from arc4random can be very poor, if you happen to choose a poor range. I hadn't realised the powers-of-two expectation. +1 for use @yood's version - made a noticeable difference for larger numbers (e.g. range of 400)

how does arc4random() 'know' to limit its return values to below the integer on the other side of the modulo operator if it is not being passed into the function?

@codecowboy It doesn't. It always returns an integer in the range [0, (2^32)-1]. It's the modulo that limits the upper-bound of the range to the number you specify.

Generating random numbers in Objective-C - Stack Overflow

objective-c random