2014-06-06 24 views
5

Tôi đang cố viết một ứng dụng để kiểm soát nhanh iTunes. Nhưng khi khởi tạo ứng dụng trả về một đối tượng kiểu AnyObject, nhưng phải iTunesApplication.Khởi tạo đối tượng Swift và scriptingbridge

Đối tượng này không phản hồi với các phương pháp và biến iTunes. Ai biết cách làm cho nó hoạt động?

var iTunes = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes") 

Tiêu đề iTunes.h cũng chứa các lớp mà tôi cần truy cập nhưng không thể. Các lớp này gây ra lỗi biên dịch như thể chúng không nằm trong iTunes.h đã khai báo.

Tại sao điều này xảy ra với tôi vẫn chưa rõ ràng.

Toàn bộ danh sách các lớp được tuyên bố một iTunes.h trong qua @class:

iTunesPrintSettings @class, iTunesApplication, iTunesItem, iTunesAirPlayDevice, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource , iTunesTrack, iTunesAudioCDTrack, iTunesFileTrack, iTunesSharedTrack, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderDanh sách phát, iTunesVisual, iTunesWindow, iTunesBrowserWindow, iTunesEQWindow, iTunesPlaylistWindow;

Ví dụ trong Objective - c bạn sẽ sử dụng một cái gì đó như thế này để có được những ca khúc hiện

iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; 
NSLog(@"Current song is %@", [[iTunes currentTrack] name]); 

Nhưng tôi không thể có được một tương đương trong nhanh chóng để làm việc.

+0

Khi bạn thực hiện 'println (" \ (iTunes.className) ")' nó trả về "ITunesApplication" – markhunte

+0

Lỗi trình biên dịch - "AnyObject không có thành viên có tên className" –

+0

Có. Tôi thấy rằng trong các bài kiểm tra của tôi. Tôi đã chỉ ra rằng mặc dù nó cho rằng lỗi nó được phân loại như là một ITunesApplication. tôi cũng có thể đề nghị bạn thêm chi tiết hơn cho câu hỏi của bạn. về những gì bạn đã cố gắng giải quyết vấn đề này và cách bạn đang nhập tệp iTunes.h, v.v. Tôi biết tôi đã mong chờ xcode cung cấp thêm nó vào tệp nhập tiêu đề nhưng tôi chưa bao giờ có. – markhunte

Trả lời

3

Tôi nghi ngờ rằng vấn đề là tệp iTunes.h không được nhập. Vì vậy, đó là phương pháp mà không được chọn.

Vì vậy, tôi đã tạo tệp -Bridging-Header.h.

Dự án của tôi là tên swiftItunesTest. vì vậy các tập tin -Bridging-Header.h được đặt tên:

swiftItunesTest-Bridging-Header.h

Bên trong này tôi đặt #import "iTunes.h" dòng

Và trong tập tin AppDelegate.swift

import Cocoa 
import Appkit 
import ScriptingBridge 





class AppDelegate: NSObject, NSApplicationDelegate { 

    @IBOutlet var window: NSWindow 


    func applicationDidFinishLaunching(aNotification: NSNotification?) { 
     var iTunes : AnyObject = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes") 

     iTunes.playpause() 


    } 

    func applicationWillTerminate(aNotification: NSNotification?) { 
     // Insert code here to tear down your application 
    } 


} 

các iTunesApplication (iTunes.) bây giờ bắt đầu để chọn lên các phương pháp/chức năng


Dưới đây là ví dụ được cập nhật một chút.

func applicationDidFinishLaunching(aNotification: NSNotification) { 
     let iTunes : AnyObject = SBApplication(bundleIdentifier: "com.apple.iTunes")! 

     iTunes.playpause() 


      guard let currentTrack: AnyObject = iTunes.currentTrack!.name else { 

      print("No Tracks Playing") 
      return 
     } 
      print("\(currentTrack)") 

    } 

    func applicationWillTerminate(aNotification: NSNotification) { 

    } 
+0

@jQwierdy đây là một bài cũ và nhanh chóng đã thay đổi kể từ đó, vì vậy tôi sẽ không ngạc nhiên nếu nó đã ném một lỗi bây giờ nhưng tại thời điểm gửi tất cả làm việc như tôi nhà nước. Tôi đã không chơi nhiều với ScriptingBridge kể từ đó. Chủ yếu là vì tôi không cần và cũng bởi vì nó là một nỗi đau để sử dụng cho tất cả các lý do bài viết này có nguồn gốc. – markhunte

