Why kABPersonPhoneProperty is not visible to swift? - addressbook

In the code below,
import Foundation
import AddressBook
let pty = kABPersonPhoneProperty;
swift flags kABPersonPhoneProperty as a unresolved identifier.
Why it is the case?
I am using XCode Beta3

Related

Strange behavior of Obj-C Bridging Header and main function

I converted my app long ago from Obj-C to Swift. During conversion, I needed a Bridging-Header file.
Now I realized that this file is still defined for one target, although the project uses now only Swift files.
Thus I thought I can simply delete Target/Build Settings/Objective-C Bridging Header.
However, the project then no longer builds.
The bridging header file contains (for historical reasons, since I used earlier the Obj-C version of the StoreKit, but no longer) only a single entry:
#import <StoreKit/StoreKit.h>
If this entry is out commented, I get the error
Cannot find 'UIApplicationMain' in scope
in my main file that contains essentially only
let appDelegateClassName: String?
if !ProcessInfo.processInfo.isTesting {
// No unit test. Use the normal app delegate.
appDelegateClassName = NSStringFromClass(AppDelegate.self)
} else {
// Unit test. No app delegate is used.
appDelegateClassName = nil
}
let args = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, appDelegateClassName)
I assume, I don't need a Bridging-Header, if I don't have any Obj-C files. So why do I get this error when I simply out comment #import <StoreKit/StoreKit.h>? And how do I get rid of all old Obj-C traces?
UIApplicationMain is defined in the UIKit framework, so you need to add
import UIKit
to the main.swift file. With
#import <StoreKit/StoreKit.h>
in the bridging header file it happens to compile because StoreKit.h includes SKOverlay.h, which in turn includes UIKit.h (when compiled for iOS).

Xcode 8 beta 6: main.swift won't compile

We have a custom UIApplication object, so our main.swift was
import Foundation
import UIKit
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(MobileUIApplication), NSStringFromClass(AppDelegate))
and that didn't work in Xcode 8 beta 5 so we used this
//TODO Swift 3 workaround? https://forums.developer.apple.com/thread/46405
UIApplicationMain( Process.argc, UnsafeMutablePointer<UnsafeMutablePointer<CChar>>(Process.unsafeArgv), nil, NSStringFromClass(AppDelegate.self))
On Xcode 8 beta 6 we get Use of unresolved identifier 'Process'
What do we need to do in Xcode 8 beta 6/Swift 3 to define the UIApplicationMain?
I write it this way:
UIApplicationMain(
CommandLine.argc,
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(
to: UnsafeMutablePointer<Int8>.self,
capacity: Int(CommandLine.argc)),
nil,
NSStringFromClass(AppDelegate.self)
)
To change the UIApplication class, substitute NSStringFromClass(MobileUIApplication.self) for nil in that formulation.
However, if your only purpose here is to substitute a UIApplication subclass as the shared application instance, there's an easier way: in the Info.plist, add the "Principal class" key and set its value to the string name of your UIApplication subclass, and mark your declaration of that subclass with an #objc(...) attribute giving it the same Objective-C name.
EDIT This problem is now solved in Swift 4.2. CommandLine.unsafeArgv now has the correct signature, and one can call UIApplicationMain easily:
UIApplicationMain(
CommandLine.argc, CommandLine.unsafeArgv,
nil, NSStringFromClass(AppDelegate.self)
)
It seems Process has been renamed to CommandLine in beta 6.
CommandLine
But the type of CommandLine.unsafeArgv is mismatching the second argument of UIApplication, so you may need to write something like this:
CommandLine.unsafeArgv.withMemoryRebound(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc)) {argv in
_ = UIApplicationMain(CommandLine.argc, argv, NSStringFromClass(MobileUIApplication.self), NSStringFromClass(AppDelegate.self))
}
(UPDATE)This mismatching should be considered as a bug. Generally, you'd better send a bug report when you find "this-should-not-be" things, like the third parameter in beta 5. I hope this "bug" will be fixed soon.
If you just want to designate your custom UIApplication class, why don't you use Info.plist?
NSPrincipalClass | String | $(PRODUCT_MODULE_NAME).MobileUIApplication
(Shown as "Principal class" in non-Raw Keys/Values view.)
With this in your Info.plist, you can use your MobileUIApplication with normal way using #UIApplicationMain.
(ADDITION) Header doc of UIApplicationMain:
// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no
// NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init.

Swift : import UIKit in each subclass?

