I am reading matt's iOS pragraming book, when I read here:
Swift itself is defined in a module — the Swift module. Your code always implicitly imports the Swift module. You could make this explicit by starting a file with the line import Swift; there is no need to do this, but it does no harm either.
That fact is important, because it solves a major mystery: where do things like print come from, and why is it possible to use them outside of any message to any object? print is in fact a function declared at the top level of the Swift module, and your code can see the Swift module’s top-level declarations because it imports Swift. The print function thus becomes, as far as your code is concerned, an ordinary top-level func‐ tion like any other; it is global to your code, and your code can speak of it without specifying its namespace. You can specify its namespace — it is perfectly legal to say things like Swift.print("hello") — but you probably never will, because there’s no name conflict to resolve.
Such as, in my test ViewController:
import UIKit
//import Swift // here we can import Swift. it is okay
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Swift.print("hello, matt") // where we import the Swift ?
}
}
We can use print or Swift.print, I just want to ask, how apple implicitly imports the Swift module ? and obvious, UIKit, we must import, if can implicitly imports Swift module, why there apple do not implicitly imports UIKit?
My confuse is how implicitly imports the Swift module?
The implicit import of the Swift module is a behaviour hard coded into the Swift compiler, exclusively for the Swift module.
Refer to Alexandex's, I finnaly find the doc
And we can see Clang importer:
The Clang importer (implemented in lib/ClangImporter) imports Clang modules and maps the C or Objective-C APIs they export into their corresponding Swift APIs. The resulting imported ASTs can be referred to by semantic analysis.
Related
I've got a framework built in both Objective C and Swift. I've upgraded it from Swift 3 to Swift 4.2, and now, after exporting it through Aggregate target and importing the generated framework inside my Objective C demo app, it doesn't show me any Swift class.
I've already checked if -swift.h is correctly builded, and I can see inside it all Swift classes. However, even if I import the umbrella header inside my demo app, I can't see them.
Thanks
By default Swift generates code that is only available to other Swift code, but if you need to interact with the Objective-C runtime – all of UIKit, for example – you need to tell Swift what to do.
That’s where the #objc attribute comes in: when you apply it to a class or method it instructs Swift to make those things available to Objective-C as well as Swift code. So, any time you want to call a method from a UIBarButtonItem or a Timer, you’ll need to mark that method using #objc so it’s exposed – both of those, and many others, are Objective-C code.
class MyController: UIViewController {
#objc func authenticateUser() {
}
To make this class accessible from Objective-C, we need to add the #objc keyword just before the class declaration. This tells the compiler to do some magic behind the scenes (namely, create an invisible header file)
#objc class SwiftViewController: UIViewController {
// ...
}
Reference - https://www.hackingwithswift.com/example-code/language/what-is-the-objc-attribute
I'm diving into swift from the land of Objective-C, and I'm curious about swift's importing functionality. I've discovered that there's no need to import my own classes, like so:
Objective-C:
#import <UIKit/UIKit.h>
#import "CustomObject.h"
CustomObject* newObject = ...
Swift:
import UIKit
//no need to import CustomObject
var newObject: CustomObject...
My question is, how does swift accomplish this? Where does it look for .swift files to automatically import? Is it just any .swift file that's added to your project's target? I don't want to just handwave this and then get caught by surprise later when something doesn't import like magic!
I'm not sure I'm going to explain this with grace but here it goes...
Let's say you're creating an app called Battlefront. When you're adding files/classes to your application, they are in fact added to your app's module, the Battlefront module. Let's say you created a class called Hero, well, your class is not only Hero, it is Battlefront.Hero but since you're using it in the context of the Battlefront module, there is no need to specify the module name when using your class.
Imports in Swift works mostly with modules. I suppose you could import a single class in Swift but I haven't tried it so I can't comment on this. Let's say you're importing CoreData, well you're importing the whole module by using import CoreData.
By default, classes are using the internal access control. If you wanted to expose classes inside Battlefront to be available to other modules, you'd have to specify your class as public:
// Default is internal, not available outside Battlefront
class Hero {
}
// Public class, is available outside Battlefront
public class Weapon {
}
You can read more on Access Control here.
I suppose you could simplify the relationship to Target equals a Module but that would be taking a shortcut. Could be a start of understanding the concept though.
Short answer: yes, Xcode accesses all .swift files in your project.
As known, it is not possible to include the interface header file from a file in the -Header.h.
My actual problem is that I have the definition of a class one protocol of which is a Swift one:
#protocol arrivingDelegate;
#interface palettaTraffic : NSObject<MKMapViewDelegate, arrivingDelegate> {
}
If I import the *-Swift.h file I get into the ugly cycle when the file is included in another one that is included in the header file.
This is what happens when I use the #protocol directive: it is a warning, but quite a disturbing one.
This is how the swift protocol is defined:
#objc public protocol arrivingDelegate {
func submitManualBusLine(busStripe:StripeProtocol)
}
I also found a similar post:
Swift protocol in Objective-C class
But none of the suggestions seem to apply.
If I import the *-Swift.h file I get into the ugly cycle when the file is included in another one that is included in the header file.
Okay, but that is what you have to do. I don't see you doing it the screen shot above, which is why your protocol is not being seen.
The solution to the "ugly cycle" should be just a matter of tweaking the order in which things are imported in your various Objective-C files.
Adopting swift protocols in Objective-c is a tricky process. I fixed the issue by porting the adopting class to Swift too.
What I tend to do in my projects is putting the protocol conformance of the ObjC class in a Swift file, to avoid this error. Usually the file where the protocol is defined.
extension PalettaTraffic: ArrivingDelegate {}
Why? We're migrating our codebase from ObjC to Swift, but we cannot migrate every class at the same time. Because of this we have a large 'seem' between Swift & ObjC where Swift types need ObjC and vice versa. For me, this is the solution that causes the least amount of work right away.
I have a build error when trying to subclass a custom Objective-C class (a subclass of UIViewController) in Swift.
When I try to subclass in Swift, I get the build errors in the picture below. All of them relate to the use of the word class as an argument in the OCMapper library (where I've opened an issue as well).
Some more notes:
In the project, I both import and use Objective-C code in the Swift code and import and use Swift code in the Objective-C code.
I import the compiled Module-Swift.h only in .m and .mm files and forward declare classes that I need in .h files.
I've attempted to create a Module-Swift-Fixed.h class where I forward declare and/or import the custom Objective-C class headers (as recommended here), but that hasn't made a difference.
Has anyone seen anything like this before or have a solution?
I have as yet not been able to trace where in the language spec this is documented, but I suspect you have come across the same problem that I recently faced in objective-c since moving to Xcode 6.4.
I had a message (method) defined as follows
- (BOOL)canProcessClass:(Class) class {
return [class isSubclassOfClass:[NSSet class]];
}
with the same compile error as you mentioned Expected identifier. The fix was simple - just rename the the class argument to something like classToProcess. Which would give you the following
- (BOOL)canProcessClass:(Class) classToProcess {
return [classToProcess isSubclassOfClass:[NSSet classToProcess]];
}
Hence just rename the arguments in your Swift code to not use the (key)word class and you should be fine.
If anyone can point me to the language spec that documents this I would really appreciate it. As far as I'm aware you shouldn't use Class, but I haven't able to find anything about class except the obvious that it is a message (method) available on classes.
Is #IBAction just a syntactical difference in Swift or does it signify something specific.
Also, similar usage is seen in AppDelegate.swift where #UIApplicationMain is written.
These are attributes in swift.They have some special meaning for compiler.For eg: #UIApplicationMain synthesize main.swift file by compiler as entry point for application.From swift guide
Attributes provide more information about a declaration or type.
There are two kinds of attributes in Swift, those that apply to
declarations and those that apply to types.
NSApplicationMain
Apply this attribute to a class to indicate that it is the application delegate. Using this attribute is equivalent to calling
the NSApplicationMain function and passing this class’s name as the
name of the delegate class.
If you do not use this attribute, supply a main.swift file with a main
function that calls the NSApplicationMain function. For example, if
your app uses a custom subclass of NSApplication as its principle
class, call the NSApplicationMain function instead of using this
attrib
Here is whole list of attributes in swift
From apple swift blog
In Xcode, Mac templates default to including a “main.swift” file, but
for iOS apps the default for new iOS project templates is to add
#UIApplicationMain to a regular Swift file. This causes the compiler
to synthesize a main entry point for your iOS app, and eliminates the
need for a “main.swift” file.
Alternatively, you can link in an implementation of main written in
Objective-C, common when incrementally migrating projects from
Objective-C to Swift.
write code in main.swift.It will work as enty point for application
//main.swift
import Foundation
import UIKit
UIApplicationMain(C_ARGC, C_ARGV,nil, NSStringFromClass(AppDelegate))