+0

@jQwierdy Tất cả tôi đã làm để có được điều này để làm việc một lần nữa đã thay đổi dòng iTunes Var để: 'để iTunes: AnyObject = SBApplication (bundleIdentifier:" com.apple.iTunes ")!' – markhunte

+0

Bạn đang phải, tôi đã thực hiện một stupid bình luận - Tôi xin lỗi về điều đó. Ngu ngốc của tôi, tôi không hiểu rõ ý nghĩa của AnyObject là loại ID của ObjC - bởi vì điều đó có nghĩa là nó được gõ động. Bất kỳ trình biên dịch của tôi đã ném một lỗi nhưng nó đã được cho một lý do khác nhau. Xin lỗi vì điều đó. Câu trả lời của bạn là tốt. – jQwierdy

7

Trong dự án nhanh chóng của tôi, tôi đã gặp sự cố với việc sử dụng các loại được xác định trong tệp iTunes.h được tạo (lỗi liên kết và như vậy).

Câu trả lời từ markhunte giải thích rằng bạn có thể lấy tham chiếu đến đối tượng ứng dụng. Nhưng ngoài ra, tôi đã nhận được các lỗi biên dịch/liên kết khi cố gắng lấy các cá thể từ đối tượng ứng dụng đó.

Trong dự án nhanh chóng của tôi, tôi đã tạo lớp C wrapper mục tiêu cho thấy các loại iTunes là các kiểu C cơ bản (mảng và từ điển) và cũng thích nghi với các phương thức.

Các lớp nhanh chóng của tôi sử dụng trình bao bọc này thay vì các loại iTunes.

Vì vậy, C wrapper mục tiêu trông như thế này (Redux):

#import "ITunesBridgex.h" 
#import "iTunes.h" 

@interface ITunesBridgex(){ 
    iTunesApplication *_iTunesApplication; 
    iTunesSource* _iTunesLibrary; 
} 
@end 
@implementation ITunesBridgex 

-(id)init { 
    self = [super init]; 
    if (self) { 
     _iTunesApplication = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; 
     NSArray *sources = [_iTunesApplication sources]; 
     for (iTunesSource *source in sources) { 
      if ([source kind] == iTunesESrcLibrary) { 
       _iTunesLibrary = source; 
       break; 
      } 
     } 
    } 
    return self; 
} 

- (NSDictionary*) currentTrack { 
    iTunesTrack* track = _iTunesApplication.currentTrack; 
    if (!track) 
     return nil; 
    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: track.name, @"title", nil]; 
    return dict; 
} 

@end 

và mã nhanh chóng gọi:

import Foundation 
import Cocoa 

class ITunesBridgeSimple { 

    var iTunesBridgex: ITunesBridgex 

    init(){ 
     iTunesBridgex = ITunesBridgex() 
     self.updateFromCurrentTrack() 
    } 
    func updateFromCurrentTrack() { 
     if let track = self.currentTrack { 
      if let title : AnyObject = track.objectForKey("title"){ 
       println("Current track: \(title)") 
      } 
     } 
    } 
} 
2

Tôi đã viết một kịch bản Python để tạo tiêu đề Scripting Bridge và sau đó tự động tạo phiên bản Swift gốc. Bằng cách đó bạn không phải đối phó với việc viết trình bao bọc đầy đủ hoặc thậm chí sử dụng Tiêu đề chuyển tiếp. Ngoài ra, đừng lo lắng về lỗi Linker vì nó hoàn toàn trong Swift. https://github.com/garrett-davidson/SwiftingBridge/

1

Một cách thanh nha để làm việc xung quanh vấn đề này là phải có iTunes khai báo là một SBApplication, sau đó, khi bạn gọi một hàm từ iTunesApplication em, chăn màn iTunes một AnyObject:

(iTunes as AnyObject).play() 

Lưu ý rằng có không có kiểu an toàn nếu bạn làm điều này: bạn có thể gọi bất kỳ hàm nào được khai báo trong bất kỳ tiêu đề Objective-C nào: nó không đảm bảo được triển khai trong một lớp cụ thể và do đó sẽ làm hỏng chương trình.

Các vấn đề liên quan