In objective-C we can do like this:
a. Importing a file in super class
#import "MyAwesomeClass.h"
#interface MySuperViewController : UIViewController
#end
#implementation MySuperViewController
- (void)viewDidLoad {
[super viewDidLoad];
//MyAwesomeClass allocated, initialized, used
MyAwesomeClass *awesomeClass = [MyAwesomeClass new];
}
#end
b. Using the file imported in superclass, in subclass without re-importing it
#interface MySubViewController : MySuperViewController
#end
#implementation MySubViewController
- (void)viewDidLoad {
[super viewDidLoad];
//No compilation error, since MyAwesomeClass already imported in superclass
MyAwesomeClass *awesomeClass = [MyAwesomeClass new];
}
#end
Trying to do the same thing in swift gives compilation error:
a. importing UIKit in MySuperViewController
import UIKit
class MySuperViewController : UIViewController {
#IBOutlet weak var enterPrice: UITextField!
}
b. Declaring and using an object of UITextField without importing UIKit in MySubViewController
class MySubViewController: MySuperViewController {
// compilation error at below line
#IBOutlet weak var myButton: UIButton!
}
Is there any way we can avoid re-importing UIKit in above scenario? Please suggest.
Short answer:
Yes. It's my understanding that you need to import all the frameworks you need in each Swift file in your project (it is a file-by-file requirement, not class by class. If you define 2 classes in a single file, you only need one import at the top of the file.)
The #import/#include statements in C are preprocessor directives. It is as if the code in the included file is copy/pasted at the location of the include. If you include a header in your superclass's header, the superclass's header now contains the expanded contents. So when you include the superclass header in your subclass, the system framework headers are included as part of the superclass header.
Swift works a little differently.
If you use any objective-C class in your Swift project and import UIKit in that class, you don't actually have to use the import UIKit directive anywhere else in your project!
So basically:
Drag and drop your objective-C .m and/or .h file into your project. Choose copy files if necessary. Make sure all the dependencies are sorted for that file.
(optional) Xcode should prompt you to create a bridging header, if it does, move on to step 4... But if it doesn't, you have to add a header file and call it YourProjectName-Bridging-Header.h.
(optional) If you manually added it, go into Project Settings and search for Swift Compiler. In the General section, there is a place to put the path to the file you just created.
In the bridging header import the objective-c class(es) to your project by doing #import "MyClass.h"
That's it! You are now free to delete your import UIKit statements from every file. It's worth noting that stylistically and for code reuse purposes, it's better to have all of the imports in every file so everyone can see at a glance what dependencies there are, but when you are creating ViewControllers and such I think it's kind of silly to have to import UIKit in every single file. Everyone knows it has a dependency on UIKit and chances are you won't be reusing the UI in another project anyway.

NSStringFromPoint disappears under Objective-C++

The function NSStringFromPoint disappears when I compile my code using objective-C++, but it's fine under objective-C.
How can I make objective-C++ see that function?
If I compile under Objective-C++ it says:
error: 'NSStringFromPoint' was not declared in this scope
error: 'NSStringFromRect' was not declared in this scope
error: 'NSEqualSizes' was not declared in this scope
Someone can correct me if I'm wrong, but if you're linking against the iPhone SDK, there is no NSPoint or NSStringFromPoint. UIKit uses the Core Graphics structs CGPoint, CGSize and CGRect. The equivalent function would be NSStringFromCGPoint.
The Simulator libraries do not quite match up with the iPhone libraries -- I'm fairly certain applications compiled for the simulator link against the Mac's own Foundation.framework. For example, I wasted a lot of time in the pre-2.0 days thinking that NSXMLDocument was available on iPhone because it compiled and ran in the simulator.
I compiled this simple application:
#include <Cocoa/Cocoa.h>
int main (void)
{
NSLog (#"%#", NSStringFromPoint(NSMakePoint(10, 10));
return 0;
}
Using this command line:
gcc -x objective-c++ test.mm -framework Cocoa -lstdc++
And I got this output (ignoring the error about no autorelease pool in place):
2010-05-12 12:41:33.946 a.out[290:10b] {10, 10}
Make sure you're including the right headers, at the very least, make sure you're importing <Foundation/Foundation.h>. An explicit #import <Foundation/Foundation.h> will do no harm if it has already been included.

ABPersonRef - usage

Trying to create a object for ABPersonRef
example:
ABpersonRef ref;
have included Addressbook and AddressBookUI framework
even then when i compile it states 'ABPersonRef' Undeclared Identifier
Have you added imports to your source file?
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
Edit: I've read your question more carefully. There's no ABPersonRef type (at least public) in iPhone SDK. You should work with ABRecordRef type which is generic for both person and group records - as you can see all AB*** methods work with ABRecordRef type.
You will also need to link against AddressBook framework and
#import <AddressBook/AddressBook.h>