I have a need to create a packaging of UI classes that can be included in an XCode4 integration project by a developer and then get instantiated through the use of a config file in conjunction with NSClassFromString - a static plugin. I have had success with creating libraries that contain UIViews that layout based on code. Now I am trying to allow the developer to create UIs based on xib files and other resources. I am implementing the most basic version of this...a UIViewController loading a xib file created directly through the "new file" wizard in XCode4. The only modification I am making is adding a label to the UI in the xib.
I am having problems getting the xib loaded. If I include the xib in the integration project all is well. When I create the UIViewController from the library it finds the xib in the root of the app bundle and loads it. However, this is very cumbersome during the build of the integration project, I would like to be able to just link to the library and not have to add each xib to the integration project individually. Additionally the use of the root of the application bundle is bad because there is no directory structure that could facilitate multiple static plugins. I have tried creating a folder that the integration project can include during its build and the xibs for the static plugin can just be dumped into folder prior to build. If I do this the xib gets into the app bundle but when the UIViewController class loads up it cannot find the xibs. I have been unable to code a solution to get the UIViewController to initWithNibName:bundle: properly when the xibs are in the sub-folder.
My last attempt has been to create a static framework using this article: http://simplyitinc.blogspot.com/2011/04/creating-static-framework-in-xcode-4.html . That seems to get me a framework I can link against and the xib is in that framework directory but ... the xib does not get placed into the app bundle when I link against the framework. My classes are available but fail to load the xib, obviously because it is not in the app bundle.
Any suggestion on how this requirement might be accomplished?
Related
basically I have some Objective-c class already existing and I want to use them in my NativeScript projet. Currently I have added those files to the Xcode project target and I want to be able to call my objective-c code from nativeScript js. I've read the doc but I don't understand it. It seems so complicated. basically currently all I want to do is be able to present my custom view controller by calling probably something along
const vc = MyCustomViewController.alloc.initWithNibName("xib file")
page.frame.ios.controller.present(vc,true, nil)
Am I obligated to create a plugin for that? Am I obligated to use my objective-c class to build a framework in Xcode and then import the framework?
So I found out.
Actually what you need to do is first to compile your native iOS code into a framework. As per the documentation all your classes must inherit NSObject and all your function must be marked with #objc to be exposed to the objective-c Nativescript side if you write in swift. You will notice as well that in a framework your bundle is not the main bundle. In this example you can see how you can retrieve the bundle from the framework and load a xib from it.
Then you need to add your framework file to a Nativescript plugin. For that, you want to add the framework to the plugin's iOS folder yourPlugin/platform/iOS/yourFramework.framework.
then, you need to add your plugin to your app. You can add your local plugin by using the next command line. Notice the path end with the /src folder.
tns plugin add /path/to/yourplugin/src
Now, you can then call your native functions and classes without even importing them. Of course this works only on iOS. If you run your app on android, calling those methods will crash.
To show this viewController on your Nativescript side you will need to call the following code. By the way You can find documentation elsewhere to get a reference to the current page or frame object.
const controller = page.frame.ios.controller
const vc = IOMediaViewController.create()
vc.modalPresentationStyle = UIModalPresentationFullScreen
controller.presentViewControllerAnimatedCompletion(vc,true,null)
I watched the "What's New in Interface Builder" session video and tried to replicate the code that was showed but unfortunately when I assign a view to my custom class which has #IBDesignable I get 2 errors:
Main.storyboard: error: Live Views: Failed to update auto layout status: The bundle “swiftTest” couldn’t be loaded because its executable isn’t loadable.
Main.storyboard: error: Live Views: Failed to render instance of _TtC9swiftTest14ControllerView: The bundle “swiftTest” couldn’t be loaded because its executable isn’t loadable.
Later on in the video I saw that to have Live Views you have to make these steps:
1. Create framework
2. Create class
3. Mark as designable
How do I make the 1st step?
Thanks
As I understand it at the moment (prior to Xcode 6 Beta 3), #IBDesignable will only work from a view declared in a separate framework target.
However, I also struggled to add it because I had no "plus" button as described in various links (because the Hide Project & Target Lists arrow option was toggled off).
So, select your current project target, then just use the xcode menu options:
Editor > Add target...
Then select
Framework & Library > Cocoa Touch Framework etc.
By the way, to test #IBDesignable, this tutorial worked perfectly as a starting point:
http://www.weheartswift.com/make-awesome-ui-components-ios-8-using-swift-xcode-6/
One small but important thing to note in that tutorial (if you follow it onscreen instead of following on to its full github code listing) is that your view class must be prepended/decorated with #IBDesignable, e.g.
class CustomView : UIView {...}
should be
#IBDesignable class CustomView : UIView {...}
You should make new framework as a target for current project and add your live views in this framework. On General tab on main target you will see your framework in Embedded Binaries section.
I had a project with live views working and at one point I also had these error messages. This went away for me when closing XCode and restarting, fwiw.
It is working very well (and easily) for me with Swift in Xcode 6 Beta 5.
I've confirmed that with Xcode 6 Beta 5 I did not need to add any frameworks (for example, Cocoa Touch framework option under frameworks in the dialog that appears when adding a new project target). Nor did I need to add IBDesignable.h to the project. Both seem to be outdated requirements as per the the weheartswift.com write-up linked in the initial answer to the question.
All I needed to do was:
Prefix class definition of my custom Swift class source file
with keyword #IBDesignable
Prefix vars I wanted to show up in IB Attributes Inspector with #IBInspectable (IB recognizes several common variable types).
Then, after assigning my custom component's (UIControl subclass) name to IB's "Class" name file (under Identity Inspector tab, in right pane) replacing "UIView" -- e.g. the class name of the UIView placeholder object I originally dragged onto the IB VC's view -- upon selecting my custom component from the Content View component list in IB, I saw all my custom class' inspectable items show up in the IB Attributes Inspector!! Very cool.
Note: At first XCode would only allow me to prefix one variable with #IBInspectable. It showed errors on subsequent ones. Then, suddenly it seemed to work, and no more problems after that. Not sure if it was a typo or just took Xcode awhile to re-index my project and pre-compile or parse the code.
I code about #IBDesignable & #IBInspectable,
firstly, I got two errors like you,
then, I change the code I wrote,
you can checkout the code from my github
Good Luck.
Currently I'm working on a product that uses the Cappuccino Framework and the Objective-J language.
I created my project using this command after installing Cappuccino: capp gen -t NibApplication Myapp
The Problem I'm facing is that I want to keep my code and GUI clean.
By doing so I wanted to split the GUI up in separate Xib / Cib (compiled version Cappuccino can read) and separate controllers, like I do with iOS and Mac apps.
I couldn't find on the internet or on the docs how to do so.
Also, all the examples (including the NibApplication template) contains only 1 xib file.
In short what I'm after is to load a controller, based on a XIB file which holds the window. All the outlets are connected to the controller I loaded.
Is there anyone who knows how to do it?
Thanks in advance and have a nice day!
The typical way to do this is to use a CPWindowController or a CPViewController for each xib you want to load. Here's what it might look like:
var myViewController = [[CPViewController alloc] initWithCibName:"mynib" bundle:[CPBundle mainBundle]];
This would load Resources/mynib.cib from your main bundle. Normally you'd also subclass CPViewController so as to give yourself a convenient spot for your control code.
Fixed it myself! I used this tutorial: http://vimeo.com/8948460
But instead of using atlas I used XCode. Just follow the steps but with XCode and you'll be fine if you want the above to happen.
The project I was toying around with for some reason was a dated version of cocos2d, and the classes and methods I was trying to introduce were too recent. So, I have successfully installed the new cocos2d, and have created a cocos2d template in Xcode. My issue is that this project is brand new, and I want to bring all my other project's code into this.
I have searched this across other stackoverflow threads, and just dragged the files/folder into the new project. When the files wouldn't transfer, I adjusted their path, and then dragged them in, or in one unique case, when dealing with the class main.m, I just changed its internal code so that it would sync up with the rest of the code.
However, because this is a template file, there are some extra baggage classes that I am not sure how to handle. These classes are the classes that come standard in the 'Classes' folder when the cocos2d template is first created:
GameConfig.h
HelloWorldLayer.h
HelloWorldLayer.m
RootViewController.h
RootViewController.m
MyGameAppDelegate.h
MyGameAppDelegate.m
And then in the 'Other Sources' folder:
MyGame_Prefix.pch
These classes or their likeness does not appear to be used in the original project from which I copied the other classes, is there any special use for them that would be dangerously stupid for me to delete them?
You can delete HelloWorldLayer. It's just the example scene/layer.
You would do well to leave the other files in. Any modifications you may have made to your old project's app delegate (such as which scene is passed to CCDirector's runWithScene method) should be re-done in the MyGameAppDelegate rather than replacing that with your old project's app delegate.
The reason is that the startup sequence for cocos2d has changed to support Retina devices, autorotation, changes in the iOS SDK, etc. The RootViewController handles autorotation, should you need that. Whether autorotation is enabled or not can be changed via GameConfig.h.
I've just purchased a Mac and am beginning to explore software development using Cocoa and Objective-C using XCode in Snow Leaped having come from a strong Microsoft and C# backgrund
All of the documentation and tutorials I have read use Interface Builder and XCode to create applications with user interfaces. My current understanding is that objects created by Interface Builder are in some way defined in an .xib file and created at runtime.
A bundle contains code and resources that accompany it. Is it right to say that an .xib file is in fact a bundle that contains UI resources and that this bundle is loaded (is that the correct verb?) at runtime and object instances are created?
If the abive is true is there any way I can see the code generated by Interface Builder and the point in code where these objects are created, without seeing this at least once I feel like there is a lot of "magic" happening and that isn't helping me at this stage of my learning.
Is there anything I should be reading to grasp the apparent paradigm-shift between C# / WinForms and Objective-C / Mac OS / Cocoa?
Is it right to say that an .xib file is in fact a bundle that contains UI resources and that this bundle is loaded (is that the correct verb?) at runtime and object instances are created?
No. A bundle is one of several specific directory structures, and a xib file is a regular file, not a directory.
A xib file contains descriptions of objects. When you compile the nib (usually as part of building your app), the nib compiler reads in the xib, creates the objects as described therein, and archives them into a nib, which isn't a bundle either.
When you load the nib in your application, the nib loader unarchives the objects and ensures all outlets are connected as they were in IB between its objects and to and from the File's Owner.
Don't worry about implementation details. Nibs Just Work. All you have to do is:
Create xib files. If you use version control, these are what you tell it to track.
Make sure they're in .lproj folders (so that localizers can create localized versions of them).
Let Xcode handle the rest.
The key thing to realize is that there isn't any code in the normal sense...at least, nib/xib UI resources are not simply contruscts of objective-c code that are merely generated by the Inteface Builder.
These are objects that are sort of "frozen" in the nibs and "unfrozen" when needed by the apps (or awakened, I guess, as the awakeFromNib would suggest). They are archived in xml/plist/etc form, rather than being a framework for generating objective-c source code.
Consider them objects that have been serialized as xml or other data.